Merge remote-tracking branch 'origin/main' into query-history-app
This commit is contained in:
+1
-1
@@ -799,7 +799,7 @@ playwright.storybook.config.ts @grafana/grafana-frontend-platform
|
||||
/public/app/core/components/ColorScale/ @grafana/dataviz-squad
|
||||
/public/app/core/components/DynamicImports/ @grafana/grafana-search-navigate-organise
|
||||
/public/app/core/components/EmptyListCTA/ @grafana/grafana-frontend-platform
|
||||
/public/app/core/components/FolderFilter/ @grafana/sharing-squad
|
||||
/public/app/core/components/FolderFilter/ @grafana/grafana-search-navigate-organise
|
||||
/public/app/core/components/Footer/ @grafana/grafana-search-navigate-organise
|
||||
/public/app/core/components/ForgottenPassword/ @grafana/grafana-search-navigate-organise
|
||||
/public/app/core/components/Form/ @grafana/grafana-frontend-platform
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
private_key: ${{ fromJSON(steps.secrets.outputs.secrets).APP_PEM }}
|
||||
|
||||
- name: Download PR info artifact
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
id: download-pr-info
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
|
||||
@@ -141,12 +141,12 @@ jobs:
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Get built packages from pr
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: buildPr
|
||||
|
||||
- name: Get built packages from base
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: buildBase
|
||||
|
||||
@@ -225,7 +225,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: 'Download artifact'
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: levitate
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ jobs:
|
||||
with:
|
||||
registry: 'us-docker.pkg.dev'
|
||||
environment: 'dev'
|
||||
- uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c
|
||||
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
|
||||
with:
|
||||
name: grafana-docker-tar-gz
|
||||
path: .
|
||||
@@ -221,10 +221,10 @@ jobs:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: grafana-tar-gz
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: ${{ needs.build-e2e-runner.outputs.artifact }}
|
||||
- name: chmod +x
|
||||
@@ -298,7 +298,7 @@ jobs:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: grafana-tar-gz
|
||||
- name: Run E2E tests
|
||||
@@ -360,7 +360,7 @@ jobs:
|
||||
run: |
|
||||
docker cp cpp-e2e-deploy:/outputs.json /tmp/outputs.json
|
||||
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: grafana-tar-gz
|
||||
|
||||
@@ -400,7 +400,7 @@ jobs:
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Download blob reports from GitHub Actions Artifacts
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
path: blobs
|
||||
pattern: playwright-blob-*
|
||||
@@ -479,7 +479,7 @@ jobs:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: grafana-tar-gz
|
||||
- name: Run PR a11y test
|
||||
@@ -531,7 +531,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: yarn install --immutable
|
||||
- name: Get pa11y results
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: pa11y-ci-results
|
||||
- name: Extract and publish metrics
|
||||
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
permissions:
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c
|
||||
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
|
||||
with:
|
||||
name: ${{ inputs.name }}
|
||||
pattern: ${{ inputs.pattern }}
|
||||
|
||||
@@ -224,27 +224,27 @@ jobs:
|
||||
- build
|
||||
steps:
|
||||
- uses: grafana/shared-workflows/actions/dockerhub-login@dockerhub-login/v1.0.2
|
||||
- uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c
|
||||
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
|
||||
with:
|
||||
name: artifacts-list-linux-amd64
|
||||
path: .
|
||||
- uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c
|
||||
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
|
||||
with:
|
||||
name: artifacts-list-linux-arm64
|
||||
path: .
|
||||
- uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c
|
||||
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
|
||||
with:
|
||||
name: artifacts-list-linux-armv7
|
||||
path: .
|
||||
- uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c
|
||||
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
|
||||
with:
|
||||
name: artifacts-linux-amd64
|
||||
path: dist
|
||||
- uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c
|
||||
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
|
||||
with:
|
||||
name: artifacts-linux-arm64
|
||||
path: dist
|
||||
- uses: actions/download-artifact@4a24838f3d5601fd639834081e118c2995d51e1c
|
||||
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
|
||||
with:
|
||||
name: artifacts-linux-armv7
|
||||
path: dist
|
||||
|
||||
@@ -31,6 +31,6 @@ jobs:
|
||||
persist-credentials: false
|
||||
fetch-depth: ${{ steps.fetch_depth.outputs.fetch_depth }}
|
||||
- name: Trufflehog
|
||||
uses: trufflesecurity/trufflehog@ad6fc8fb446b8fafbf7ea8193d2d6bfd42f45690 # v3.90.11
|
||||
uses: trufflesecurity/trufflehog@b84c3d14d189e16da175e2c27fa8136603783ffc # v3.90.12
|
||||
with:
|
||||
extra_args: --results=verified
|
||||
|
||||
+4
-1
@@ -250,9 +250,12 @@ public/mockServiceWorker.js
|
||||
/e2e-playwright/test-plugins/*/dist
|
||||
/apps/provisioning/cmd/job-controller/bin/
|
||||
|
||||
|
||||
# Ignore unified storage kv store files
|
||||
/grafana-kv-data
|
||||
|
||||
# Ignore debug output from test library
|
||||
/pkg/storage/secret/metadata/testdata/rapid/TestStateMachine/
|
||||
|
||||
/codeowners-manifest/
|
||||
|
||||
# Ignore grafana/hippocampus local cache folder
|
||||
|
||||
+3
-1
@@ -2,7 +2,9 @@
|
||||
|
||||
Thank you for your interest in contributing to Grafana! We welcome all people who want to contribute in a healthy and constructive manner within our community. To help us create a safe and positive community experience for all, we require all participants to adhere to the [Code of Conduct](CODE_OF_CONDUCT.md).
|
||||
|
||||
This document is a guide to help you through the process of contributing to Grafana. Be sure to check out the [Grafana Champions program](https://grafana.com/community/champions/?src=github&camp=community-cross-platform-engagement) as you start to contribute. It’s designed to recognize and empower individuals who are actively contributing to the growth and success of the Grafana ecosystem.
|
||||
This document is a guide to help you through the process of contributing to Grafana. Be sure to check out the [Grafana Champions program](https://grafana.com/community/champions/?src=github&camp=community-cross-platform-engagement) as you start to contribute. It's designed to recognize and empower individuals who are actively contributing to the growth and success of the Grafana ecosystem.
|
||||
|
||||
> **Help us improve!** We'd love to hear about your contributor experience. Take a moment to share your feedback in our [Open Source Contributor Experience Survey](https://gra.fan/ome). Your input helps us make contributing to Grafana better for everyone.
|
||||
|
||||
Whether you're a new contributor or a seasoned veteran, we hope these resources help you connect with the community.
|
||||
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ ARG JS_SRC=js-builder
|
||||
FROM alpine:3.22.2 AS alpine-base
|
||||
FROM ubuntu:22.04 AS ubuntu-base
|
||||
FROM golang:1.25.3-alpine AS go-builder-base
|
||||
FROM --platform=${JS_PLATFORM} node:22-alpine AS js-builder-base
|
||||
FROM --platform=${JS_PLATFORM} node:24-alpine AS js-builder-base
|
||||
# Javascript build stage
|
||||
FROM --platform=${JS_PLATFORM} ${JS_IMAGE} AS js-builder
|
||||
ARG JS_NODE_ENV=production
|
||||
|
||||
@@ -178,7 +178,7 @@ gen-apps: do-gen-apps gofmt ## Generate code for Grafana App SDK apps and run go
|
||||
@if [ -n "$$CODEGEN_VERIFY" ]; then \
|
||||
echo "Verifying generated code is up to date..."; \
|
||||
if ! git diff --quiet; then \
|
||||
echo "Error: Generated apps code is not up to date. Please run 'make gen-apps' to regenerate."; \
|
||||
echo "Error: Generated code is not up to date. Please run 'make gen-apps', 'make gen-cue', and 'make gen-jsonnet' to regenerate."; \
|
||||
git diff --name-only; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
The open-source platform for monitoring and observability
|
||||
|
||||
[](LICENSE)
|
||||
[](https://drone.grafana.net/grafana/grafana)
|
||||
[](https://goreportcard.com/report/github.com/grafana/grafana)
|
||||
|
||||
Grafana allows you to query, visualize, alert on and understand your metrics no matter where they are stored. Create, explore, and share dashboards with your team and foster a data-driven culture:
|
||||
@@ -36,6 +35,8 @@ If you're interested in contributing to the Grafana project:
|
||||
- Explore our [beginner-friendly issues](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22).
|
||||
- Look through our [style guide and Storybook](https://developers.grafana.com/ui/latest/index.html).
|
||||
|
||||
> Share your contributor experience in our [feedback survey](https://gra.fan/ome) to help us improve.
|
||||
|
||||
## Get involved
|
||||
|
||||
- Follow [@grafana on X (formerly Twitter)](https://x.com/grafana/).
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@ require (
|
||||
github.com/dolthub/go-icu-regex v0.0.0-20250327004329-6799764f2dad // indirect
|
||||
github.com/dolthub/go-mysql-server v0.19.1-0.20250410182021-5632d67cd46e // indirect
|
||||
github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71 // indirect
|
||||
github.com/dolthub/vitess v0.0.0-20250410090211-143e6b272ad4 // indirect
|
||||
github.com/dolthub/vitess v0.0.0-20250930230441-70c2c6a98e33 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
|
||||
+2
-2
@@ -383,8 +383,8 @@ github.com/dolthub/go-mysql-server v0.19.1-0.20250410182021-5632d67cd46e h1:7pAt
|
||||
github.com/dolthub/go-mysql-server v0.19.1-0.20250410182021-5632d67cd46e/go.mod h1:KZyoO3jngyZCLyCf100FEQTrwAHj33AIMj4Zv4u3MNE=
|
||||
github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71 h1:bMGS25NWAGTEtT5tOBsCuCrlYnLRKpbJVJkDbrTRhwQ=
|
||||
github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71/go.mod h1:2/2zjLQ/JOOSbbSboojeg+cAwcRV0fDLzIiWch/lhqI=
|
||||
github.com/dolthub/vitess v0.0.0-20250410090211-143e6b272ad4 h1:LGTt2LtYX8vaai32d+c9L0sMcP+Dg9w1kO6+lbsxxYg=
|
||||
github.com/dolthub/vitess v0.0.0-20250410090211-143e6b272ad4/go.mod h1:1gQZs/byeHLMSul3Lvl3MzioMtOW1je79QYGyi2fd70=
|
||||
github.com/dolthub/vitess v0.0.0-20250930230441-70c2c6a98e33 h1:ScHTwNbcVC6JH1OSyXzj8S4w67BIpRXwTSjrac3/PSw=
|
||||
github.com/dolthub/vitess v0.0.0-20250930230441-70c2c6a98e33/go.mod h1:8pvvk5OLaLN9LLxghyczUapn/97l+mBgIb10qC1LG84=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
include ../../sdk.mk
|
||||
|
||||
.PHONY: generate
|
||||
generate: do-generate ## Run Grafana App SDK code generation
|
||||
|
||||
.PHONY: do-generate
|
||||
do-generate: install-app-sdk update-app-sdk
|
||||
@$(APP_SDK_BIN) generate --grouping=group --gogenpath=./pkg/apis --defencoding=yaml --postprocess
|
||||
.PHONY: generate # Run Grafana App SDK code generation
|
||||
generate: install-app-sdk update-app-sdk
|
||||
@$(APP_SDK_BIN) generate \
|
||||
--source=./kinds/ \
|
||||
--gogenpath=./pkg/apis \
|
||||
--grouping=group \
|
||||
--genoperatorstate=false \
|
||||
--defencoding=none
|
||||
|
||||
-19
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type ReceiverClient struct {
|
||||
@@ -76,24 +75,6 @@ func (c *ReceiverClient) Patch(ctx context.Context, identifier resource.Identifi
|
||||
return c.client.Patch(ctx, identifier, req, opts)
|
||||
}
|
||||
|
||||
func (c *ReceiverClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus ReceiverStatus, opts resource.UpdateOptions) (*Receiver, error) {
|
||||
return c.client.Update(ctx, &Receiver{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: ReceiverKind().Kind(),
|
||||
APIVersion: GroupVersion.Identifier(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Namespace: identifier.Namespace,
|
||||
Name: identifier.Name,
|
||||
},
|
||||
Status: newStatus,
|
||||
}, resource.UpdateOptions{
|
||||
Subresource: "status",
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *ReceiverClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
|
||||
return c.client.Delete(ctx, identifier, opts)
|
||||
}
|
||||
|
||||
+1
-27
@@ -21,8 +21,6 @@ type Receiver struct {
|
||||
|
||||
// Spec is the spec of the Receiver
|
||||
Spec ReceiverSpec `json:"spec" yaml:"spec"`
|
||||
|
||||
Status ReceiverStatus `json:"status" yaml:"status"`
|
||||
}
|
||||
|
||||
func (o *Receiver) GetSpec() any {
|
||||
@@ -39,15 +37,11 @@ func (o *Receiver) SetSpec(spec any) error {
|
||||
}
|
||||
|
||||
func (o *Receiver) GetSubresources() map[string]any {
|
||||
return map[string]any{
|
||||
"status": o.Status,
|
||||
}
|
||||
return map[string]any{}
|
||||
}
|
||||
|
||||
func (o *Receiver) GetSubresource(name string) (any, bool) {
|
||||
switch name {
|
||||
case "status":
|
||||
return o.Status, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
@@ -55,13 +49,6 @@ func (o *Receiver) GetSubresource(name string) (any, bool) {
|
||||
|
||||
func (o *Receiver) SetSubresource(name string, value any) error {
|
||||
switch name {
|
||||
case "status":
|
||||
cast, ok := value.(ReceiverStatus)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot set status type %#v, not of type ReceiverStatus", value)
|
||||
}
|
||||
o.Status = cast
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("subresource '%s' does not exist", name)
|
||||
}
|
||||
@@ -233,7 +220,6 @@ func (o *Receiver) DeepCopyInto(dst *Receiver) {
|
||||
dst.TypeMeta.Kind = o.TypeMeta.Kind
|
||||
o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
|
||||
o.Spec.DeepCopyInto(&dst.Spec)
|
||||
o.Status.DeepCopyInto(&dst.Status)
|
||||
}
|
||||
|
||||
// Interface compliance compile-time check
|
||||
@@ -305,15 +291,3 @@ func (s *ReceiverSpec) DeepCopy() *ReceiverSpec {
|
||||
func (s *ReceiverSpec) DeepCopyInto(dst *ReceiverSpec) {
|
||||
resource.CopyObjectInto(dst, s)
|
||||
}
|
||||
|
||||
// DeepCopy creates a full deep copy of ReceiverStatus
|
||||
func (s *ReceiverStatus) DeepCopy() *ReceiverStatus {
|
||||
cpy := &ReceiverStatus{}
|
||||
s.DeepCopyInto(cpy)
|
||||
return cpy
|
||||
}
|
||||
|
||||
// DeepCopyInto deep copies ReceiverStatus into another ReceiverStatus object
|
||||
func (s *ReceiverStatus) DeepCopyInto(dst *ReceiverStatus) {
|
||||
resource.CopyObjectInto(dst, s)
|
||||
}
|
||||
|
||||
-19
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type RoutingTreeClient struct {
|
||||
@@ -76,24 +75,6 @@ func (c *RoutingTreeClient) Patch(ctx context.Context, identifier resource.Ident
|
||||
return c.client.Patch(ctx, identifier, req, opts)
|
||||
}
|
||||
|
||||
func (c *RoutingTreeClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus RoutingTreeStatus, opts resource.UpdateOptions) (*RoutingTree, error) {
|
||||
return c.client.Update(ctx, &RoutingTree{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: RoutingTreeKind().Kind(),
|
||||
APIVersion: GroupVersion.Identifier(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Namespace: identifier.Namespace,
|
||||
Name: identifier.Name,
|
||||
},
|
||||
Status: newStatus,
|
||||
}, resource.UpdateOptions{
|
||||
Subresource: "status",
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *RoutingTreeClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
|
||||
return c.client.Delete(ctx, identifier, opts)
|
||||
}
|
||||
|
||||
+1
-27
@@ -21,8 +21,6 @@ type RoutingTree struct {
|
||||
|
||||
// Spec is the spec of the RoutingTree
|
||||
Spec RoutingTreeSpec `json:"spec" yaml:"spec"`
|
||||
|
||||
Status RoutingTreeStatus `json:"status" yaml:"status"`
|
||||
}
|
||||
|
||||
func (o *RoutingTree) GetSpec() any {
|
||||
@@ -39,15 +37,11 @@ func (o *RoutingTree) SetSpec(spec any) error {
|
||||
}
|
||||
|
||||
func (o *RoutingTree) GetSubresources() map[string]any {
|
||||
return map[string]any{
|
||||
"status": o.Status,
|
||||
}
|
||||
return map[string]any{}
|
||||
}
|
||||
|
||||
func (o *RoutingTree) GetSubresource(name string) (any, bool) {
|
||||
switch name {
|
||||
case "status":
|
||||
return o.Status, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
@@ -55,13 +49,6 @@ func (o *RoutingTree) GetSubresource(name string) (any, bool) {
|
||||
|
||||
func (o *RoutingTree) SetSubresource(name string, value any) error {
|
||||
switch name {
|
||||
case "status":
|
||||
cast, ok := value.(RoutingTreeStatus)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot set status type %#v, not of type RoutingTreeStatus", value)
|
||||
}
|
||||
o.Status = cast
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("subresource '%s' does not exist", name)
|
||||
}
|
||||
@@ -233,7 +220,6 @@ func (o *RoutingTree) DeepCopyInto(dst *RoutingTree) {
|
||||
dst.TypeMeta.Kind = o.TypeMeta.Kind
|
||||
o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
|
||||
o.Spec.DeepCopyInto(&dst.Spec)
|
||||
o.Status.DeepCopyInto(&dst.Status)
|
||||
}
|
||||
|
||||
// Interface compliance compile-time check
|
||||
@@ -305,15 +291,3 @@ func (s *RoutingTreeSpec) DeepCopy() *RoutingTreeSpec {
|
||||
func (s *RoutingTreeSpec) DeepCopyInto(dst *RoutingTreeSpec) {
|
||||
resource.CopyObjectInto(dst, s)
|
||||
}
|
||||
|
||||
// DeepCopy creates a full deep copy of RoutingTreeStatus
|
||||
func (s *RoutingTreeStatus) DeepCopy() *RoutingTreeStatus {
|
||||
cpy := &RoutingTreeStatus{}
|
||||
s.DeepCopyInto(cpy)
|
||||
return cpy
|
||||
}
|
||||
|
||||
// DeepCopyInto deep copies RoutingTreeStatus into another RoutingTreeStatus object
|
||||
func (s *RoutingTreeStatus) DeepCopyInto(dst *RoutingTreeStatus) {
|
||||
resource.CopyObjectInto(dst, s)
|
||||
}
|
||||
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
|
||||
package v0alpha1
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type RoutingTreestatusOperatorState struct {
|
||||
// lastEvaluation is the ResourceVersion last evaluated
|
||||
LastEvaluation string `json:"lastEvaluation"`
|
||||
// state describes the state of the lastEvaluation.
|
||||
// It is limited to three possible states for machine evaluation.
|
||||
State RoutingTreeStatusOperatorStateState `json:"state"`
|
||||
// descriptiveState is an optional more descriptive state field which has no requirements on format
|
||||
DescriptiveState *string `json:"descriptiveState,omitempty"`
|
||||
// details contains any extra information that is operator-specific
|
||||
Details map[string]interface{} `json:"details,omitempty"`
|
||||
}
|
||||
|
||||
// NewRoutingTreestatusOperatorState creates a new RoutingTreestatusOperatorState object.
|
||||
func NewRoutingTreestatusOperatorState() *RoutingTreestatusOperatorState {
|
||||
return &RoutingTreestatusOperatorState{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type RoutingTreeStatus struct {
|
||||
// operatorStates is a map of operator ID to operator state evaluations.
|
||||
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
|
||||
OperatorStates map[string]RoutingTreestatusOperatorState `json:"operatorStates,omitempty"`
|
||||
// additionalFields is reserved for future use
|
||||
AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
|
||||
}
|
||||
|
||||
// NewRoutingTreeStatus creates a new RoutingTreeStatus object.
|
||||
func NewRoutingTreeStatus() *RoutingTreeStatus {
|
||||
return &RoutingTreeStatus{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type RoutingTreeStatusOperatorStateState string
|
||||
|
||||
const (
|
||||
RoutingTreeStatusOperatorStateStateSuccess RoutingTreeStatusOperatorStateState = "success"
|
||||
RoutingTreeStatusOperatorStateStateInProgress RoutingTreeStatusOperatorStateState = "in_progress"
|
||||
RoutingTreeStatusOperatorStateStateFailed RoutingTreeStatusOperatorStateState = "failed"
|
||||
)
|
||||
-19
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type TemplateGroupClient struct {
|
||||
@@ -76,24 +75,6 @@ func (c *TemplateGroupClient) Patch(ctx context.Context, identifier resource.Ide
|
||||
return c.client.Patch(ctx, identifier, req, opts)
|
||||
}
|
||||
|
||||
func (c *TemplateGroupClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus TemplateGroupStatus, opts resource.UpdateOptions) (*TemplateGroup, error) {
|
||||
return c.client.Update(ctx, &TemplateGroup{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: TemplateGroupKind().Kind(),
|
||||
APIVersion: GroupVersion.Identifier(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Namespace: identifier.Namespace,
|
||||
Name: identifier.Name,
|
||||
},
|
||||
Status: newStatus,
|
||||
}, resource.UpdateOptions{
|
||||
Subresource: "status",
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *TemplateGroupClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
|
||||
return c.client.Delete(ctx, identifier, opts)
|
||||
}
|
||||
|
||||
+1
-27
@@ -21,8 +21,6 @@ type TemplateGroup struct {
|
||||
|
||||
// Spec is the spec of the TemplateGroup
|
||||
Spec TemplateGroupSpec `json:"spec" yaml:"spec"`
|
||||
|
||||
Status TemplateGroupStatus `json:"status" yaml:"status"`
|
||||
}
|
||||
|
||||
func (o *TemplateGroup) GetSpec() any {
|
||||
@@ -39,15 +37,11 @@ func (o *TemplateGroup) SetSpec(spec any) error {
|
||||
}
|
||||
|
||||
func (o *TemplateGroup) GetSubresources() map[string]any {
|
||||
return map[string]any{
|
||||
"status": o.Status,
|
||||
}
|
||||
return map[string]any{}
|
||||
}
|
||||
|
||||
func (o *TemplateGroup) GetSubresource(name string) (any, bool) {
|
||||
switch name {
|
||||
case "status":
|
||||
return o.Status, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
@@ -55,13 +49,6 @@ func (o *TemplateGroup) GetSubresource(name string) (any, bool) {
|
||||
|
||||
func (o *TemplateGroup) SetSubresource(name string, value any) error {
|
||||
switch name {
|
||||
case "status":
|
||||
cast, ok := value.(TemplateGroupStatus)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot set status type %#v, not of type TemplateGroupStatus", value)
|
||||
}
|
||||
o.Status = cast
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("subresource '%s' does not exist", name)
|
||||
}
|
||||
@@ -233,7 +220,6 @@ func (o *TemplateGroup) DeepCopyInto(dst *TemplateGroup) {
|
||||
dst.TypeMeta.Kind = o.TypeMeta.Kind
|
||||
o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
|
||||
o.Spec.DeepCopyInto(&dst.Spec)
|
||||
o.Status.DeepCopyInto(&dst.Status)
|
||||
}
|
||||
|
||||
// Interface compliance compile-time check
|
||||
@@ -305,15 +291,3 @@ func (s *TemplateGroupSpec) DeepCopy() *TemplateGroupSpec {
|
||||
func (s *TemplateGroupSpec) DeepCopyInto(dst *TemplateGroupSpec) {
|
||||
resource.CopyObjectInto(dst, s)
|
||||
}
|
||||
|
||||
// DeepCopy creates a full deep copy of TemplateGroupStatus
|
||||
func (s *TemplateGroupStatus) DeepCopy() *TemplateGroupStatus {
|
||||
cpy := &TemplateGroupStatus{}
|
||||
s.DeepCopyInto(cpy)
|
||||
return cpy
|
||||
}
|
||||
|
||||
// DeepCopyInto deep copies TemplateGroupStatus into another TemplateGroupStatus object
|
||||
func (s *TemplateGroupStatus) DeepCopyInto(dst *TemplateGroupStatus) {
|
||||
resource.CopyObjectInto(dst, s)
|
||||
}
|
||||
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
|
||||
package v0alpha1
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type TemplateGroupstatusOperatorState struct {
|
||||
// lastEvaluation is the ResourceVersion last evaluated
|
||||
LastEvaluation string `json:"lastEvaluation"`
|
||||
// state describes the state of the lastEvaluation.
|
||||
// It is limited to three possible states for machine evaluation.
|
||||
State TemplateGroupStatusOperatorStateState `json:"state"`
|
||||
// descriptiveState is an optional more descriptive state field which has no requirements on format
|
||||
DescriptiveState *string `json:"descriptiveState,omitempty"`
|
||||
// details contains any extra information that is operator-specific
|
||||
Details map[string]interface{} `json:"details,omitempty"`
|
||||
}
|
||||
|
||||
// NewTemplateGroupstatusOperatorState creates a new TemplateGroupstatusOperatorState object.
|
||||
func NewTemplateGroupstatusOperatorState() *TemplateGroupstatusOperatorState {
|
||||
return &TemplateGroupstatusOperatorState{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type TemplateGroupStatus struct {
|
||||
// operatorStates is a map of operator ID to operator state evaluations.
|
||||
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
|
||||
OperatorStates map[string]TemplateGroupstatusOperatorState `json:"operatorStates,omitempty"`
|
||||
// additionalFields is reserved for future use
|
||||
AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
|
||||
}
|
||||
|
||||
// NewTemplateGroupStatus creates a new TemplateGroupStatus object.
|
||||
func NewTemplateGroupStatus() *TemplateGroupStatus {
|
||||
return &TemplateGroupStatus{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type TemplateGroupStatusOperatorStateState string
|
||||
|
||||
const (
|
||||
TemplateGroupStatusOperatorStateStateSuccess TemplateGroupStatusOperatorStateState = "success"
|
||||
TemplateGroupStatusOperatorStateStateInProgress TemplateGroupStatusOperatorStateState = "in_progress"
|
||||
TemplateGroupStatusOperatorStateStateFailed TemplateGroupStatusOperatorStateState = "failed"
|
||||
)
|
||||
-19
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type TimeIntervalClient struct {
|
||||
@@ -76,24 +75,6 @@ func (c *TimeIntervalClient) Patch(ctx context.Context, identifier resource.Iden
|
||||
return c.client.Patch(ctx, identifier, req, opts)
|
||||
}
|
||||
|
||||
func (c *TimeIntervalClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus TimeIntervalStatus, opts resource.UpdateOptions) (*TimeInterval, error) {
|
||||
return c.client.Update(ctx, &TimeInterval{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: TimeIntervalKind().Kind(),
|
||||
APIVersion: GroupVersion.Identifier(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Namespace: identifier.Namespace,
|
||||
Name: identifier.Name,
|
||||
},
|
||||
Status: newStatus,
|
||||
}, resource.UpdateOptions{
|
||||
Subresource: "status",
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *TimeIntervalClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
|
||||
return c.client.Delete(ctx, identifier, opts)
|
||||
}
|
||||
|
||||
+1
-27
@@ -21,8 +21,6 @@ type TimeInterval struct {
|
||||
|
||||
// Spec is the spec of the TimeInterval
|
||||
Spec TimeIntervalSpec `json:"spec" yaml:"spec"`
|
||||
|
||||
Status TimeIntervalStatus `json:"status" yaml:"status"`
|
||||
}
|
||||
|
||||
func (o *TimeInterval) GetSpec() any {
|
||||
@@ -39,15 +37,11 @@ func (o *TimeInterval) SetSpec(spec any) error {
|
||||
}
|
||||
|
||||
func (o *TimeInterval) GetSubresources() map[string]any {
|
||||
return map[string]any{
|
||||
"status": o.Status,
|
||||
}
|
||||
return map[string]any{}
|
||||
}
|
||||
|
||||
func (o *TimeInterval) GetSubresource(name string) (any, bool) {
|
||||
switch name {
|
||||
case "status":
|
||||
return o.Status, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
@@ -55,13 +49,6 @@ func (o *TimeInterval) GetSubresource(name string) (any, bool) {
|
||||
|
||||
func (o *TimeInterval) SetSubresource(name string, value any) error {
|
||||
switch name {
|
||||
case "status":
|
||||
cast, ok := value.(TimeIntervalStatus)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot set status type %#v, not of type TimeIntervalStatus", value)
|
||||
}
|
||||
o.Status = cast
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("subresource '%s' does not exist", name)
|
||||
}
|
||||
@@ -233,7 +220,6 @@ func (o *TimeInterval) DeepCopyInto(dst *TimeInterval) {
|
||||
dst.TypeMeta.Kind = o.TypeMeta.Kind
|
||||
o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
|
||||
o.Spec.DeepCopyInto(&dst.Spec)
|
||||
o.Status.DeepCopyInto(&dst.Status)
|
||||
}
|
||||
|
||||
// Interface compliance compile-time check
|
||||
@@ -305,15 +291,3 @@ func (s *TimeIntervalSpec) DeepCopy() *TimeIntervalSpec {
|
||||
func (s *TimeIntervalSpec) DeepCopyInto(dst *TimeIntervalSpec) {
|
||||
resource.CopyObjectInto(dst, s)
|
||||
}
|
||||
|
||||
// DeepCopy creates a full deep copy of TimeIntervalStatus
|
||||
func (s *TimeIntervalStatus) DeepCopy() *TimeIntervalStatus {
|
||||
cpy := &TimeIntervalStatus{}
|
||||
s.DeepCopyInto(cpy)
|
||||
return cpy
|
||||
}
|
||||
|
||||
// DeepCopyInto deep copies TimeIntervalStatus into another TimeIntervalStatus object
|
||||
func (s *TimeIntervalStatus) DeepCopyInto(dst *TimeIntervalStatus) {
|
||||
resource.CopyObjectInto(dst, s)
|
||||
}
|
||||
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
|
||||
package v0alpha1
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type TimeIntervalstatusOperatorState struct {
|
||||
// lastEvaluation is the ResourceVersion last evaluated
|
||||
LastEvaluation string `json:"lastEvaluation"`
|
||||
// state describes the state of the lastEvaluation.
|
||||
// It is limited to three possible states for machine evaluation.
|
||||
State TimeIntervalStatusOperatorStateState `json:"state"`
|
||||
// descriptiveState is an optional more descriptive state field which has no requirements on format
|
||||
DescriptiveState *string `json:"descriptiveState,omitempty"`
|
||||
// details contains any extra information that is operator-specific
|
||||
Details map[string]interface{} `json:"details,omitempty"`
|
||||
}
|
||||
|
||||
// NewTimeIntervalstatusOperatorState creates a new TimeIntervalstatusOperatorState object.
|
||||
func NewTimeIntervalstatusOperatorState() *TimeIntervalstatusOperatorState {
|
||||
return &TimeIntervalstatusOperatorState{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type TimeIntervalStatus struct {
|
||||
// operatorStates is a map of operator ID to operator state evaluations.
|
||||
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
|
||||
OperatorStates map[string]TimeIntervalstatusOperatorState `json:"operatorStates,omitempty"`
|
||||
// additionalFields is reserved for future use
|
||||
AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
|
||||
}
|
||||
|
||||
// NewTimeIntervalStatus creates a new TimeIntervalStatus object.
|
||||
func NewTimeIntervalStatus() *TimeIntervalStatus {
|
||||
return &TimeIntervalStatus{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type TimeIntervalStatusOperatorStateState string
|
||||
|
||||
const (
|
||||
TimeIntervalStatusOperatorStateStateSuccess TimeIntervalStatusOperatorStateState = "success"
|
||||
TimeIntervalStatusOperatorStateStateInProgress TimeIntervalStatusOperatorStateState = "in_progress"
|
||||
TimeIntervalStatusOperatorStateStateFailed TimeIntervalStatusOperatorStateState = "failed"
|
||||
)
|
||||
-1321
File diff suppressed because it is too large
Load Diff
@@ -20,16 +20,16 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
rawSchemaReceiverv0alpha1 = []byte(`{"Integration":{"additionalProperties":false,"properties":{"disableResolveMessage":{"type":"boolean"},"secureFields":{"additionalProperties":{"type":"boolean"},"type":"object"},"settings":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"type":{"type":"string"},"uid":{"type":"string"},"version":{"type":"string"}},"required":["type","version","settings"],"type":"object"},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"Receiver":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"integrations":{"items":{"$ref":"#/components/schemas/Integration"},"type":"array"},"title":{"type":"string"}},"required":["title","integrations"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
|
||||
rawSchemaReceiverv0alpha1 = []byte(`{"Integration":{"additionalProperties":false,"properties":{"disableResolveMessage":{"type":"boolean"},"secureFields":{"additionalProperties":{"type":"boolean"},"type":"object"},"settings":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"type":{"type":"string"},"uid":{"type":"string"},"version":{"type":"string"}},"required":["type","version","settings"],"type":"object"},"Receiver":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"integrations":{"items":{"$ref":"#/components/schemas/Integration"},"type":"array"},"title":{"type":"string"}},"required":["title","integrations"],"type":"object"}}`)
|
||||
versionSchemaReceiverv0alpha1 app.VersionSchema
|
||||
_ = json.Unmarshal(rawSchemaReceiverv0alpha1, &versionSchemaReceiverv0alpha1)
|
||||
rawSchemaRoutingTreev0alpha1 = []byte(`{"Matcher":{"additionalProperties":false,"properties":{"label":{"type":"string"},"type":{"enum":["=","!=","=~","!~"],"type":"string"},"value":{"type":"string"}},"required":["type","label","value"],"type":"object"},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"Route":{"additionalProperties":false,"properties":{"active_time_intervals":{"items":{"type":"string"},"type":"array"},"continue":{"type":"boolean"},"group_by":{"items":{"type":"string"},"type":"array"},"group_interval":{"type":"string"},"group_wait":{"type":"string"},"matchers":{"items":{"$ref":"#/components/schemas/Matcher"},"type":"array"},"mute_time_intervals":{"items":{"type":"string"},"type":"array"},"receiver":{"type":"string"},"repeat_interval":{"type":"string"},"routes":{"items":{"$ref":"#/components/schemas/Route"},"type":"array"}},"required":["continue"],"type":"object"},"RouteDefaults":{"additionalProperties":false,"properties":{"group_by":{"items":{"type":"string"},"type":"array"},"group_interval":{"type":"string"},"group_wait":{"type":"string"},"receiver":{"type":"string"},"repeat_interval":{"type":"string"}},"required":["receiver"],"type":"object"},"RoutingTree":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"defaults":{"$ref":"#/components/schemas/RouteDefaults"},"routes":{"items":{"$ref":"#/components/schemas/Route"},"type":"array"}},"required":["defaults","routes"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
|
||||
rawSchemaRoutingTreev0alpha1 = []byte(`{"Matcher":{"additionalProperties":false,"properties":{"label":{"type":"string"},"type":{"enum":["=","!=","=~","!~"],"type":"string"},"value":{"type":"string"}},"required":["type","label","value"],"type":"object"},"Route":{"additionalProperties":false,"properties":{"active_time_intervals":{"items":{"type":"string"},"type":"array"},"continue":{"type":"boolean"},"group_by":{"items":{"type":"string"},"type":"array"},"group_interval":{"type":"string"},"group_wait":{"type":"string"},"matchers":{"items":{"$ref":"#/components/schemas/Matcher"},"type":"array"},"mute_time_intervals":{"items":{"type":"string"},"type":"array"},"receiver":{"type":"string"},"repeat_interval":{"type":"string"},"routes":{"items":{"$ref":"#/components/schemas/Route"},"type":"array"}},"required":["continue"],"type":"object"},"RouteDefaults":{"additionalProperties":false,"properties":{"group_by":{"items":{"type":"string"},"type":"array"},"group_interval":{"type":"string"},"group_wait":{"type":"string"},"receiver":{"type":"string"},"repeat_interval":{"type":"string"}},"required":["receiver"],"type":"object"},"RoutingTree":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"defaults":{"$ref":"#/components/schemas/RouteDefaults"},"routes":{"items":{"$ref":"#/components/schemas/Route"},"type":"array"}},"required":["defaults","routes"],"type":"object"}}`)
|
||||
versionSchemaRoutingTreev0alpha1 app.VersionSchema
|
||||
_ = json.Unmarshal(rawSchemaRoutingTreev0alpha1, &versionSchemaRoutingTreev0alpha1)
|
||||
rawSchemaTemplateGroupv0alpha1 = []byte(`{"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"TemplateGroup":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"content":{"type":"string"},"title":{"type":"string"}},"required":["title","content"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
|
||||
rawSchemaTemplateGroupv0alpha1 = []byte(`{"TemplateGroup":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"content":{"type":"string"},"title":{"type":"string"}},"required":["title","content"],"type":"object"}}`)
|
||||
versionSchemaTemplateGroupv0alpha1 app.VersionSchema
|
||||
_ = json.Unmarshal(rawSchemaTemplateGroupv0alpha1, &versionSchemaTemplateGroupv0alpha1)
|
||||
rawSchemaTimeIntervalv0alpha1 = []byte(`{"Interval":{"additionalProperties":false,"properties":{"days_of_month":{"items":{"type":"string"},"type":"array"},"location":{"type":"string"},"months":{"items":{"type":"string"},"type":"array"},"times":{"items":{"$ref":"#/components/schemas/TimeRange"},"type":"array"},"weekdays":{"items":{"type":"string"},"type":"array"},"years":{"items":{"type":"string"},"type":"array"}},"type":"object"},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"TimeInterval":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"TimeRange":{"additionalProperties":false,"properties":{"end_time":{"type":"string"},"start_time":{"type":"string"}},"required":["start_time","end_time"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"name":{"type":"string"},"time_intervals":{"items":{"$ref":"#/components/schemas/Interval"},"type":"array"}},"required":["name","time_intervals"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
|
||||
rawSchemaTimeIntervalv0alpha1 = []byte(`{"Interval":{"additionalProperties":false,"properties":{"days_of_month":{"items":{"type":"string"},"type":"array"},"location":{"type":"string"},"months":{"items":{"type":"string"},"type":"array"},"times":{"items":{"$ref":"#/components/schemas/TimeRange"},"type":"array"},"weekdays":{"items":{"type":"string"},"type":"array"},"years":{"items":{"type":"string"},"type":"array"}},"type":"object"},"TimeInterval":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"TimeRange":{"additionalProperties":false,"properties":{"end_time":{"type":"string"},"start_time":{"type":"string"}},"required":["start_time","end_time"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"name":{"type":"string"},"time_intervals":{"items":{"$ref":"#/components/schemas/Interval"},"type":"array"}},"required":["name","time_intervals"],"type":"object"}}`)
|
||||
versionSchemaTimeIntervalv0alpha1 app.VersionSchema
|
||||
_ = json.Unmarshal(rawSchemaTimeIntervalv0alpha1, &versionSchemaTimeIntervalv0alpha1)
|
||||
)
|
||||
|
||||
@@ -452,6 +452,7 @@ QueryOptionsSpec: {
|
||||
interval?: string
|
||||
cacheTimeout?: string
|
||||
hideTimeOverride?: bool
|
||||
timeCompare?: string
|
||||
}
|
||||
|
||||
DataQueryKind: {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package cuevalidator
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
cuejson "cuelang.org/go/encoding/json"
|
||||
)
|
||||
|
||||
// Validator provides thread-safe CUE schema validation.
|
||||
//
|
||||
// CUE is not safe for concurrent use: https://github.com/cue-lang/cue/discussions/1205#discussioncomment-1189238
|
||||
// This validator uses a mutex to protect concurrent access to the underlying CUE validation.
|
||||
type Validator struct {
|
||||
schema cue.Value
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func NewValidator(schema cue.Value) *Validator {
|
||||
return &Validator{
|
||||
schema: schema,
|
||||
}
|
||||
}
|
||||
|
||||
func (v *Validator) Validate(data []byte) error {
|
||||
v.mu.Lock()
|
||||
defer v.mu.Unlock()
|
||||
return cuejson.Validate(data, v.schema)
|
||||
}
|
||||
@@ -670,6 +670,10 @@ lineage: schemas: [{
|
||||
// Controls if the timeFrom or timeShift overrides are shown in the panel header
|
||||
hideTimeOverride?: bool
|
||||
|
||||
// Compare the current time range with a previous period
|
||||
// For example "1d" to compare current period but shifted back 1 day
|
||||
timeCompare?: string
|
||||
|
||||
// Dynamically load the panel
|
||||
libraryPanel?: #LibraryPanelRef
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
data "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1"
|
||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type LibraryPanel struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
// +optional
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Panel properties
|
||||
Spec LibraryPanelSpec `json:"spec"`
|
||||
|
||||
// Status will show errors
|
||||
Status *LibraryPanelStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type LibraryPanelList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// +optional
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
Items []LibraryPanel `json:"items"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
type LibraryPanelSpec struct {
|
||||
// The panel type
|
||||
Type string `json:"type"`
|
||||
|
||||
// The panel type
|
||||
PluginVersion string `json:"pluginVersion,omitempty"`
|
||||
|
||||
// The title of the library panel
|
||||
Title string `json:"title,omitempty"`
|
||||
|
||||
// The title of the panel when displayed in the dashboard
|
||||
PanelTitle string `json:"panelTitle,omitempty"`
|
||||
|
||||
// Library panel description
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// The options schema depends on the panel type
|
||||
Options common.Unstructured `json:"options"`
|
||||
|
||||
// The fieldConfig schema depends on the panel type
|
||||
FieldConfig common.Unstructured `json:"fieldConfig"`
|
||||
|
||||
// The default datasource type
|
||||
Datasource *data.DataSourceRef `json:"datasource,omitempty"`
|
||||
|
||||
// The grid position
|
||||
GridPos GridPos `json:"gridPos,omitempty"`
|
||||
|
||||
// Whether the panel is transparent
|
||||
Transparent bool `json:"transparent,omitempty"`
|
||||
|
||||
// The links for the panel
|
||||
Links []common.Unstructured `json:"links,omitempty"`
|
||||
|
||||
// The datasource queries
|
||||
// +listType=atomic
|
||||
Targets []data.DataQuery `json:"targets,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
type GridPos struct {
|
||||
W int `json:"w"`
|
||||
H int `json:"h"`
|
||||
X int `json:"x"`
|
||||
Y int `json:"y"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
type LibraryPanelStatus struct {
|
||||
// Translation warnings (mostly things that were in SQL columns but not found in the saved body)
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
|
||||
// The properties previously stored in SQL that are not included in this model
|
||||
Missing common.Unstructured `json:"missing,omitempty"`
|
||||
}
|
||||
@@ -1,95 +1,5 @@
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
data "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1"
|
||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type LibraryPanel struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
// +optional
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Panel properties
|
||||
Spec LibraryPanelSpec `json:"spec"`
|
||||
|
||||
// Status will show errors
|
||||
Status *LibraryPanelStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type LibraryPanelList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// +optional
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
Items []LibraryPanel `json:"items"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
type LibraryPanelSpec struct {
|
||||
// The panel type
|
||||
Type string `json:"type"`
|
||||
|
||||
// The panel type
|
||||
PluginVersion string `json:"pluginVersion,omitempty"`
|
||||
|
||||
// The title of the library panel
|
||||
Title string `json:"title,omitempty"`
|
||||
|
||||
// The title of the panel when displayed in the dashboard
|
||||
PanelTitle string `json:"panelTitle,omitempty"`
|
||||
|
||||
// Library panel description
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// The options schema depends on the panel type
|
||||
Options common.Unstructured `json:"options"`
|
||||
|
||||
// The fieldConfig schema depends on the panel type
|
||||
FieldConfig common.Unstructured `json:"fieldConfig"`
|
||||
|
||||
// The default datasource type
|
||||
Datasource *data.DataSourceRef `json:"datasource,omitempty"`
|
||||
|
||||
// The grid position
|
||||
GridPos GridPos `json:"gridPos,omitempty"`
|
||||
|
||||
// Whether the panel is transparent
|
||||
Transparent bool `json:"transparent,omitempty"`
|
||||
|
||||
// The links for the panel
|
||||
Links []common.Unstructured `json:"links,omitempty"`
|
||||
|
||||
// The datasource queries
|
||||
// +listType=set
|
||||
Targets []data.DataQuery `json:"targets,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
type GridPos struct {
|
||||
W int `json:"w"`
|
||||
H int `json:"h"`
|
||||
X int `json:"x"`
|
||||
Y int `json:"y"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
type LibraryPanelStatus struct {
|
||||
// Translation warnings (mostly things that were in SQL columns but not found in the saved body)
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
|
||||
// The properties previously stored in SQL that are not included in this model
|
||||
Missing common.Unstructured `json:"missing,omitempty"`
|
||||
}
|
||||
|
||||
// This is like the legacy DTO where access and metadata are all returned in a single call
|
||||
// +k8s:deepcopy-gen=true
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
@@ -7,13 +7,13 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/cuevalidator"
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
"cuelang.org/go/cue/errors"
|
||||
cuejson "cuelang.org/go/encoding/json"
|
||||
)
|
||||
|
||||
func ValidateDashboardSpec(obj *Dashboard, forceValidation bool) (field.ErrorList, field.ErrorList) {
|
||||
@@ -33,7 +33,7 @@ func ValidateDashboardSpec(obj *Dashboard, forceValidation bool) (field.ErrorLis
|
||||
}, schemaVersionError
|
||||
}
|
||||
|
||||
if err := cuejson.Validate(data, getCueSchema()); err != nil {
|
||||
if err := getValidator().Validate(data); err != nil {
|
||||
errs := field.ErrorList{}
|
||||
|
||||
for _, e := range errors.Errors(err) {
|
||||
@@ -71,20 +71,21 @@ func formatErrorPath(path []string) string {
|
||||
}
|
||||
|
||||
var (
|
||||
compiledSchema cue.Value
|
||||
getSchemaOnce sync.Once
|
||||
validator *cuevalidator.Validator
|
||||
getSchemaOnce sync.Once
|
||||
)
|
||||
|
||||
//go:embed dashboard_kind.cue
|
||||
var schemaSource string
|
||||
|
||||
func getCueSchema() cue.Value {
|
||||
func getValidator() *cuevalidator.Validator {
|
||||
getSchemaOnce.Do(func() {
|
||||
cueCtx := cuecontext.New()
|
||||
compiledSchema = cueCtx.CompileString(schemaSource).LookupPath(
|
||||
compiledSchema := cueCtx.CompileString(schemaSource).LookupPath(
|
||||
cue.ParsePath("lineage.schemas[0].schema.spec"),
|
||||
)
|
||||
validator = cuevalidator.NewValidator(compiledSchema)
|
||||
})
|
||||
|
||||
return compiledSchema
|
||||
return validator
|
||||
}
|
||||
|
||||
@@ -882,7 +882,7 @@ func schema_pkg_apis_dashboard_v0alpha1_LibraryPanelSpec(ref common.ReferenceCal
|
||||
"targets": {
|
||||
VendorExtensible: spec.VendorExtensible{
|
||||
Extensions: spec.Extensions{
|
||||
"x-kubernetes-list-type": "set",
|
||||
"x-kubernetes-list-type": "atomic",
|
||||
},
|
||||
},
|
||||
SchemaProps: spec.SchemaProps{
|
||||
|
||||
@@ -670,6 +670,10 @@ lineage: schemas: [{
|
||||
// Controls if the timeFrom or timeShift overrides are shown in the panel header
|
||||
hideTimeOverride?: bool
|
||||
|
||||
// Compare the current time range with a previous period
|
||||
// For example "1d" to compare current period but shifted back 1 day
|
||||
timeCompare?: string
|
||||
|
||||
// Dynamically load the panel
|
||||
libraryPanel?: #LibraryPanelRef
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
"cuelang.org/go/cue/errors"
|
||||
cuejson "cuelang.org/go/encoding/json"
|
||||
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/cuevalidator"
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
|
||||
)
|
||||
|
||||
@@ -34,7 +34,7 @@ func ValidateDashboardSpec(obj *Dashboard, forceValidation bool) (field.ErrorLis
|
||||
}, schemaVersionError
|
||||
}
|
||||
|
||||
if err := cuejson.Validate(data, getCueSchema()); err != nil {
|
||||
if err := getValidator().Validate(data); err != nil {
|
||||
errs := field.ErrorList{}
|
||||
|
||||
for _, e := range errors.Errors(err) {
|
||||
@@ -72,20 +72,21 @@ func formatErrorPath(path []string) string {
|
||||
}
|
||||
|
||||
var (
|
||||
compiledSchema cue.Value
|
||||
getSchemaOnce sync.Once
|
||||
validator *cuevalidator.Validator
|
||||
getSchemaOnce sync.Once
|
||||
)
|
||||
|
||||
//go:embed dashboard_kind.cue
|
||||
var schemaSource string
|
||||
|
||||
func getCueSchema() cue.Value {
|
||||
func getValidator() *cuevalidator.Validator {
|
||||
getSchemaOnce.Do(func() {
|
||||
cueCtx := cuecontext.New()
|
||||
compiledSchema = cueCtx.CompileString(schemaSource).LookupPath(
|
||||
compiledSchema := cueCtx.CompileString(schemaSource).LookupPath(
|
||||
cue.ParsePath("lineage.schemas[0].schema.spec"),
|
||||
)
|
||||
validator = cuevalidator.NewValidator(compiledSchema)
|
||||
})
|
||||
|
||||
return compiledSchema
|
||||
return validator
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ import (
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
"cuelang.org/go/cue/errors"
|
||||
cuejson "cuelang.org/go/encoding/json"
|
||||
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/cuevalidator"
|
||||
)
|
||||
|
||||
func ValidateDashboardSpec(obj *Dashboard) field.ErrorList {
|
||||
@@ -26,7 +27,7 @@ func ValidateDashboardSpec(obj *Dashboard) field.ErrorList {
|
||||
// Custom validation for action query params and headers
|
||||
validateAndTrimActionArrays(obj)
|
||||
|
||||
if err := cuejson.Validate(data, getCueSchema()); err != nil {
|
||||
if err := getValidator().Validate(data); err != nil {
|
||||
errs := field.ErrorList{}
|
||||
|
||||
for _, e := range errors.Errors(err) {
|
||||
@@ -123,20 +124,21 @@ func formatErrorPath(path []string) string {
|
||||
}
|
||||
|
||||
var (
|
||||
compiledSchema cue.Value
|
||||
getSchemaOnce sync.Once
|
||||
validator *cuevalidator.Validator
|
||||
getSchemaOnce sync.Once
|
||||
)
|
||||
|
||||
//go:embed dashboard_spec.cue
|
||||
var schemaSource string
|
||||
|
||||
func getCueSchema() cue.Value {
|
||||
func getValidator() *cuevalidator.Validator {
|
||||
getSchemaOnce.Do(func() {
|
||||
cueCtx := cuecontext.New()
|
||||
compiledSchema = cueCtx.CompileString(schemaSource).LookupPath(
|
||||
compiledSchema := cueCtx.CompileString(schemaSource).LookupPath(
|
||||
cue.ParsePath("DashboardSpec"),
|
||||
)
|
||||
validator = cuevalidator.NewValidator(compiledSchema)
|
||||
})
|
||||
|
||||
return compiledSchema
|
||||
return validator
|
||||
}
|
||||
|
||||
@@ -456,6 +456,7 @@ QueryOptionsSpec: {
|
||||
interval?: string
|
||||
cacheTimeout?: string
|
||||
hideTimeOverride?: bool
|
||||
timeCompare?: string
|
||||
}
|
||||
|
||||
DataQueryKind: {
|
||||
|
||||
@@ -278,6 +278,7 @@ type DashboardQueryOptionsSpec struct {
|
||||
Interval *string `json:"interval,omitempty"`
|
||||
CacheTimeout *string `json:"cacheTimeout,omitempty"`
|
||||
HideTimeOverride *bool `json:"hideTimeOverride,omitempty"`
|
||||
TimeCompare *string `json:"timeCompare,omitempty"`
|
||||
}
|
||||
|
||||
// NewDashboardQueryOptionsSpec creates a new DashboardQueryOptionsSpec object.
|
||||
|
||||
@@ -12,7 +12,8 @@ import (
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
"cuelang.org/go/cue/errors"
|
||||
cuejson "cuelang.org/go/encoding/json"
|
||||
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/cuevalidator"
|
||||
)
|
||||
|
||||
func ValidateDashboardSpec(obj *Dashboard) field.ErrorList {
|
||||
@@ -26,7 +27,7 @@ func ValidateDashboardSpec(obj *Dashboard) field.ErrorList {
|
||||
// Custom validation for action query params and headers
|
||||
validateAndTrimActionArrays(obj)
|
||||
|
||||
if err := cuejson.Validate(data, getCueSchema()); err != nil {
|
||||
if err := getValidator().Validate(data); err != nil {
|
||||
errs := field.ErrorList{}
|
||||
|
||||
for _, e := range errors.Errors(err) {
|
||||
@@ -123,20 +124,21 @@ func formatErrorPath(path []string) string {
|
||||
}
|
||||
|
||||
var (
|
||||
compiledSchema cue.Value
|
||||
getSchemaOnce sync.Once
|
||||
validator *cuevalidator.Validator
|
||||
getSchemaOnce sync.Once
|
||||
)
|
||||
|
||||
//go:embed dashboard_spec.cue
|
||||
var schemaSource string
|
||||
|
||||
func getCueSchema() cue.Value {
|
||||
func getValidator() *cuevalidator.Validator {
|
||||
getSchemaOnce.Do(func() {
|
||||
cueCtx := cuecontext.New()
|
||||
compiledSchema = cueCtx.CompileString(schemaSource).LookupPath(
|
||||
compiledSchema := cueCtx.CompileString(schemaSource).LookupPath(
|
||||
cue.ParsePath("DashboardSpec"),
|
||||
)
|
||||
validator = cuevalidator.NewValidator(compiledSchema)
|
||||
})
|
||||
|
||||
return compiledSchema
|
||||
return validator
|
||||
}
|
||||
|
||||
@@ -3426,6 +3426,12 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardQueryOptionsSpec(ref common.Refe
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"timeCompare": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
+22
-2
@@ -208,7 +208,27 @@
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"actions": [
|
||||
{
|
||||
"fetch": {
|
||||
"body": "{}",
|
||||
"headers": [["Content-Type", "application/json"]],
|
||||
"method": "GET",
|
||||
"queryParams": [],
|
||||
"url": "/api/health"
|
||||
},
|
||||
"title": "Get instance health",
|
||||
"type": "fetch"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"targetBlank": true,
|
||||
"title": "Google Grafana",
|
||||
"url": "https://google.com/search?q=grafana"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
@@ -592,4 +612,4 @@
|
||||
"title": "Panel Tests - Table - Sparklines",
|
||||
"uid": "d6373b49-1957-4f00-9218-ee2120d3ecd9",
|
||||
"weekStart": ""
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -165,7 +165,7 @@ require (
|
||||
github.com/dolthub/go-icu-regex v0.0.0-20250327004329-6799764f2dad // indirect
|
||||
github.com/dolthub/go-mysql-server v0.19.1-0.20250410182021-5632d67cd46e // indirect
|
||||
github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71 // indirect
|
||||
github.com/dolthub/vitess v0.0.0-20250410090211-143e6b272ad4 // indirect
|
||||
github.com/dolthub/vitess v0.0.0-20250930230441-70c2c6a98e33 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
|
||||
+2
-2
@@ -499,8 +499,8 @@ github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71 h1:bMGS25NWAGTE
|
||||
github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71/go.mod h1:2/2zjLQ/JOOSbbSboojeg+cAwcRV0fDLzIiWch/lhqI=
|
||||
github.com/dolthub/maphash v0.1.0 h1:bsQ7JsF4FkkWyrP3oCnFJgrCUAFbFf3kOl4L/QxPDyQ=
|
||||
github.com/dolthub/maphash v0.1.0/go.mod h1:gkg4Ch4CdCDu5h6PMriVLawB7koZ+5ijb9puGMV50a4=
|
||||
github.com/dolthub/vitess v0.0.0-20250410090211-143e6b272ad4 h1:LGTt2LtYX8vaai32d+c9L0sMcP+Dg9w1kO6+lbsxxYg=
|
||||
github.com/dolthub/vitess v0.0.0-20250410090211-143e6b272ad4/go.mod h1:1gQZs/byeHLMSul3Lvl3MzioMtOW1je79QYGyi2fd70=
|
||||
github.com/dolthub/vitess v0.0.0-20250930230441-70c2c6a98e33 h1:ScHTwNbcVC6JH1OSyXzj8S4w67BIpRXwTSjrac3/PSw=
|
||||
github.com/dolthub/vitess v0.0.0-20250930230441-70c2c6a98e33/go.mod h1:8pvvk5OLaLN9LLxghyczUapn/97l+mBgIb10qC1LG84=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
|
||||
+2
-4
@@ -3,8 +3,8 @@ module github.com/grafana/grafana/apps/plugins
|
||||
go 1.25.3
|
||||
|
||||
require (
|
||||
github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37
|
||||
github.com/grafana/grafana-app-sdk v0.48.1
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.1
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250428110029-a8ea72012bde
|
||||
k8s.io/apimachinery v0.34.1
|
||||
k8s.io/apiserver v0.34.1
|
||||
@@ -14,7 +14,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
@@ -37,8 +36,8 @@ require (
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // indirect
|
||||
github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37 // indirect
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.1 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
@@ -93,7 +92,6 @@ require (
|
||||
k8s.io/api v0.34.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.34.1 // indirect
|
||||
k8s.io/client-go v0.34.1 // indirect
|
||||
k8s.io/component-base v0.34.1 // indirect
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||
@@ -242,8 +240,6 @@ k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA=
|
||||
k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0=
|
||||
k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY=
|
||||
k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8=
|
||||
k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A=
|
||||
k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
|
||||
|
||||
@@ -5,14 +5,13 @@ manifest: {
|
||||
groupOverride: "plugins.grafana.app"
|
||||
versions: {
|
||||
"v0alpha1": {
|
||||
served: false
|
||||
served: true
|
||||
codegen: {
|
||||
ts: {enabled: false}
|
||||
go: {enabled: true}
|
||||
}
|
||||
kinds: [
|
||||
pluginMetaV0Alpha1,
|
||||
pluginInstallV0Alpha1,
|
||||
pluginV0Alpha1,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,17 +4,33 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
pluginMetaV0Alpha1: {
|
||||
kind: "PluginMeta"
|
||||
plural: "pluginsmeta"
|
||||
pluginV0Alpha1: {
|
||||
kind: "Plugin"
|
||||
plural: "plugins"
|
||||
scope: "Namespaced"
|
||||
schema: {
|
||||
spec: {
|
||||
pluginJSON: #JSONData,
|
||||
id: string
|
||||
version: string
|
||||
url?: string
|
||||
class: "core" | "external" | "cdn"
|
||||
}
|
||||
}
|
||||
routes: {
|
||||
"/meta": {
|
||||
"GET": {
|
||||
request: {}
|
||||
response: #JSONData,
|
||||
responseMetadata: {
|
||||
typeMeta: false
|
||||
objectMeta: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// JSON configuration schema for Grafana plugins
|
||||
// Converted from: https://github.com/grafana/grafana/blob/main/docs/sources/developers/plugins/plugin.schema.json
|
||||
#JSONData: {
|
||||
@@ -217,4 +233,4 @@ pluginMetaV0Alpha1: {
|
||||
title?: string
|
||||
description?: string
|
||||
}]
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package plugins
|
||||
|
||||
pluginInstallV0Alpha1: {
|
||||
kind: "PluginInstall"
|
||||
plural: "plugininstalls"
|
||||
scope: "Namespaced"
|
||||
schema: {
|
||||
spec: {
|
||||
id: string
|
||||
version: string
|
||||
url?: string
|
||||
class: "core" | "external" | "cdn"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type PluginClient struct {
|
||||
client *resource.TypedClient[*Plugin, *PluginList]
|
||||
}
|
||||
|
||||
func NewPluginClient(client resource.Client) *PluginClient {
|
||||
return &PluginClient{
|
||||
client: resource.NewTypedClient[*Plugin, *PluginList](client, PluginKind()),
|
||||
}
|
||||
}
|
||||
|
||||
func NewPluginClientFromGenerator(generator resource.ClientGenerator) (*PluginClient, error) {
|
||||
c, err := generator.ClientFor(PluginKind())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewPluginClient(c), nil
|
||||
}
|
||||
|
||||
func (c *PluginClient) Get(ctx context.Context, identifier resource.Identifier) (*Plugin, error) {
|
||||
return c.client.Get(ctx, identifier)
|
||||
}
|
||||
|
||||
func (c *PluginClient) List(ctx context.Context, namespace string, opts resource.ListOptions) (*PluginList, error) {
|
||||
return c.client.List(ctx, namespace, opts)
|
||||
}
|
||||
|
||||
func (c *PluginClient) ListAll(ctx context.Context, namespace string, opts resource.ListOptions) (*PluginList, error) {
|
||||
resp, err := c.client.List(ctx, namespace, resource.ListOptions{
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Limit: opts.Limit,
|
||||
LabelFilters: opts.LabelFilters,
|
||||
FieldSelectors: opts.FieldSelectors,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for resp.GetContinue() != "" {
|
||||
page, err := c.client.List(ctx, namespace, resource.ListOptions{
|
||||
Continue: resp.GetContinue(),
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Limit: opts.Limit,
|
||||
LabelFilters: opts.LabelFilters,
|
||||
FieldSelectors: opts.FieldSelectors,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.SetContinue(page.GetContinue())
|
||||
resp.SetResourceVersion(page.GetResourceVersion())
|
||||
resp.SetItems(append(resp.GetItems(), page.GetItems()...))
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *PluginClient) Create(ctx context.Context, obj *Plugin, opts resource.CreateOptions) (*Plugin, error) {
|
||||
// Make sure apiVersion and kind are set
|
||||
obj.APIVersion = GroupVersion.Identifier()
|
||||
obj.Kind = PluginKind().Kind()
|
||||
return c.client.Create(ctx, obj, opts)
|
||||
}
|
||||
|
||||
func (c *PluginClient) Update(ctx context.Context, obj *Plugin, opts resource.UpdateOptions) (*Plugin, error) {
|
||||
return c.client.Update(ctx, obj, opts)
|
||||
}
|
||||
|
||||
func (c *PluginClient) Patch(ctx context.Context, identifier resource.Identifier, req resource.PatchRequest, opts resource.PatchOptions) (*Plugin, error) {
|
||||
return c.client.Patch(ctx, identifier, req, opts)
|
||||
}
|
||||
|
||||
func (c *PluginClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus PluginStatus, opts resource.UpdateOptions) (*Plugin, error) {
|
||||
return c.client.Update(ctx, &Plugin{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: PluginKind().Kind(),
|
||||
APIVersion: GroupVersion.Identifier(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Namespace: identifier.Namespace,
|
||||
Name: identifier.Name,
|
||||
},
|
||||
Status: newStatus,
|
||||
}, resource.UpdateOptions{
|
||||
Subresource: "status",
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *PluginClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
|
||||
return c.client.Delete(ctx, identifier, opts)
|
||||
}
|
||||
|
||||
type GetMetaRequest struct {
|
||||
Headers http.Header
|
||||
}
|
||||
|
||||
func (c *PluginClient) GetMeta(ctx context.Context, identifier resource.Identifier, request GetMetaRequest) (*GetMeta, error) {
|
||||
resp, err := c.client.SubresourceRequest(ctx, identifier, resource.CustomRouteRequestOptions{
|
||||
Path: "/meta",
|
||||
Verb: "GET",
|
||||
Headers: request.Headers,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cast := GetMeta{}
|
||||
err = json.Unmarshal(resp, &cast)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to unmarshal response bytes into GetMeta: %w", err)
|
||||
}
|
||||
return &cast, nil
|
||||
}
|
||||
+5
-5
@@ -11,18 +11,18 @@ import (
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
)
|
||||
|
||||
// PluginMetaJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
|
||||
type PluginMetaJSONCodec struct{}
|
||||
// PluginJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
|
||||
type PluginJSONCodec struct{}
|
||||
|
||||
// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
|
||||
func (*PluginMetaJSONCodec) Read(reader io.Reader, into resource.Object) error {
|
||||
func (*PluginJSONCodec) Read(reader io.Reader, into resource.Object) error {
|
||||
return json.NewDecoder(reader).Decode(into)
|
||||
}
|
||||
|
||||
// Write writes JSON-encoded bytes into `writer` marshaled from `from`
|
||||
func (*PluginMetaJSONCodec) Write(writer io.Writer, from resource.Object) error {
|
||||
func (*PluginJSONCodec) Write(writer io.Writer, from resource.Object) error {
|
||||
return json.NewEncoder(writer).Encode(from)
|
||||
}
|
||||
|
||||
// Interface compliance checks
|
||||
var _ resource.Codec = &PluginMetaJSONCodec{}
|
||||
var _ resource.Codec = &PluginJSONCodec{}
|
||||
@@ -0,0 +1,463 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
time "time"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type Info struct {
|
||||
// Required fields
|
||||
// +listType=set
|
||||
Keywords []string `json:"keywords"`
|
||||
Logos V0alpha1InfoLogos `json:"logos"`
|
||||
Updated time.Time `json:"updated"`
|
||||
Version string `json:"version"`
|
||||
// Optional fields
|
||||
Author *V0alpha1InfoAuthor `json:"author,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
// +listType=atomic
|
||||
Links []V0alpha1InfoLinks `json:"links,omitempty"`
|
||||
// +listType=atomic
|
||||
Screenshots []V0alpha1InfoScreenshots `json:"screenshots,omitempty"`
|
||||
}
|
||||
|
||||
// NewInfo creates a new Info object.
|
||||
func NewInfo() *Info {
|
||||
return &Info{
|
||||
Keywords: []string{},
|
||||
Logos: *NewV0alpha1InfoLogos(),
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type Dependencies struct {
|
||||
// Required field
|
||||
GrafanaDependency string `json:"grafanaDependency"`
|
||||
// Optional fields
|
||||
GrafanaVersion *string `json:"grafanaVersion,omitempty"`
|
||||
// +listType=set
|
||||
// +listMapKey=id
|
||||
Plugins []V0alpha1DependenciesPlugins `json:"plugins,omitempty"`
|
||||
Extensions *V0alpha1DependenciesExtensions `json:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
// NewDependencies creates a new Dependencies object.
|
||||
func NewDependencies() *Dependencies {
|
||||
return &Dependencies{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type EnterpriseFeatures struct {
|
||||
// Allow additional properties
|
||||
HealthDiagnosticsErrors *bool `json:"healthDiagnosticsErrors,omitempty"`
|
||||
}
|
||||
|
||||
// NewEnterpriseFeatures creates a new EnterpriseFeatures object.
|
||||
func NewEnterpriseFeatures() *EnterpriseFeatures {
|
||||
return &EnterpriseFeatures{
|
||||
HealthDiagnosticsErrors: (func(input bool) *bool { return &input })(false),
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type Include struct {
|
||||
Uid *string `json:"uid,omitempty"`
|
||||
Type *IncludeType `json:"type,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Component *string `json:"component,omitempty"`
|
||||
Role *IncludeRole `json:"role,omitempty"`
|
||||
Action *string `json:"action,omitempty"`
|
||||
Path *string `json:"path,omitempty"`
|
||||
AddToNav *bool `json:"addToNav,omitempty"`
|
||||
DefaultNav *bool `json:"defaultNav,omitempty"`
|
||||
Icon *string `json:"icon,omitempty"`
|
||||
}
|
||||
|
||||
// NewInclude creates a new Include object.
|
||||
func NewInclude() *Include {
|
||||
return &Include{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type QueryOptions struct {
|
||||
MaxDataPoints *bool `json:"maxDataPoints,omitempty"`
|
||||
MinInterval *bool `json:"minInterval,omitempty"`
|
||||
CacheTimeout *bool `json:"cacheTimeout,omitempty"`
|
||||
}
|
||||
|
||||
// NewQueryOptions creates a new QueryOptions object.
|
||||
func NewQueryOptions() *QueryOptions {
|
||||
return &QueryOptions{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type Route struct {
|
||||
Path *string `json:"path,omitempty"`
|
||||
Method *string `json:"method,omitempty"`
|
||||
Url *string `json:"url,omitempty"`
|
||||
ReqSignedIn *bool `json:"reqSignedIn,omitempty"`
|
||||
ReqRole *string `json:"reqRole,omitempty"`
|
||||
ReqAction *string `json:"reqAction,omitempty"`
|
||||
// +listType=atomic
|
||||
Headers []string `json:"headers,omitempty"`
|
||||
Body map[string]interface{} `json:"body,omitempty"`
|
||||
TokenAuth *V0alpha1RouteTokenAuth `json:"tokenAuth,omitempty"`
|
||||
JwtTokenAuth *V0alpha1RouteJwtTokenAuth `json:"jwtTokenAuth,omitempty"`
|
||||
// +listType=atomic
|
||||
UrlParams []V0alpha1RouteUrlParams `json:"urlParams,omitempty"`
|
||||
}
|
||||
|
||||
// NewRoute creates a new Route object.
|
||||
func NewRoute() *Route {
|
||||
return &Route{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type IAM struct {
|
||||
// +listType=atomic
|
||||
Permissions []V0alpha1IAMPermissions `json:"permissions,omitempty"`
|
||||
}
|
||||
|
||||
// NewIAM creates a new IAM object.
|
||||
func NewIAM() *IAM {
|
||||
return &IAM{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type Role struct {
|
||||
Role *V0alpha1RoleRole `json:"role,omitempty"`
|
||||
// +listType=set
|
||||
Grants []string `json:"grants,omitempty"`
|
||||
}
|
||||
|
||||
// NewRole creates a new Role object.
|
||||
func NewRole() *Role {
|
||||
return &Role{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type Extensions struct {
|
||||
// +listType=atomic
|
||||
AddedComponents []V0alpha1ExtensionsAddedComponents `json:"addedComponents,omitempty"`
|
||||
// +listType=atomic
|
||||
AddedLinks []V0alpha1ExtensionsAddedLinks `json:"addedLinks,omitempty"`
|
||||
// +listType=set
|
||||
// +listMapKey=id
|
||||
ExposedComponents []V0alpha1ExtensionsExposedComponents `json:"exposedComponents,omitempty"`
|
||||
// +listType=set
|
||||
// +listMapKey=id
|
||||
ExtensionPoints []V0alpha1ExtensionsExtensionPoints `json:"extensionPoints,omitempty"`
|
||||
}
|
||||
|
||||
// NewExtensions creates a new Extensions object.
|
||||
func NewExtensions() *Extensions {
|
||||
return &Extensions{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type GetMeta struct {
|
||||
// Unique name of the plugin
|
||||
Id string `json:"id"`
|
||||
// Plugin type
|
||||
Type GetMetaType `json:"type"`
|
||||
// Human-readable name of the plugin
|
||||
Name string `json:"name"`
|
||||
// Metadata for the plugin
|
||||
Info Info `json:"info"`
|
||||
// Dependency information
|
||||
Dependencies Dependencies `json:"dependencies"`
|
||||
// Optional fields
|
||||
Alerting *bool `json:"alerting,omitempty"`
|
||||
Annotations *bool `json:"annotations,omitempty"`
|
||||
AutoEnabled *bool `json:"autoEnabled,omitempty"`
|
||||
Backend *bool `json:"backend,omitempty"`
|
||||
BuildMode *string `json:"buildMode,omitempty"`
|
||||
BuiltIn *bool `json:"builtIn,omitempty"`
|
||||
Category *GetMetaCategory `json:"category,omitempty"`
|
||||
EnterpriseFeatures *EnterpriseFeatures `json:"enterpriseFeatures,omitempty"`
|
||||
Executable *string `json:"executable,omitempty"`
|
||||
HideFromList *bool `json:"hideFromList,omitempty"`
|
||||
// +listType=atomic
|
||||
Includes []Include `json:"includes,omitempty"`
|
||||
Logs *bool `json:"logs,omitempty"`
|
||||
Metrics *bool `json:"metrics,omitempty"`
|
||||
MultiValueFilterOperators *bool `json:"multiValueFilterOperators,omitempty"`
|
||||
PascalName *string `json:"pascalName,omitempty"`
|
||||
Preload *bool `json:"preload,omitempty"`
|
||||
QueryOptions *QueryOptions `json:"queryOptions,omitempty"`
|
||||
// +listType=atomic
|
||||
Routes []Route `json:"routes,omitempty"`
|
||||
SkipDataQuery *bool `json:"skipDataQuery,omitempty"`
|
||||
State *GetMetaState `json:"state,omitempty"`
|
||||
Streaming *bool `json:"streaming,omitempty"`
|
||||
Tracing *bool `json:"tracing,omitempty"`
|
||||
Iam *IAM `json:"iam,omitempty"`
|
||||
// +listType=atomic
|
||||
Roles []Role `json:"roles,omitempty"`
|
||||
Extensions *Extensions `json:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
// NewGetMeta creates a new GetMeta object.
|
||||
func NewGetMeta() *GetMeta {
|
||||
return &GetMeta{
|
||||
Info: *NewInfo(),
|
||||
Dependencies: *NewDependencies(),
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1InfoLogos struct {
|
||||
Small string `json:"small"`
|
||||
Large string `json:"large"`
|
||||
}
|
||||
|
||||
// NewV0alpha1InfoLogos creates a new V0alpha1InfoLogos object.
|
||||
func NewV0alpha1InfoLogos() *V0alpha1InfoLogos {
|
||||
return &V0alpha1InfoLogos{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1InfoAuthor struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Email *string `json:"email,omitempty"`
|
||||
Url *string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1InfoAuthor creates a new V0alpha1InfoAuthor object.
|
||||
func NewV0alpha1InfoAuthor() *V0alpha1InfoAuthor {
|
||||
return &V0alpha1InfoAuthor{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1InfoLinks struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Url *string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1InfoLinks creates a new V0alpha1InfoLinks object.
|
||||
func NewV0alpha1InfoLinks() *V0alpha1InfoLinks {
|
||||
return &V0alpha1InfoLinks{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1InfoScreenshots struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Path *string `json:"path,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1InfoScreenshots creates a new V0alpha1InfoScreenshots object.
|
||||
func NewV0alpha1InfoScreenshots() *V0alpha1InfoScreenshots {
|
||||
return &V0alpha1InfoScreenshots{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1DependenciesPlugins struct {
|
||||
Id string `json:"id"`
|
||||
Type V0alpha1DependenciesPluginsType `json:"type"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// NewV0alpha1DependenciesPlugins creates a new V0alpha1DependenciesPlugins object.
|
||||
func NewV0alpha1DependenciesPlugins() *V0alpha1DependenciesPlugins {
|
||||
return &V0alpha1DependenciesPlugins{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1DependenciesExtensions struct {
|
||||
// +listType=set
|
||||
ExposedComponents []string `json:"exposedComponents,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1DependenciesExtensions creates a new V0alpha1DependenciesExtensions object.
|
||||
func NewV0alpha1DependenciesExtensions() *V0alpha1DependenciesExtensions {
|
||||
return &V0alpha1DependenciesExtensions{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1RouteTokenAuth struct {
|
||||
Url *string `json:"url,omitempty"`
|
||||
// +listType=set
|
||||
Scopes []string `json:"scopes,omitempty"`
|
||||
Params map[string]interface{} `json:"params,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1RouteTokenAuth creates a new V0alpha1RouteTokenAuth object.
|
||||
func NewV0alpha1RouteTokenAuth() *V0alpha1RouteTokenAuth {
|
||||
return &V0alpha1RouteTokenAuth{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1RouteJwtTokenAuth struct {
|
||||
Url *string `json:"url,omitempty"`
|
||||
// +listType=set
|
||||
Scopes []string `json:"scopes,omitempty"`
|
||||
Params map[string]interface{} `json:"params,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1RouteJwtTokenAuth creates a new V0alpha1RouteJwtTokenAuth object.
|
||||
func NewV0alpha1RouteJwtTokenAuth() *V0alpha1RouteJwtTokenAuth {
|
||||
return &V0alpha1RouteJwtTokenAuth{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1RouteUrlParams struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Content *string `json:"content,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1RouteUrlParams creates a new V0alpha1RouteUrlParams object.
|
||||
func NewV0alpha1RouteUrlParams() *V0alpha1RouteUrlParams {
|
||||
return &V0alpha1RouteUrlParams{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1IAMPermissions struct {
|
||||
Action *string `json:"action,omitempty"`
|
||||
Scope *string `json:"scope,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1IAMPermissions creates a new V0alpha1IAMPermissions object.
|
||||
func NewV0alpha1IAMPermissions() *V0alpha1IAMPermissions {
|
||||
return &V0alpha1IAMPermissions{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1RoleRolePermissions struct {
|
||||
Action *string `json:"action,omitempty"`
|
||||
Scope *string `json:"scope,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1RoleRolePermissions creates a new V0alpha1RoleRolePermissions object.
|
||||
func NewV0alpha1RoleRolePermissions() *V0alpha1RoleRolePermissions {
|
||||
return &V0alpha1RoleRolePermissions{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1RoleRole struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
// +listType=atomic
|
||||
Permissions []V0alpha1RoleRolePermissions `json:"permissions,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1RoleRole creates a new V0alpha1RoleRole object.
|
||||
func NewV0alpha1RoleRole() *V0alpha1RoleRole {
|
||||
return &V0alpha1RoleRole{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1ExtensionsAddedComponents struct {
|
||||
// +listType=set
|
||||
Targets []string `json:"targets"`
|
||||
Title string `json:"title"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1ExtensionsAddedComponents creates a new V0alpha1ExtensionsAddedComponents object.
|
||||
func NewV0alpha1ExtensionsAddedComponents() *V0alpha1ExtensionsAddedComponents {
|
||||
return &V0alpha1ExtensionsAddedComponents{
|
||||
Targets: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1ExtensionsAddedLinks struct {
|
||||
// +listType=set
|
||||
Targets []string `json:"targets"`
|
||||
Title string `json:"title"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1ExtensionsAddedLinks creates a new V0alpha1ExtensionsAddedLinks object.
|
||||
func NewV0alpha1ExtensionsAddedLinks() *V0alpha1ExtensionsAddedLinks {
|
||||
return &V0alpha1ExtensionsAddedLinks{
|
||||
Targets: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1ExtensionsExposedComponents struct {
|
||||
Id string `json:"id"`
|
||||
Title *string `json:"title,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1ExtensionsExposedComponents creates a new V0alpha1ExtensionsExposedComponents object.
|
||||
func NewV0alpha1ExtensionsExposedComponents() *V0alpha1ExtensionsExposedComponents {
|
||||
return &V0alpha1ExtensionsExposedComponents{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1ExtensionsExtensionPoints struct {
|
||||
Id string `json:"id"`
|
||||
Title *string `json:"title,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// NewV0alpha1ExtensionsExtensionPoints creates a new V0alpha1ExtensionsExtensionPoints object.
|
||||
func NewV0alpha1ExtensionsExtensionPoints() *V0alpha1ExtensionsExtensionPoints {
|
||||
return &V0alpha1ExtensionsExtensionPoints{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type IncludeType string
|
||||
|
||||
const (
|
||||
IncludeTypeDashboard IncludeType = "dashboard"
|
||||
IncludeTypePage IncludeType = "page"
|
||||
IncludeTypePanel IncludeType = "panel"
|
||||
IncludeTypeDatasource IncludeType = "datasource"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type IncludeRole string
|
||||
|
||||
const (
|
||||
IncludeRoleAdmin IncludeRole = "Admin"
|
||||
IncludeRoleEditor IncludeRole = "Editor"
|
||||
IncludeRoleViewer IncludeRole = "Viewer"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type GetMetaType string
|
||||
|
||||
const (
|
||||
GetMetaTypeApp GetMetaType = "app"
|
||||
GetMetaTypeDatasource GetMetaType = "datasource"
|
||||
GetMetaTypePanel GetMetaType = "panel"
|
||||
GetMetaTypeRenderer GetMetaType = "renderer"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type GetMetaCategory string
|
||||
|
||||
const (
|
||||
GetMetaCategoryTsdb GetMetaCategory = "tsdb"
|
||||
GetMetaCategoryLogging GetMetaCategory = "logging"
|
||||
GetMetaCategoryCloud GetMetaCategory = "cloud"
|
||||
GetMetaCategoryTracing GetMetaCategory = "tracing"
|
||||
GetMetaCategoryProfiling GetMetaCategory = "profiling"
|
||||
GetMetaCategorySql GetMetaCategory = "sql"
|
||||
GetMetaCategoryEnterprise GetMetaCategory = "enterprise"
|
||||
GetMetaCategoryIot GetMetaCategory = "iot"
|
||||
GetMetaCategoryOther GetMetaCategory = "other"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type GetMetaState string
|
||||
|
||||
const (
|
||||
GetMetaStateAlpha GetMetaState = "alpha"
|
||||
GetMetaStateBeta GetMetaState = "beta"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type V0alpha1DependenciesPluginsType string
|
||||
|
||||
const (
|
||||
V0alpha1DependenciesPluginsTypeApp V0alpha1DependenciesPluginsType = "app"
|
||||
V0alpha1DependenciesPluginsTypeDatasource V0alpha1DependenciesPluginsType = "datasource"
|
||||
V0alpha1DependenciesPluginsTypePanel V0alpha1DependenciesPluginsType = "panel"
|
||||
)
|
||||
+4
-4
@@ -9,7 +9,7 @@ import (
|
||||
// metadata contains embedded CommonMetadata and can be extended with custom string fields
|
||||
// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
|
||||
// without external reference as using the CommonMetadata reference breaks thema codegen.
|
||||
type PluginMetaMetadata struct {
|
||||
type PluginMetadata struct {
|
||||
UpdateTimestamp time.Time `json:"updateTimestamp"`
|
||||
CreatedBy string `json:"createdBy"`
|
||||
Uid string `json:"uid"`
|
||||
@@ -22,9 +22,9 @@ type PluginMetaMetadata struct {
|
||||
Labels map[string]string `json:"labels"`
|
||||
}
|
||||
|
||||
// NewPluginMetaMetadata creates a new PluginMetaMetadata object.
|
||||
func NewPluginMetaMetadata() *PluginMetaMetadata {
|
||||
return &PluginMetaMetadata{
|
||||
// NewPluginMetadata creates a new PluginMetadata object.
|
||||
func NewPluginMetadata() *PluginMetadata {
|
||||
return &PluginMetadata{
|
||||
Finalizers: []string{},
|
||||
Labels: map[string]string{},
|
||||
}
|
||||
+51
-51
@@ -15,22 +15,22 @@ import (
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMeta struct {
|
||||
type Plugin struct {
|
||||
metav1.TypeMeta `json:",inline" yaml:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
|
||||
|
||||
// Spec is the spec of the PluginMeta
|
||||
Spec PluginMetaSpec `json:"spec" yaml:"spec"`
|
||||
// Spec is the spec of the Plugin
|
||||
Spec PluginSpec `json:"spec" yaml:"spec"`
|
||||
|
||||
Status PluginMetaStatus `json:"status" yaml:"status"`
|
||||
Status PluginStatus `json:"status" yaml:"status"`
|
||||
}
|
||||
|
||||
func (o *PluginMeta) GetSpec() any {
|
||||
func (o *Plugin) GetSpec() any {
|
||||
return o.Spec
|
||||
}
|
||||
|
||||
func (o *PluginMeta) SetSpec(spec any) error {
|
||||
cast, ok := spec.(PluginMetaSpec)
|
||||
func (o *Plugin) SetSpec(spec any) error {
|
||||
cast, ok := spec.(PluginSpec)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
|
||||
}
|
||||
@@ -38,13 +38,13 @@ func (o *PluginMeta) SetSpec(spec any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *PluginMeta) GetSubresources() map[string]any {
|
||||
func (o *Plugin) GetSubresources() map[string]any {
|
||||
return map[string]any{
|
||||
"status": o.Status,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginMeta) GetSubresource(name string) (any, bool) {
|
||||
func (o *Plugin) GetSubresource(name string) (any, bool) {
|
||||
switch name {
|
||||
case "status":
|
||||
return o.Status, true
|
||||
@@ -53,12 +53,12 @@ func (o *PluginMeta) GetSubresource(name string) (any, bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginMeta) SetSubresource(name string, value any) error {
|
||||
func (o *Plugin) SetSubresource(name string, value any) error {
|
||||
switch name {
|
||||
case "status":
|
||||
cast, ok := value.(PluginMetaStatus)
|
||||
cast, ok := value.(PluginStatus)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot set status type %#v, not of type PluginMetaStatus", value)
|
||||
return fmt.Errorf("cannot set status type %#v, not of type PluginStatus", value)
|
||||
}
|
||||
o.Status = cast
|
||||
return nil
|
||||
@@ -67,7 +67,7 @@ func (o *PluginMeta) SetSubresource(name string, value any) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginMeta) GetStaticMetadata() resource.StaticMetadata {
|
||||
func (o *Plugin) GetStaticMetadata() resource.StaticMetadata {
|
||||
gvk := o.GroupVersionKind()
|
||||
return resource.StaticMetadata{
|
||||
Name: o.ObjectMeta.Name,
|
||||
@@ -78,7 +78,7 @@ func (o *PluginMeta) GetStaticMetadata() resource.StaticMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginMeta) SetStaticMetadata(metadata resource.StaticMetadata) {
|
||||
func (o *Plugin) SetStaticMetadata(metadata resource.StaticMetadata) {
|
||||
o.Name = metadata.Name
|
||||
o.Namespace = metadata.Namespace
|
||||
o.SetGroupVersionKind(schema.GroupVersionKind{
|
||||
@@ -88,7 +88,7 @@ func (o *PluginMeta) SetStaticMetadata(metadata resource.StaticMetadata) {
|
||||
})
|
||||
}
|
||||
|
||||
func (o *PluginMeta) GetCommonMetadata() resource.CommonMetadata {
|
||||
func (o *Plugin) GetCommonMetadata() resource.CommonMetadata {
|
||||
dt := o.DeletionTimestamp
|
||||
var deletionTimestamp *time.Time
|
||||
if dt != nil {
|
||||
@@ -120,7 +120,7 @@ func (o *PluginMeta) GetCommonMetadata() resource.CommonMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginMeta) SetCommonMetadata(metadata resource.CommonMetadata) {
|
||||
func (o *Plugin) SetCommonMetadata(metadata resource.CommonMetadata) {
|
||||
o.UID = types.UID(metadata.UID)
|
||||
o.ResourceVersion = metadata.ResourceVersion
|
||||
o.Generation = metadata.Generation
|
||||
@@ -165,7 +165,7 @@ func (o *PluginMeta) SetCommonMetadata(metadata resource.CommonMetadata) {
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginMeta) GetCreatedBy() string {
|
||||
func (o *Plugin) GetCreatedBy() string {
|
||||
if o.ObjectMeta.Annotations == nil {
|
||||
o.ObjectMeta.Annotations = make(map[string]string)
|
||||
}
|
||||
@@ -173,7 +173,7 @@ func (o *PluginMeta) GetCreatedBy() string {
|
||||
return o.ObjectMeta.Annotations["grafana.com/createdBy"]
|
||||
}
|
||||
|
||||
func (o *PluginMeta) SetCreatedBy(createdBy string) {
|
||||
func (o *Plugin) SetCreatedBy(createdBy string) {
|
||||
if o.ObjectMeta.Annotations == nil {
|
||||
o.ObjectMeta.Annotations = make(map[string]string)
|
||||
}
|
||||
@@ -181,7 +181,7 @@ func (o *PluginMeta) SetCreatedBy(createdBy string) {
|
||||
o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
|
||||
}
|
||||
|
||||
func (o *PluginMeta) GetUpdateTimestamp() time.Time {
|
||||
func (o *Plugin) GetUpdateTimestamp() time.Time {
|
||||
if o.ObjectMeta.Annotations == nil {
|
||||
o.ObjectMeta.Annotations = make(map[string]string)
|
||||
}
|
||||
@@ -190,7 +190,7 @@ func (o *PluginMeta) GetUpdateTimestamp() time.Time {
|
||||
return parsed
|
||||
}
|
||||
|
||||
func (o *PluginMeta) SetUpdateTimestamp(updateTimestamp time.Time) {
|
||||
func (o *Plugin) SetUpdateTimestamp(updateTimestamp time.Time) {
|
||||
if o.ObjectMeta.Annotations == nil {
|
||||
o.ObjectMeta.Annotations = make(map[string]string)
|
||||
}
|
||||
@@ -198,7 +198,7 @@ func (o *PluginMeta) SetUpdateTimestamp(updateTimestamp time.Time) {
|
||||
o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
func (o *PluginMeta) GetUpdatedBy() string {
|
||||
func (o *Plugin) GetUpdatedBy() string {
|
||||
if o.ObjectMeta.Annotations == nil {
|
||||
o.ObjectMeta.Annotations = make(map[string]string)
|
||||
}
|
||||
@@ -206,7 +206,7 @@ func (o *PluginMeta) GetUpdatedBy() string {
|
||||
return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
|
||||
}
|
||||
|
||||
func (o *PluginMeta) SetUpdatedBy(updatedBy string) {
|
||||
func (o *Plugin) SetUpdatedBy(updatedBy string) {
|
||||
if o.ObjectMeta.Annotations == nil {
|
||||
o.ObjectMeta.Annotations = make(map[string]string)
|
||||
}
|
||||
@@ -214,21 +214,21 @@ func (o *PluginMeta) SetUpdatedBy(updatedBy string) {
|
||||
o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
|
||||
}
|
||||
|
||||
func (o *PluginMeta) Copy() resource.Object {
|
||||
func (o *Plugin) Copy() resource.Object {
|
||||
return resource.CopyObject(o)
|
||||
}
|
||||
|
||||
func (o *PluginMeta) DeepCopyObject() runtime.Object {
|
||||
func (o *Plugin) DeepCopyObject() runtime.Object {
|
||||
return o.Copy()
|
||||
}
|
||||
|
||||
func (o *PluginMeta) DeepCopy() *PluginMeta {
|
||||
cpy := &PluginMeta{}
|
||||
func (o *Plugin) DeepCopy() *Plugin {
|
||||
cpy := &Plugin{}
|
||||
o.DeepCopyInto(cpy)
|
||||
return cpy
|
||||
}
|
||||
|
||||
func (o *PluginMeta) DeepCopyInto(dst *PluginMeta) {
|
||||
func (o *Plugin) DeepCopyInto(dst *Plugin) {
|
||||
dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
|
||||
dst.TypeMeta.Kind = o.TypeMeta.Kind
|
||||
o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
|
||||
@@ -237,34 +237,34 @@ func (o *PluginMeta) DeepCopyInto(dst *PluginMeta) {
|
||||
}
|
||||
|
||||
// Interface compliance compile-time check
|
||||
var _ resource.Object = &PluginMeta{}
|
||||
var _ resource.Object = &Plugin{}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaList struct {
|
||||
type PluginList struct {
|
||||
metav1.TypeMeta `json:",inline" yaml:",inline"`
|
||||
metav1.ListMeta `json:"metadata" yaml:"metadata"`
|
||||
Items []PluginMeta `json:"items" yaml:"items"`
|
||||
Items []Plugin `json:"items" yaml:"items"`
|
||||
}
|
||||
|
||||
func (o *PluginMetaList) DeepCopyObject() runtime.Object {
|
||||
func (o *PluginList) DeepCopyObject() runtime.Object {
|
||||
return o.Copy()
|
||||
}
|
||||
|
||||
func (o *PluginMetaList) Copy() resource.ListObject {
|
||||
cpy := &PluginMetaList{
|
||||
func (o *PluginList) Copy() resource.ListObject {
|
||||
cpy := &PluginList{
|
||||
TypeMeta: o.TypeMeta,
|
||||
Items: make([]PluginMeta, len(o.Items)),
|
||||
Items: make([]Plugin, len(o.Items)),
|
||||
}
|
||||
o.ListMeta.DeepCopyInto(&cpy.ListMeta)
|
||||
for i := 0; i < len(o.Items); i++ {
|
||||
if item, ok := o.Items[i].Copy().(*PluginMeta); ok {
|
||||
if item, ok := o.Items[i].Copy().(*Plugin); ok {
|
||||
cpy.Items[i] = *item
|
||||
}
|
||||
}
|
||||
return cpy
|
||||
}
|
||||
|
||||
func (o *PluginMetaList) GetItems() []resource.Object {
|
||||
func (o *PluginList) GetItems() []resource.Object {
|
||||
items := make([]resource.Object, len(o.Items))
|
||||
for i := 0; i < len(o.Items); i++ {
|
||||
items[i] = &o.Items[i]
|
||||
@@ -272,48 +272,48 @@ func (o *PluginMetaList) GetItems() []resource.Object {
|
||||
return items
|
||||
}
|
||||
|
||||
func (o *PluginMetaList) SetItems(items []resource.Object) {
|
||||
o.Items = make([]PluginMeta, len(items))
|
||||
func (o *PluginList) SetItems(items []resource.Object) {
|
||||
o.Items = make([]Plugin, len(items))
|
||||
for i := 0; i < len(items); i++ {
|
||||
o.Items[i] = *items[i].(*PluginMeta)
|
||||
o.Items[i] = *items[i].(*Plugin)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginMetaList) DeepCopy() *PluginMetaList {
|
||||
cpy := &PluginMetaList{}
|
||||
func (o *PluginList) DeepCopy() *PluginList {
|
||||
cpy := &PluginList{}
|
||||
o.DeepCopyInto(cpy)
|
||||
return cpy
|
||||
}
|
||||
|
||||
func (o *PluginMetaList) DeepCopyInto(dst *PluginMetaList) {
|
||||
func (o *PluginList) DeepCopyInto(dst *PluginList) {
|
||||
resource.CopyObjectInto(dst, o)
|
||||
}
|
||||
|
||||
// Interface compliance compile-time check
|
||||
var _ resource.ListObject = &PluginMetaList{}
|
||||
var _ resource.ListObject = &PluginList{}
|
||||
|
||||
// Copy methods for all subresource types
|
||||
|
||||
// DeepCopy creates a full deep copy of Spec
|
||||
func (s *PluginMetaSpec) DeepCopy() *PluginMetaSpec {
|
||||
cpy := &PluginMetaSpec{}
|
||||
func (s *PluginSpec) DeepCopy() *PluginSpec {
|
||||
cpy := &PluginSpec{}
|
||||
s.DeepCopyInto(cpy)
|
||||
return cpy
|
||||
}
|
||||
|
||||
// DeepCopyInto deep copies Spec into another Spec object
|
||||
func (s *PluginMetaSpec) DeepCopyInto(dst *PluginMetaSpec) {
|
||||
func (s *PluginSpec) DeepCopyInto(dst *PluginSpec) {
|
||||
resource.CopyObjectInto(dst, s)
|
||||
}
|
||||
|
||||
// DeepCopy creates a full deep copy of PluginMetaStatus
|
||||
func (s *PluginMetaStatus) DeepCopy() *PluginMetaStatus {
|
||||
cpy := &PluginMetaStatus{}
|
||||
// DeepCopy creates a full deep copy of PluginStatus
|
||||
func (s *PluginStatus) DeepCopy() *PluginStatus {
|
||||
cpy := &PluginStatus{}
|
||||
s.DeepCopyInto(cpy)
|
||||
return cpy
|
||||
}
|
||||
|
||||
// DeepCopyInto deep copies PluginMetaStatus into another PluginMetaStatus object
|
||||
func (s *PluginMetaStatus) DeepCopyInto(dst *PluginMetaStatus) {
|
||||
// DeepCopyInto deep copies PluginStatus into another PluginStatus object
|
||||
func (s *PluginStatus) DeepCopyInto(dst *PluginStatus) {
|
||||
resource.CopyObjectInto(dst, s)
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Code generated by grafana-app-sdk. DO NOT EDIT.
|
||||
//
|
||||
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
)
|
||||
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaPlugin = resource.NewSimpleSchema("plugins.grafana.app", "v0alpha1", &Plugin{}, &PluginList{}, resource.WithKind("Plugin"),
|
||||
resource.WithPlural("plugins"), resource.WithScope(resource.NamespacedScope))
|
||||
kindPlugin = resource.Kind{
|
||||
Schema: schemaPlugin,
|
||||
Codecs: map[resource.KindEncoding]resource.Codec{
|
||||
resource.KindEncodingJSON: &PluginJSONCodec{},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// Kind returns a resource.Kind for this Schema with a JSON codec
|
||||
func PluginKind() resource.Kind {
|
||||
return kindPlugin
|
||||
}
|
||||
|
||||
// Schema returns a resource.SimpleSchema representation of Plugin
|
||||
func PluginSchema() *resource.SimpleSchema {
|
||||
return schemaPlugin
|
||||
}
|
||||
|
||||
// Interface compliance checks
|
||||
var _ resource.Schema = kindPlugin
|
||||
@@ -0,0 +1,25 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
|
||||
package v0alpha1
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginSpec struct {
|
||||
Id string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Url *string `json:"url,omitempty"`
|
||||
Class PluginSpecClass `json:"class"`
|
||||
}
|
||||
|
||||
// NewPluginSpec creates a new PluginSpec object.
|
||||
func NewPluginSpec() *PluginSpec {
|
||||
return &PluginSpec{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginSpecClass string
|
||||
|
||||
const (
|
||||
PluginSpecClassCore PluginSpecClass = "core"
|
||||
PluginSpecClassExternal PluginSpecClass = "external"
|
||||
PluginSpecClassCdn PluginSpecClass = "cdn"
|
||||
)
|
||||
+14
-14
@@ -3,42 +3,42 @@
|
||||
package v0alpha1
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type ReceiverstatusOperatorState struct {
|
||||
type PluginstatusOperatorState struct {
|
||||
// lastEvaluation is the ResourceVersion last evaluated
|
||||
LastEvaluation string `json:"lastEvaluation"`
|
||||
// state describes the state of the lastEvaluation.
|
||||
// It is limited to three possible states for machine evaluation.
|
||||
State ReceiverStatusOperatorStateState `json:"state"`
|
||||
State PluginStatusOperatorStateState `json:"state"`
|
||||
// descriptiveState is an optional more descriptive state field which has no requirements on format
|
||||
DescriptiveState *string `json:"descriptiveState,omitempty"`
|
||||
// details contains any extra information that is operator-specific
|
||||
Details map[string]interface{} `json:"details,omitempty"`
|
||||
}
|
||||
|
||||
// NewReceiverstatusOperatorState creates a new ReceiverstatusOperatorState object.
|
||||
func NewReceiverstatusOperatorState() *ReceiverstatusOperatorState {
|
||||
return &ReceiverstatusOperatorState{}
|
||||
// NewPluginstatusOperatorState creates a new PluginstatusOperatorState object.
|
||||
func NewPluginstatusOperatorState() *PluginstatusOperatorState {
|
||||
return &PluginstatusOperatorState{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type ReceiverStatus struct {
|
||||
type PluginStatus struct {
|
||||
// operatorStates is a map of operator ID to operator state evaluations.
|
||||
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
|
||||
OperatorStates map[string]ReceiverstatusOperatorState `json:"operatorStates,omitempty"`
|
||||
OperatorStates map[string]PluginstatusOperatorState `json:"operatorStates,omitempty"`
|
||||
// additionalFields is reserved for future use
|
||||
AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
|
||||
}
|
||||
|
||||
// NewReceiverStatus creates a new ReceiverStatus object.
|
||||
func NewReceiverStatus() *ReceiverStatus {
|
||||
return &ReceiverStatus{}
|
||||
// NewPluginStatus creates a new PluginStatus object.
|
||||
func NewPluginStatus() *PluginStatus {
|
||||
return &PluginStatus{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type ReceiverStatusOperatorStateState string
|
||||
type PluginStatusOperatorStateState string
|
||||
|
||||
const (
|
||||
ReceiverStatusOperatorStateStateSuccess ReceiverStatusOperatorStateState = "success"
|
||||
ReceiverStatusOperatorStateStateInProgress ReceiverStatusOperatorStateState = "in_progress"
|
||||
ReceiverStatusOperatorStateStateFailed ReceiverStatusOperatorStateState = "failed"
|
||||
PluginStatusOperatorStateStateSuccess PluginStatusOperatorStateState = "success"
|
||||
PluginStatusOperatorStateStateInProgress PluginStatusOperatorStateState = "in_progress"
|
||||
PluginStatusOperatorStateStateFailed PluginStatusOperatorStateState = "failed"
|
||||
)
|
||||
@@ -1,99 +0,0 @@
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type PluginInstallClient struct {
|
||||
client *resource.TypedClient[*PluginInstall, *PluginInstallList]
|
||||
}
|
||||
|
||||
func NewPluginInstallClient(client resource.Client) *PluginInstallClient {
|
||||
return &PluginInstallClient{
|
||||
client: resource.NewTypedClient[*PluginInstall, *PluginInstallList](client, PluginInstallKind()),
|
||||
}
|
||||
}
|
||||
|
||||
func NewPluginInstallClientFromGenerator(generator resource.ClientGenerator) (*PluginInstallClient, error) {
|
||||
c, err := generator.ClientFor(PluginInstallKind())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewPluginInstallClient(c), nil
|
||||
}
|
||||
|
||||
func (c *PluginInstallClient) Get(ctx context.Context, identifier resource.Identifier) (*PluginInstall, error) {
|
||||
return c.client.Get(ctx, identifier)
|
||||
}
|
||||
|
||||
func (c *PluginInstallClient) List(ctx context.Context, namespace string, opts resource.ListOptions) (*PluginInstallList, error) {
|
||||
return c.client.List(ctx, namespace, opts)
|
||||
}
|
||||
|
||||
func (c *PluginInstallClient) ListAll(ctx context.Context, namespace string, opts resource.ListOptions) (*PluginInstallList, error) {
|
||||
resp, err := c.client.List(ctx, namespace, resource.ListOptions{
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Limit: opts.Limit,
|
||||
LabelFilters: opts.LabelFilters,
|
||||
FieldSelectors: opts.FieldSelectors,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for resp.GetContinue() != "" {
|
||||
page, err := c.client.List(ctx, namespace, resource.ListOptions{
|
||||
Continue: resp.GetContinue(),
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Limit: opts.Limit,
|
||||
LabelFilters: opts.LabelFilters,
|
||||
FieldSelectors: opts.FieldSelectors,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.SetContinue(page.GetContinue())
|
||||
resp.SetResourceVersion(page.GetResourceVersion())
|
||||
resp.SetItems(append(resp.GetItems(), page.GetItems()...))
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *PluginInstallClient) Create(ctx context.Context, obj *PluginInstall, opts resource.CreateOptions) (*PluginInstall, error) {
|
||||
// Make sure apiVersion and kind are set
|
||||
obj.APIVersion = GroupVersion.Identifier()
|
||||
obj.Kind = PluginInstallKind().Kind()
|
||||
return c.client.Create(ctx, obj, opts)
|
||||
}
|
||||
|
||||
func (c *PluginInstallClient) Update(ctx context.Context, obj *PluginInstall, opts resource.UpdateOptions) (*PluginInstall, error) {
|
||||
return c.client.Update(ctx, obj, opts)
|
||||
}
|
||||
|
||||
func (c *PluginInstallClient) Patch(ctx context.Context, identifier resource.Identifier, req resource.PatchRequest, opts resource.PatchOptions) (*PluginInstall, error) {
|
||||
return c.client.Patch(ctx, identifier, req, opts)
|
||||
}
|
||||
|
||||
func (c *PluginInstallClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus PluginInstallStatus, opts resource.UpdateOptions) (*PluginInstall, error) {
|
||||
return c.client.Update(ctx, &PluginInstall{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: PluginInstallKind().Kind(),
|
||||
APIVersion: GroupVersion.Identifier(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Namespace: identifier.Namespace,
|
||||
Name: identifier.Name,
|
||||
},
|
||||
Status: newStatus,
|
||||
}, resource.UpdateOptions{
|
||||
Subresource: "status",
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *PluginInstallClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
|
||||
return c.client.Delete(ctx, identifier, opts)
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
//
|
||||
// Code generated by grafana-app-sdk. DO NOT EDIT.
|
||||
//
|
||||
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
)
|
||||
|
||||
// PluginInstallJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
|
||||
type PluginInstallJSONCodec struct{}
|
||||
|
||||
// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
|
||||
func (*PluginInstallJSONCodec) Read(reader io.Reader, into resource.Object) error {
|
||||
return json.NewDecoder(reader).Decode(into)
|
||||
}
|
||||
|
||||
// Write writes JSON-encoded bytes into `writer` marshaled from `from`
|
||||
func (*PluginInstallJSONCodec) Write(writer io.Writer, from resource.Object) error {
|
||||
return json.NewEncoder(writer).Encode(from)
|
||||
}
|
||||
|
||||
// Interface compliance checks
|
||||
var _ resource.Codec = &PluginInstallJSONCodec{}
|
||||
@@ -1,31 +0,0 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
time "time"
|
||||
)
|
||||
|
||||
// metadata contains embedded CommonMetadata and can be extended with custom string fields
|
||||
// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
|
||||
// without external reference as using the CommonMetadata reference breaks thema codegen.
|
||||
type PluginInstallMetadata struct {
|
||||
UpdateTimestamp time.Time `json:"updateTimestamp"`
|
||||
CreatedBy string `json:"createdBy"`
|
||||
Uid string `json:"uid"`
|
||||
CreationTimestamp time.Time `json:"creationTimestamp"`
|
||||
DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
|
||||
Finalizers []string `json:"finalizers"`
|
||||
ResourceVersion string `json:"resourceVersion"`
|
||||
Generation int64 `json:"generation"`
|
||||
UpdatedBy string `json:"updatedBy"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
}
|
||||
|
||||
// NewPluginInstallMetadata creates a new PluginInstallMetadata object.
|
||||
func NewPluginInstallMetadata() *PluginInstallMetadata {
|
||||
return &PluginInstallMetadata{
|
||||
Finalizers: []string{},
|
||||
Labels: map[string]string{},
|
||||
}
|
||||
}
|
||||
@@ -1,319 +0,0 @@
|
||||
//
|
||||
// Code generated by grafana-app-sdk. DO NOT EDIT.
|
||||
//
|
||||
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"time"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginInstall struct {
|
||||
metav1.TypeMeta `json:",inline" yaml:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
|
||||
|
||||
// Spec is the spec of the PluginInstall
|
||||
Spec PluginInstallSpec `json:"spec" yaml:"spec"`
|
||||
|
||||
Status PluginInstallStatus `json:"status" yaml:"status"`
|
||||
}
|
||||
|
||||
func (o *PluginInstall) GetSpec() any {
|
||||
return o.Spec
|
||||
}
|
||||
|
||||
func (o *PluginInstall) SetSpec(spec any) error {
|
||||
cast, ok := spec.(PluginInstallSpec)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
|
||||
}
|
||||
o.Spec = cast
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *PluginInstall) GetSubresources() map[string]any {
|
||||
return map[string]any{
|
||||
"status": o.Status,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginInstall) GetSubresource(name string) (any, bool) {
|
||||
switch name {
|
||||
case "status":
|
||||
return o.Status, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginInstall) SetSubresource(name string, value any) error {
|
||||
switch name {
|
||||
case "status":
|
||||
cast, ok := value.(PluginInstallStatus)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot set status type %#v, not of type PluginInstallStatus", value)
|
||||
}
|
||||
o.Status = cast
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("subresource '%s' does not exist", name)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginInstall) GetStaticMetadata() resource.StaticMetadata {
|
||||
gvk := o.GroupVersionKind()
|
||||
return resource.StaticMetadata{
|
||||
Name: o.ObjectMeta.Name,
|
||||
Namespace: o.ObjectMeta.Namespace,
|
||||
Group: gvk.Group,
|
||||
Version: gvk.Version,
|
||||
Kind: gvk.Kind,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginInstall) SetStaticMetadata(metadata resource.StaticMetadata) {
|
||||
o.Name = metadata.Name
|
||||
o.Namespace = metadata.Namespace
|
||||
o.SetGroupVersionKind(schema.GroupVersionKind{
|
||||
Group: metadata.Group,
|
||||
Version: metadata.Version,
|
||||
Kind: metadata.Kind,
|
||||
})
|
||||
}
|
||||
|
||||
func (o *PluginInstall) GetCommonMetadata() resource.CommonMetadata {
|
||||
dt := o.DeletionTimestamp
|
||||
var deletionTimestamp *time.Time
|
||||
if dt != nil {
|
||||
deletionTimestamp = &dt.Time
|
||||
}
|
||||
// Legacy ExtraFields support
|
||||
extraFields := make(map[string]any)
|
||||
if o.Annotations != nil {
|
||||
extraFields["annotations"] = o.Annotations
|
||||
}
|
||||
if o.ManagedFields != nil {
|
||||
extraFields["managedFields"] = o.ManagedFields
|
||||
}
|
||||
if o.OwnerReferences != nil {
|
||||
extraFields["ownerReferences"] = o.OwnerReferences
|
||||
}
|
||||
return resource.CommonMetadata{
|
||||
UID: string(o.UID),
|
||||
ResourceVersion: o.ResourceVersion,
|
||||
Generation: o.Generation,
|
||||
Labels: o.Labels,
|
||||
CreationTimestamp: o.CreationTimestamp.Time,
|
||||
DeletionTimestamp: deletionTimestamp,
|
||||
Finalizers: o.Finalizers,
|
||||
UpdateTimestamp: o.GetUpdateTimestamp(),
|
||||
CreatedBy: o.GetCreatedBy(),
|
||||
UpdatedBy: o.GetUpdatedBy(),
|
||||
ExtraFields: extraFields,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginInstall) SetCommonMetadata(metadata resource.CommonMetadata) {
|
||||
o.UID = types.UID(metadata.UID)
|
||||
o.ResourceVersion = metadata.ResourceVersion
|
||||
o.Generation = metadata.Generation
|
||||
o.Labels = metadata.Labels
|
||||
o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
|
||||
if metadata.DeletionTimestamp != nil {
|
||||
dt := metav1.NewTime(*metadata.DeletionTimestamp)
|
||||
o.DeletionTimestamp = &dt
|
||||
} else {
|
||||
o.DeletionTimestamp = nil
|
||||
}
|
||||
o.Finalizers = metadata.Finalizers
|
||||
if o.Annotations == nil {
|
||||
o.Annotations = make(map[string]string)
|
||||
}
|
||||
if !metadata.UpdateTimestamp.IsZero() {
|
||||
o.SetUpdateTimestamp(metadata.UpdateTimestamp)
|
||||
}
|
||||
if metadata.CreatedBy != "" {
|
||||
o.SetCreatedBy(metadata.CreatedBy)
|
||||
}
|
||||
if metadata.UpdatedBy != "" {
|
||||
o.SetUpdatedBy(metadata.UpdatedBy)
|
||||
}
|
||||
// Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
|
||||
if metadata.ExtraFields != nil {
|
||||
if annotations, ok := metadata.ExtraFields["annotations"]; ok {
|
||||
if cast, ok := annotations.(map[string]string); ok {
|
||||
o.Annotations = cast
|
||||
}
|
||||
}
|
||||
if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
|
||||
if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
|
||||
o.ManagedFields = cast
|
||||
}
|
||||
}
|
||||
if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
|
||||
if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
|
||||
o.OwnerReferences = cast
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginInstall) GetCreatedBy() string {
|
||||
if o.ObjectMeta.Annotations == nil {
|
||||
o.ObjectMeta.Annotations = make(map[string]string)
|
||||
}
|
||||
|
||||
return o.ObjectMeta.Annotations["grafana.com/createdBy"]
|
||||
}
|
||||
|
||||
func (o *PluginInstall) SetCreatedBy(createdBy string) {
|
||||
if o.ObjectMeta.Annotations == nil {
|
||||
o.ObjectMeta.Annotations = make(map[string]string)
|
||||
}
|
||||
|
||||
o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
|
||||
}
|
||||
|
||||
func (o *PluginInstall) GetUpdateTimestamp() time.Time {
|
||||
if o.ObjectMeta.Annotations == nil {
|
||||
o.ObjectMeta.Annotations = make(map[string]string)
|
||||
}
|
||||
|
||||
parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
|
||||
return parsed
|
||||
}
|
||||
|
||||
func (o *PluginInstall) SetUpdateTimestamp(updateTimestamp time.Time) {
|
||||
if o.ObjectMeta.Annotations == nil {
|
||||
o.ObjectMeta.Annotations = make(map[string]string)
|
||||
}
|
||||
|
||||
o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
func (o *PluginInstall) GetUpdatedBy() string {
|
||||
if o.ObjectMeta.Annotations == nil {
|
||||
o.ObjectMeta.Annotations = make(map[string]string)
|
||||
}
|
||||
|
||||
return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
|
||||
}
|
||||
|
||||
func (o *PluginInstall) SetUpdatedBy(updatedBy string) {
|
||||
if o.ObjectMeta.Annotations == nil {
|
||||
o.ObjectMeta.Annotations = make(map[string]string)
|
||||
}
|
||||
|
||||
o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
|
||||
}
|
||||
|
||||
func (o *PluginInstall) Copy() resource.Object {
|
||||
return resource.CopyObject(o)
|
||||
}
|
||||
|
||||
func (o *PluginInstall) DeepCopyObject() runtime.Object {
|
||||
return o.Copy()
|
||||
}
|
||||
|
||||
func (o *PluginInstall) DeepCopy() *PluginInstall {
|
||||
cpy := &PluginInstall{}
|
||||
o.DeepCopyInto(cpy)
|
||||
return cpy
|
||||
}
|
||||
|
||||
func (o *PluginInstall) DeepCopyInto(dst *PluginInstall) {
|
||||
dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
|
||||
dst.TypeMeta.Kind = o.TypeMeta.Kind
|
||||
o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
|
||||
o.Spec.DeepCopyInto(&dst.Spec)
|
||||
o.Status.DeepCopyInto(&dst.Status)
|
||||
}
|
||||
|
||||
// Interface compliance compile-time check
|
||||
var _ resource.Object = &PluginInstall{}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginInstallList struct {
|
||||
metav1.TypeMeta `json:",inline" yaml:",inline"`
|
||||
metav1.ListMeta `json:"metadata" yaml:"metadata"`
|
||||
Items []PluginInstall `json:"items" yaml:"items"`
|
||||
}
|
||||
|
||||
func (o *PluginInstallList) DeepCopyObject() runtime.Object {
|
||||
return o.Copy()
|
||||
}
|
||||
|
||||
func (o *PluginInstallList) Copy() resource.ListObject {
|
||||
cpy := &PluginInstallList{
|
||||
TypeMeta: o.TypeMeta,
|
||||
Items: make([]PluginInstall, len(o.Items)),
|
||||
}
|
||||
o.ListMeta.DeepCopyInto(&cpy.ListMeta)
|
||||
for i := 0; i < len(o.Items); i++ {
|
||||
if item, ok := o.Items[i].Copy().(*PluginInstall); ok {
|
||||
cpy.Items[i] = *item
|
||||
}
|
||||
}
|
||||
return cpy
|
||||
}
|
||||
|
||||
func (o *PluginInstallList) GetItems() []resource.Object {
|
||||
items := make([]resource.Object, len(o.Items))
|
||||
for i := 0; i < len(o.Items); i++ {
|
||||
items[i] = &o.Items[i]
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func (o *PluginInstallList) SetItems(items []resource.Object) {
|
||||
o.Items = make([]PluginInstall, len(items))
|
||||
for i := 0; i < len(items); i++ {
|
||||
o.Items[i] = *items[i].(*PluginInstall)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PluginInstallList) DeepCopy() *PluginInstallList {
|
||||
cpy := &PluginInstallList{}
|
||||
o.DeepCopyInto(cpy)
|
||||
return cpy
|
||||
}
|
||||
|
||||
func (o *PluginInstallList) DeepCopyInto(dst *PluginInstallList) {
|
||||
resource.CopyObjectInto(dst, o)
|
||||
}
|
||||
|
||||
// Interface compliance compile-time check
|
||||
var _ resource.ListObject = &PluginInstallList{}
|
||||
|
||||
// Copy methods for all subresource types
|
||||
|
||||
// DeepCopy creates a full deep copy of Spec
|
||||
func (s *PluginInstallSpec) DeepCopy() *PluginInstallSpec {
|
||||
cpy := &PluginInstallSpec{}
|
||||
s.DeepCopyInto(cpy)
|
||||
return cpy
|
||||
}
|
||||
|
||||
// DeepCopyInto deep copies Spec into another Spec object
|
||||
func (s *PluginInstallSpec) DeepCopyInto(dst *PluginInstallSpec) {
|
||||
resource.CopyObjectInto(dst, s)
|
||||
}
|
||||
|
||||
// DeepCopy creates a full deep copy of PluginInstallStatus
|
||||
func (s *PluginInstallStatus) DeepCopy() *PluginInstallStatus {
|
||||
cpy := &PluginInstallStatus{}
|
||||
s.DeepCopyInto(cpy)
|
||||
return cpy
|
||||
}
|
||||
|
||||
// DeepCopyInto deep copies PluginInstallStatus into another PluginInstallStatus object
|
||||
func (s *PluginInstallStatus) DeepCopyInto(dst *PluginInstallStatus) {
|
||||
resource.CopyObjectInto(dst, s)
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
//
|
||||
// Code generated by grafana-app-sdk. DO NOT EDIT.
|
||||
//
|
||||
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
)
|
||||
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaPluginInstall = resource.NewSimpleSchema("plugins.grafana.app", "v0alpha1", &PluginInstall{}, &PluginInstallList{}, resource.WithKind("PluginInstall"),
|
||||
resource.WithPlural("plugininstalls"), resource.WithScope(resource.NamespacedScope))
|
||||
kindPluginInstall = resource.Kind{
|
||||
Schema: schemaPluginInstall,
|
||||
Codecs: map[resource.KindEncoding]resource.Codec{
|
||||
resource.KindEncodingJSON: &PluginInstallJSONCodec{},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// Kind returns a resource.Kind for this Schema with a JSON codec
|
||||
func PluginInstallKind() resource.Kind {
|
||||
return kindPluginInstall
|
||||
}
|
||||
|
||||
// Schema returns a resource.SimpleSchema representation of PluginInstall
|
||||
func PluginInstallSchema() *resource.SimpleSchema {
|
||||
return schemaPluginInstall
|
||||
}
|
||||
|
||||
// Interface compliance checks
|
||||
var _ resource.Schema = kindPluginInstall
|
||||
@@ -1,25 +0,0 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
|
||||
package v0alpha1
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginInstallSpec struct {
|
||||
Id string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Url *string `json:"url,omitempty"`
|
||||
Class PluginInstallSpecClass `json:"class"`
|
||||
}
|
||||
|
||||
// NewPluginInstallSpec creates a new PluginInstallSpec object.
|
||||
func NewPluginInstallSpec() *PluginInstallSpec {
|
||||
return &PluginInstallSpec{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginInstallSpecClass string
|
||||
|
||||
const (
|
||||
PluginInstallSpecClassCore PluginInstallSpecClass = "core"
|
||||
PluginInstallSpecClassExternal PluginInstallSpecClass = "external"
|
||||
PluginInstallSpecClassCdn PluginInstallSpecClass = "cdn"
|
||||
)
|
||||
@@ -1,44 +0,0 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
|
||||
package v0alpha1
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginInstallstatusOperatorState struct {
|
||||
// lastEvaluation is the ResourceVersion last evaluated
|
||||
LastEvaluation string `json:"lastEvaluation"`
|
||||
// state describes the state of the lastEvaluation.
|
||||
// It is limited to three possible states for machine evaluation.
|
||||
State PluginInstallStatusOperatorStateState `json:"state"`
|
||||
// descriptiveState is an optional more descriptive state field which has no requirements on format
|
||||
DescriptiveState *string `json:"descriptiveState,omitempty"`
|
||||
// details contains any extra information that is operator-specific
|
||||
Details map[string]interface{} `json:"details,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginInstallstatusOperatorState creates a new PluginInstallstatusOperatorState object.
|
||||
func NewPluginInstallstatusOperatorState() *PluginInstallstatusOperatorState {
|
||||
return &PluginInstallstatusOperatorState{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginInstallStatus struct {
|
||||
// operatorStates is a map of operator ID to operator state evaluations.
|
||||
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
|
||||
OperatorStates map[string]PluginInstallstatusOperatorState `json:"operatorStates,omitempty"`
|
||||
// additionalFields is reserved for future use
|
||||
AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginInstallStatus creates a new PluginInstallStatus object.
|
||||
func NewPluginInstallStatus() *PluginInstallStatus {
|
||||
return &PluginInstallStatus{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginInstallStatusOperatorStateState string
|
||||
|
||||
const (
|
||||
PluginInstallStatusOperatorStateStateSuccess PluginInstallStatusOperatorStateState = "success"
|
||||
PluginInstallStatusOperatorStateStateInProgress PluginInstallStatusOperatorStateState = "in_progress"
|
||||
PluginInstallStatusOperatorStateStateFailed PluginInstallStatusOperatorStateState = "failed"
|
||||
)
|
||||
@@ -1,99 +0,0 @@
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type PluginMetaClient struct {
|
||||
client *resource.TypedClient[*PluginMeta, *PluginMetaList]
|
||||
}
|
||||
|
||||
func NewPluginMetaClient(client resource.Client) *PluginMetaClient {
|
||||
return &PluginMetaClient{
|
||||
client: resource.NewTypedClient[*PluginMeta, *PluginMetaList](client, PluginMetaKind()),
|
||||
}
|
||||
}
|
||||
|
||||
func NewPluginMetaClientFromGenerator(generator resource.ClientGenerator) (*PluginMetaClient, error) {
|
||||
c, err := generator.ClientFor(PluginMetaKind())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewPluginMetaClient(c), nil
|
||||
}
|
||||
|
||||
func (c *PluginMetaClient) Get(ctx context.Context, identifier resource.Identifier) (*PluginMeta, error) {
|
||||
return c.client.Get(ctx, identifier)
|
||||
}
|
||||
|
||||
func (c *PluginMetaClient) List(ctx context.Context, namespace string, opts resource.ListOptions) (*PluginMetaList, error) {
|
||||
return c.client.List(ctx, namespace, opts)
|
||||
}
|
||||
|
||||
func (c *PluginMetaClient) ListAll(ctx context.Context, namespace string, opts resource.ListOptions) (*PluginMetaList, error) {
|
||||
resp, err := c.client.List(ctx, namespace, resource.ListOptions{
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Limit: opts.Limit,
|
||||
LabelFilters: opts.LabelFilters,
|
||||
FieldSelectors: opts.FieldSelectors,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for resp.GetContinue() != "" {
|
||||
page, err := c.client.List(ctx, namespace, resource.ListOptions{
|
||||
Continue: resp.GetContinue(),
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Limit: opts.Limit,
|
||||
LabelFilters: opts.LabelFilters,
|
||||
FieldSelectors: opts.FieldSelectors,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.SetContinue(page.GetContinue())
|
||||
resp.SetResourceVersion(page.GetResourceVersion())
|
||||
resp.SetItems(append(resp.GetItems(), page.GetItems()...))
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *PluginMetaClient) Create(ctx context.Context, obj *PluginMeta, opts resource.CreateOptions) (*PluginMeta, error) {
|
||||
// Make sure apiVersion and kind are set
|
||||
obj.APIVersion = GroupVersion.Identifier()
|
||||
obj.Kind = PluginMetaKind().Kind()
|
||||
return c.client.Create(ctx, obj, opts)
|
||||
}
|
||||
|
||||
func (c *PluginMetaClient) Update(ctx context.Context, obj *PluginMeta, opts resource.UpdateOptions) (*PluginMeta, error) {
|
||||
return c.client.Update(ctx, obj, opts)
|
||||
}
|
||||
|
||||
func (c *PluginMetaClient) Patch(ctx context.Context, identifier resource.Identifier, req resource.PatchRequest, opts resource.PatchOptions) (*PluginMeta, error) {
|
||||
return c.client.Patch(ctx, identifier, req, opts)
|
||||
}
|
||||
|
||||
func (c *PluginMetaClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus PluginMetaStatus, opts resource.UpdateOptions) (*PluginMeta, error) {
|
||||
return c.client.Update(ctx, &PluginMeta{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: PluginMetaKind().Kind(),
|
||||
APIVersion: GroupVersion.Identifier(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
Namespace: identifier.Namespace,
|
||||
Name: identifier.Name,
|
||||
},
|
||||
Status: newStatus,
|
||||
}, resource.UpdateOptions{
|
||||
Subresource: "status",
|
||||
ResourceVersion: opts.ResourceVersion,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *PluginMetaClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error {
|
||||
return c.client.Delete(ctx, identifier, opts)
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
//
|
||||
// Code generated by grafana-app-sdk. DO NOT EDIT.
|
||||
//
|
||||
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
)
|
||||
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaPluginMeta = resource.NewSimpleSchema("plugins.grafana.app", "v0alpha1", &PluginMeta{}, &PluginMetaList{}, resource.WithKind("PluginMeta"),
|
||||
resource.WithPlural("pluginmetas"), resource.WithScope(resource.NamespacedScope))
|
||||
kindPluginMeta = resource.Kind{
|
||||
Schema: schemaPluginMeta,
|
||||
Codecs: map[resource.KindEncoding]resource.Codec{
|
||||
resource.KindEncodingJSON: &PluginMetaJSONCodec{},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// Kind returns a resource.Kind for this Schema with a JSON codec
|
||||
func PluginMetaKind() resource.Kind {
|
||||
return kindPluginMeta
|
||||
}
|
||||
|
||||
// Schema returns a resource.SimpleSchema representation of PluginMeta
|
||||
func PluginMetaSchema() *resource.SimpleSchema {
|
||||
return schemaPluginMeta
|
||||
}
|
||||
|
||||
// Interface compliance checks
|
||||
var _ resource.Schema = kindPluginMeta
|
||||
@@ -1,477 +0,0 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
|
||||
package v0alpha1
|
||||
|
||||
import (
|
||||
time "time"
|
||||
)
|
||||
|
||||
// JSON configuration schema for Grafana plugins
|
||||
// Converted from: https://github.com/grafana/grafana/blob/main/docs/sources/developers/plugins/plugin.schema.json
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaJSONData struct {
|
||||
// Unique name of the plugin
|
||||
Id string `json:"id"`
|
||||
// Plugin type
|
||||
Type PluginMetaJSONDataType `json:"type"`
|
||||
// Human-readable name of the plugin
|
||||
Name string `json:"name"`
|
||||
// Metadata for the plugin
|
||||
Info PluginMetaInfo `json:"info"`
|
||||
// Dependency information
|
||||
Dependencies PluginMetaDependencies `json:"dependencies"`
|
||||
// Optional fields
|
||||
Alerting *bool `json:"alerting,omitempty"`
|
||||
Annotations *bool `json:"annotations,omitempty"`
|
||||
AutoEnabled *bool `json:"autoEnabled,omitempty"`
|
||||
Backend *bool `json:"backend,omitempty"`
|
||||
BuildMode *string `json:"buildMode,omitempty"`
|
||||
BuiltIn *bool `json:"builtIn,omitempty"`
|
||||
Category *PluginMetaJSONDataCategory `json:"category,omitempty"`
|
||||
EnterpriseFeatures *PluginMetaEnterpriseFeatures `json:"enterpriseFeatures,omitempty"`
|
||||
Executable *string `json:"executable,omitempty"`
|
||||
HideFromList *bool `json:"hideFromList,omitempty"`
|
||||
// +listType=atomic
|
||||
Includes []PluginMetaInclude `json:"includes,omitempty"`
|
||||
Logs *bool `json:"logs,omitempty"`
|
||||
Metrics *bool `json:"metrics,omitempty"`
|
||||
MultiValueFilterOperators *bool `json:"multiValueFilterOperators,omitempty"`
|
||||
PascalName *string `json:"pascalName,omitempty"`
|
||||
Preload *bool `json:"preload,omitempty"`
|
||||
QueryOptions *PluginMetaQueryOptions `json:"queryOptions,omitempty"`
|
||||
// +listType=atomic
|
||||
Routes []PluginMetaRoute `json:"routes,omitempty"`
|
||||
SkipDataQuery *bool `json:"skipDataQuery,omitempty"`
|
||||
State *PluginMetaJSONDataState `json:"state,omitempty"`
|
||||
Streaming *bool `json:"streaming,omitempty"`
|
||||
Tracing *bool `json:"tracing,omitempty"`
|
||||
Iam *PluginMetaIAM `json:"iam,omitempty"`
|
||||
// +listType=atomic
|
||||
Roles []PluginMetaRole `json:"roles,omitempty"`
|
||||
Extensions *PluginMetaExtensions `json:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaJSONData creates a new PluginMetaJSONData object.
|
||||
func NewPluginMetaJSONData() *PluginMetaJSONData {
|
||||
return &PluginMetaJSONData{
|
||||
Info: *NewPluginMetaInfo(),
|
||||
Dependencies: *NewPluginMetaDependencies(),
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaInfo struct {
|
||||
// Required fields
|
||||
// +listType=set
|
||||
Keywords []string `json:"keywords"`
|
||||
Logos PluginMetaV0alpha1InfoLogos `json:"logos"`
|
||||
Updated time.Time `json:"updated"`
|
||||
Version string `json:"version"`
|
||||
// Optional fields
|
||||
Author *PluginMetaV0alpha1InfoAuthor `json:"author,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
// +listType=atomic
|
||||
Links []PluginMetaV0alpha1InfoLinks `json:"links,omitempty"`
|
||||
// +listType=atomic
|
||||
Screenshots []PluginMetaV0alpha1InfoScreenshots `json:"screenshots,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaInfo creates a new PluginMetaInfo object.
|
||||
func NewPluginMetaInfo() *PluginMetaInfo {
|
||||
return &PluginMetaInfo{
|
||||
Keywords: []string{},
|
||||
Logos: *NewPluginMetaV0alpha1InfoLogos(),
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaDependencies struct {
|
||||
// Required field
|
||||
GrafanaDependency string `json:"grafanaDependency"`
|
||||
// Optional fields
|
||||
GrafanaVersion *string `json:"grafanaVersion,omitempty"`
|
||||
// +listType=set
|
||||
// +listMapKey=id
|
||||
Plugins []PluginMetaV0alpha1DependenciesPlugins `json:"plugins,omitempty"`
|
||||
Extensions *PluginMetaV0alpha1DependenciesExtensions `json:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaDependencies creates a new PluginMetaDependencies object.
|
||||
func NewPluginMetaDependencies() *PluginMetaDependencies {
|
||||
return &PluginMetaDependencies{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaEnterpriseFeatures struct {
|
||||
// Allow additional properties
|
||||
HealthDiagnosticsErrors *bool `json:"healthDiagnosticsErrors,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaEnterpriseFeatures creates a new PluginMetaEnterpriseFeatures object.
|
||||
func NewPluginMetaEnterpriseFeatures() *PluginMetaEnterpriseFeatures {
|
||||
return &PluginMetaEnterpriseFeatures{
|
||||
HealthDiagnosticsErrors: (func(input bool) *bool { return &input })(false),
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaInclude struct {
|
||||
Uid *string `json:"uid,omitempty"`
|
||||
Type *PluginMetaIncludeType `json:"type,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Component *string `json:"component,omitempty"`
|
||||
Role *PluginMetaIncludeRole `json:"role,omitempty"`
|
||||
Action *string `json:"action,omitempty"`
|
||||
Path *string `json:"path,omitempty"`
|
||||
AddToNav *bool `json:"addToNav,omitempty"`
|
||||
DefaultNav *bool `json:"defaultNav,omitempty"`
|
||||
Icon *string `json:"icon,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaInclude creates a new PluginMetaInclude object.
|
||||
func NewPluginMetaInclude() *PluginMetaInclude {
|
||||
return &PluginMetaInclude{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaQueryOptions struct {
|
||||
MaxDataPoints *bool `json:"maxDataPoints,omitempty"`
|
||||
MinInterval *bool `json:"minInterval,omitempty"`
|
||||
CacheTimeout *bool `json:"cacheTimeout,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaQueryOptions creates a new PluginMetaQueryOptions object.
|
||||
func NewPluginMetaQueryOptions() *PluginMetaQueryOptions {
|
||||
return &PluginMetaQueryOptions{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaRoute struct {
|
||||
Path *string `json:"path,omitempty"`
|
||||
Method *string `json:"method,omitempty"`
|
||||
Url *string `json:"url,omitempty"`
|
||||
ReqSignedIn *bool `json:"reqSignedIn,omitempty"`
|
||||
ReqRole *string `json:"reqRole,omitempty"`
|
||||
ReqAction *string `json:"reqAction,omitempty"`
|
||||
// +listType=atomic
|
||||
Headers []string `json:"headers,omitempty"`
|
||||
Body map[string]interface{} `json:"body,omitempty"`
|
||||
TokenAuth *PluginMetaV0alpha1RouteTokenAuth `json:"tokenAuth,omitempty"`
|
||||
JwtTokenAuth *PluginMetaV0alpha1RouteJwtTokenAuth `json:"jwtTokenAuth,omitempty"`
|
||||
// +listType=atomic
|
||||
UrlParams []PluginMetaV0alpha1RouteUrlParams `json:"urlParams,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaRoute creates a new PluginMetaRoute object.
|
||||
func NewPluginMetaRoute() *PluginMetaRoute {
|
||||
return &PluginMetaRoute{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaIAM struct {
|
||||
// +listType=atomic
|
||||
Permissions []PluginMetaV0alpha1IAMPermissions `json:"permissions,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaIAM creates a new PluginMetaIAM object.
|
||||
func NewPluginMetaIAM() *PluginMetaIAM {
|
||||
return &PluginMetaIAM{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaRole struct {
|
||||
Role *PluginMetaV0alpha1RoleRole `json:"role,omitempty"`
|
||||
// +listType=set
|
||||
Grants []string `json:"grants,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaRole creates a new PluginMetaRole object.
|
||||
func NewPluginMetaRole() *PluginMetaRole {
|
||||
return &PluginMetaRole{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaExtensions struct {
|
||||
// +listType=atomic
|
||||
AddedComponents []PluginMetaV0alpha1ExtensionsAddedComponents `json:"addedComponents,omitempty"`
|
||||
// +listType=atomic
|
||||
AddedLinks []PluginMetaV0alpha1ExtensionsAddedLinks `json:"addedLinks,omitempty"`
|
||||
// +listType=set
|
||||
// +listMapKey=id
|
||||
ExposedComponents []PluginMetaV0alpha1ExtensionsExposedComponents `json:"exposedComponents,omitempty"`
|
||||
// +listType=set
|
||||
// +listMapKey=id
|
||||
ExtensionPoints []PluginMetaV0alpha1ExtensionsExtensionPoints `json:"extensionPoints,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaExtensions creates a new PluginMetaExtensions object.
|
||||
func NewPluginMetaExtensions() *PluginMetaExtensions {
|
||||
return &PluginMetaExtensions{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaSpec struct {
|
||||
PluginJSON PluginMetaJSONData `json:"pluginJSON"`
|
||||
}
|
||||
|
||||
// NewPluginMetaSpec creates a new PluginMetaSpec object.
|
||||
func NewPluginMetaSpec() *PluginMetaSpec {
|
||||
return &PluginMetaSpec{
|
||||
PluginJSON: *NewPluginMetaJSONData(),
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1InfoLogos struct {
|
||||
Small string `json:"small"`
|
||||
Large string `json:"large"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1InfoLogos creates a new PluginMetaV0alpha1InfoLogos object.
|
||||
func NewPluginMetaV0alpha1InfoLogos() *PluginMetaV0alpha1InfoLogos {
|
||||
return &PluginMetaV0alpha1InfoLogos{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1InfoAuthor struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Email *string `json:"email,omitempty"`
|
||||
Url *string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1InfoAuthor creates a new PluginMetaV0alpha1InfoAuthor object.
|
||||
func NewPluginMetaV0alpha1InfoAuthor() *PluginMetaV0alpha1InfoAuthor {
|
||||
return &PluginMetaV0alpha1InfoAuthor{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1InfoLinks struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Url *string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1InfoLinks creates a new PluginMetaV0alpha1InfoLinks object.
|
||||
func NewPluginMetaV0alpha1InfoLinks() *PluginMetaV0alpha1InfoLinks {
|
||||
return &PluginMetaV0alpha1InfoLinks{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1InfoScreenshots struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Path *string `json:"path,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1InfoScreenshots creates a new PluginMetaV0alpha1InfoScreenshots object.
|
||||
func NewPluginMetaV0alpha1InfoScreenshots() *PluginMetaV0alpha1InfoScreenshots {
|
||||
return &PluginMetaV0alpha1InfoScreenshots{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1DependenciesPlugins struct {
|
||||
Id string `json:"id"`
|
||||
Type PluginMetaV0alpha1DependenciesPluginsType `json:"type"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1DependenciesPlugins creates a new PluginMetaV0alpha1DependenciesPlugins object.
|
||||
func NewPluginMetaV0alpha1DependenciesPlugins() *PluginMetaV0alpha1DependenciesPlugins {
|
||||
return &PluginMetaV0alpha1DependenciesPlugins{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1DependenciesExtensions struct {
|
||||
// +listType=set
|
||||
ExposedComponents []string `json:"exposedComponents,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1DependenciesExtensions creates a new PluginMetaV0alpha1DependenciesExtensions object.
|
||||
func NewPluginMetaV0alpha1DependenciesExtensions() *PluginMetaV0alpha1DependenciesExtensions {
|
||||
return &PluginMetaV0alpha1DependenciesExtensions{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1RouteTokenAuth struct {
|
||||
Url *string `json:"url,omitempty"`
|
||||
// +listType=set
|
||||
Scopes []string `json:"scopes,omitempty"`
|
||||
Params map[string]interface{} `json:"params,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1RouteTokenAuth creates a new PluginMetaV0alpha1RouteTokenAuth object.
|
||||
func NewPluginMetaV0alpha1RouteTokenAuth() *PluginMetaV0alpha1RouteTokenAuth {
|
||||
return &PluginMetaV0alpha1RouteTokenAuth{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1RouteJwtTokenAuth struct {
|
||||
Url *string `json:"url,omitempty"`
|
||||
// +listType=set
|
||||
Scopes []string `json:"scopes,omitempty"`
|
||||
Params map[string]interface{} `json:"params,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1RouteJwtTokenAuth creates a new PluginMetaV0alpha1RouteJwtTokenAuth object.
|
||||
func NewPluginMetaV0alpha1RouteJwtTokenAuth() *PluginMetaV0alpha1RouteJwtTokenAuth {
|
||||
return &PluginMetaV0alpha1RouteJwtTokenAuth{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1RouteUrlParams struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Content *string `json:"content,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1RouteUrlParams creates a new PluginMetaV0alpha1RouteUrlParams object.
|
||||
func NewPluginMetaV0alpha1RouteUrlParams() *PluginMetaV0alpha1RouteUrlParams {
|
||||
return &PluginMetaV0alpha1RouteUrlParams{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1IAMPermissions struct {
|
||||
Action *string `json:"action,omitempty"`
|
||||
Scope *string `json:"scope,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1IAMPermissions creates a new PluginMetaV0alpha1IAMPermissions object.
|
||||
func NewPluginMetaV0alpha1IAMPermissions() *PluginMetaV0alpha1IAMPermissions {
|
||||
return &PluginMetaV0alpha1IAMPermissions{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1RoleRolePermissions struct {
|
||||
Action *string `json:"action,omitempty"`
|
||||
Scope *string `json:"scope,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1RoleRolePermissions creates a new PluginMetaV0alpha1RoleRolePermissions object.
|
||||
func NewPluginMetaV0alpha1RoleRolePermissions() *PluginMetaV0alpha1RoleRolePermissions {
|
||||
return &PluginMetaV0alpha1RoleRolePermissions{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1RoleRole struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
// +listType=atomic
|
||||
Permissions []PluginMetaV0alpha1RoleRolePermissions `json:"permissions,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1RoleRole creates a new PluginMetaV0alpha1RoleRole object.
|
||||
func NewPluginMetaV0alpha1RoleRole() *PluginMetaV0alpha1RoleRole {
|
||||
return &PluginMetaV0alpha1RoleRole{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1ExtensionsAddedComponents struct {
|
||||
// +listType=set
|
||||
Targets []string `json:"targets"`
|
||||
Title string `json:"title"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1ExtensionsAddedComponents creates a new PluginMetaV0alpha1ExtensionsAddedComponents object.
|
||||
func NewPluginMetaV0alpha1ExtensionsAddedComponents() *PluginMetaV0alpha1ExtensionsAddedComponents {
|
||||
return &PluginMetaV0alpha1ExtensionsAddedComponents{
|
||||
Targets: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1ExtensionsAddedLinks struct {
|
||||
// +listType=set
|
||||
Targets []string `json:"targets"`
|
||||
Title string `json:"title"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1ExtensionsAddedLinks creates a new PluginMetaV0alpha1ExtensionsAddedLinks object.
|
||||
func NewPluginMetaV0alpha1ExtensionsAddedLinks() *PluginMetaV0alpha1ExtensionsAddedLinks {
|
||||
return &PluginMetaV0alpha1ExtensionsAddedLinks{
|
||||
Targets: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1ExtensionsExposedComponents struct {
|
||||
Id string `json:"id"`
|
||||
Title *string `json:"title,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1ExtensionsExposedComponents creates a new PluginMetaV0alpha1ExtensionsExposedComponents object.
|
||||
func NewPluginMetaV0alpha1ExtensionsExposedComponents() *PluginMetaV0alpha1ExtensionsExposedComponents {
|
||||
return &PluginMetaV0alpha1ExtensionsExposedComponents{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1ExtensionsExtensionPoints struct {
|
||||
Id string `json:"id"`
|
||||
Title *string `json:"title,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaV0alpha1ExtensionsExtensionPoints creates a new PluginMetaV0alpha1ExtensionsExtensionPoints object.
|
||||
func NewPluginMetaV0alpha1ExtensionsExtensionPoints() *PluginMetaV0alpha1ExtensionsExtensionPoints {
|
||||
return &PluginMetaV0alpha1ExtensionsExtensionPoints{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaJSONDataType string
|
||||
|
||||
const (
|
||||
PluginMetaJSONDataTypeApp PluginMetaJSONDataType = "app"
|
||||
PluginMetaJSONDataTypeDatasource PluginMetaJSONDataType = "datasource"
|
||||
PluginMetaJSONDataTypePanel PluginMetaJSONDataType = "panel"
|
||||
PluginMetaJSONDataTypeRenderer PluginMetaJSONDataType = "renderer"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaJSONDataCategory string
|
||||
|
||||
const (
|
||||
PluginMetaJSONDataCategoryTsdb PluginMetaJSONDataCategory = "tsdb"
|
||||
PluginMetaJSONDataCategoryLogging PluginMetaJSONDataCategory = "logging"
|
||||
PluginMetaJSONDataCategoryCloud PluginMetaJSONDataCategory = "cloud"
|
||||
PluginMetaJSONDataCategoryTracing PluginMetaJSONDataCategory = "tracing"
|
||||
PluginMetaJSONDataCategoryProfiling PluginMetaJSONDataCategory = "profiling"
|
||||
PluginMetaJSONDataCategorySql PluginMetaJSONDataCategory = "sql"
|
||||
PluginMetaJSONDataCategoryEnterprise PluginMetaJSONDataCategory = "enterprise"
|
||||
PluginMetaJSONDataCategoryIot PluginMetaJSONDataCategory = "iot"
|
||||
PluginMetaJSONDataCategoryOther PluginMetaJSONDataCategory = "other"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaJSONDataState string
|
||||
|
||||
const (
|
||||
PluginMetaJSONDataStateAlpha PluginMetaJSONDataState = "alpha"
|
||||
PluginMetaJSONDataStateBeta PluginMetaJSONDataState = "beta"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaIncludeType string
|
||||
|
||||
const (
|
||||
PluginMetaIncludeTypeDashboard PluginMetaIncludeType = "dashboard"
|
||||
PluginMetaIncludeTypePage PluginMetaIncludeType = "page"
|
||||
PluginMetaIncludeTypePanel PluginMetaIncludeType = "panel"
|
||||
PluginMetaIncludeTypeDatasource PluginMetaIncludeType = "datasource"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaIncludeRole string
|
||||
|
||||
const (
|
||||
PluginMetaIncludeRoleAdmin PluginMetaIncludeRole = "Admin"
|
||||
PluginMetaIncludeRoleEditor PluginMetaIncludeRole = "Editor"
|
||||
PluginMetaIncludeRoleViewer PluginMetaIncludeRole = "Viewer"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaV0alpha1DependenciesPluginsType string
|
||||
|
||||
const (
|
||||
PluginMetaV0alpha1DependenciesPluginsTypeApp PluginMetaV0alpha1DependenciesPluginsType = "app"
|
||||
PluginMetaV0alpha1DependenciesPluginsTypeDatasource PluginMetaV0alpha1DependenciesPluginsType = "datasource"
|
||||
PluginMetaV0alpha1DependenciesPluginsTypePanel PluginMetaV0alpha1DependenciesPluginsType = "panel"
|
||||
)
|
||||
@@ -1,44 +0,0 @@
|
||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||
|
||||
package v0alpha1
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetastatusOperatorState struct {
|
||||
// lastEvaluation is the ResourceVersion last evaluated
|
||||
LastEvaluation string `json:"lastEvaluation"`
|
||||
// state describes the state of the lastEvaluation.
|
||||
// It is limited to three possible states for machine evaluation.
|
||||
State PluginMetaStatusOperatorStateState `json:"state"`
|
||||
// descriptiveState is an optional more descriptive state field which has no requirements on format
|
||||
DescriptiveState *string `json:"descriptiveState,omitempty"`
|
||||
// details contains any extra information that is operator-specific
|
||||
Details map[string]interface{} `json:"details,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetastatusOperatorState creates a new PluginMetastatusOperatorState object.
|
||||
func NewPluginMetastatusOperatorState() *PluginMetastatusOperatorState {
|
||||
return &PluginMetastatusOperatorState{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaStatus struct {
|
||||
// operatorStates is a map of operator ID to operator state evaluations.
|
||||
// Any operator which consumes this kind SHOULD add its state evaluation information to this field.
|
||||
OperatorStates map[string]PluginMetastatusOperatorState `json:"operatorStates,omitempty"`
|
||||
// additionalFields is reserved for future use
|
||||
AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
|
||||
}
|
||||
|
||||
// NewPluginMetaStatus creates a new PluginMetaStatus object.
|
||||
func NewPluginMetaStatus() *PluginMetaStatus {
|
||||
return &PluginMetaStatus{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginMetaStatusOperatorStateState string
|
||||
|
||||
const (
|
||||
PluginMetaStatusOperatorStateStateSuccess PluginMetaStatusOperatorStateState = "success"
|
||||
PluginMetaStatusOperatorStateStateInProgress PluginMetaStatusOperatorStateState = "in_progress"
|
||||
PluginMetaStatusOperatorStateStateFailed PluginMetaStatusOperatorStateState = "failed"
|
||||
)
|
||||
File diff suppressed because one or more lines are too long
@@ -2,8 +2,11 @@ package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/app"
|
||||
"github.com/grafana/grafana-app-sdk/k8s"
|
||||
"github.com/grafana/grafana-app-sdk/logging"
|
||||
"github.com/grafana/grafana-app-sdk/operator"
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
"github.com/grafana/grafana-app-sdk/simple"
|
||||
@@ -11,16 +14,15 @@ import (
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
pluginsapi "github.com/grafana/grafana/apps/plugins/pkg/apis"
|
||||
pluginsv0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1"
|
||||
)
|
||||
|
||||
func New(cfg app.Config) (app.App, error) {
|
||||
managedKinds := []simple.AppManagedKind{}
|
||||
for _, kinds := range GetKinds() {
|
||||
for _, k := range kinds {
|
||||
managedKinds = append(managedKinds, simple.AppManagedKind{
|
||||
Kind: k,
|
||||
})
|
||||
}
|
||||
cfg.KubeConfig.APIPath = "apis"
|
||||
clientGenerator := k8s.NewClientRegistry(cfg.KubeConfig, k8s.DefaultClientConfig())
|
||||
client, err := pluginsv0alpha1.NewPluginClientFromGenerator(clientGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
simpleConfig := simple.AppConfig{
|
||||
@@ -33,7 +35,32 @@ func New(cfg app.Config) (app.App, error) {
|
||||
},
|
||||
},
|
||||
},
|
||||
ManagedKinds: managedKinds,
|
||||
ManagedKinds: []simple.AppManagedKind{
|
||||
{
|
||||
Kind: pluginsv0alpha1.PluginKind(),
|
||||
CustomRoutes: simple.AppCustomRouteHandlers{
|
||||
simple.AppCustomRoute{
|
||||
Method: http.MethodGet,
|
||||
Path: "meta",
|
||||
}: func(ctx context.Context, w app.CustomRouteResponseWriter, req *app.CustomRouteRequest) error {
|
||||
plugin, err := client.Get(ctx, resource.Identifier{
|
||||
Namespace: req.ResourceIdentifier.Namespace,
|
||||
Name: req.ResourceIdentifier.Name,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logging.DefaultLogger.Debug("fetched plugin", "plugin", plugin)
|
||||
// TODO: Implement this in future PR
|
||||
w.WriteHeader(http.StatusNotImplemented)
|
||||
if _, err := w.Write([]byte("Not implemented")); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
a, err := simple.NewApp(simpleConfig)
|
||||
|
||||
@@ -41,12 +41,12 @@ type PluginInstall struct {
|
||||
Source Source
|
||||
}
|
||||
|
||||
func (p *PluginInstall) ToPluginInstallV0Alpha1(namespace string) *pluginsv0alpha1.PluginInstall {
|
||||
func (p *PluginInstall) ToPluginInstallV0Alpha1(namespace string) *pluginsv0alpha1.Plugin {
|
||||
var url *string = nil
|
||||
if p.URL != "" {
|
||||
url = &p.URL
|
||||
}
|
||||
return &pluginsv0alpha1.PluginInstall{
|
||||
return &pluginsv0alpha1.Plugin{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: namespace,
|
||||
Name: p.ID,
|
||||
@@ -54,16 +54,16 @@ func (p *PluginInstall) ToPluginInstallV0Alpha1(namespace string) *pluginsv0alph
|
||||
PluginInstallSourceAnnotation: p.Source,
|
||||
},
|
||||
},
|
||||
Spec: pluginsv0alpha1.PluginInstallSpec{
|
||||
Spec: pluginsv0alpha1.PluginSpec{
|
||||
Id: p.ID,
|
||||
Version: p.Version,
|
||||
Url: url,
|
||||
Class: pluginsv0alpha1.PluginInstallSpecClass(p.Class),
|
||||
Class: pluginsv0alpha1.PluginSpecClass(p.Class),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PluginInstall) ShouldUpdate(existing *pluginsv0alpha1.PluginInstall) bool {
|
||||
func (p *PluginInstall) ShouldUpdate(existing *pluginsv0alpha1.Plugin) bool {
|
||||
update := p.ToPluginInstallV0Alpha1(existing.Namespace)
|
||||
if source, ok := existing.Annotations[PluginInstallSourceAnnotation]; ok && source != p.Source {
|
||||
return true
|
||||
@@ -92,7 +92,7 @@ func equalStringPointers(a, b *string) bool {
|
||||
|
||||
type InstallRegistrar struct {
|
||||
clientGenerator resource.ClientGenerator
|
||||
client *pluginsv0alpha1.PluginInstallClient
|
||||
client *pluginsv0alpha1.PluginClient
|
||||
clientOnce sync.Once
|
||||
}
|
||||
|
||||
@@ -103,9 +103,9 @@ func NewInstallRegistrar(clientGenerator resource.ClientGenerator) *InstallRegis
|
||||
}
|
||||
}
|
||||
|
||||
func (r *InstallRegistrar) GetClient() (*pluginsv0alpha1.PluginInstallClient, error) {
|
||||
func (r *InstallRegistrar) GetClient() (*pluginsv0alpha1.PluginClient, error) {
|
||||
r.clientOnce.Do(func() {
|
||||
client, err := pluginsv0alpha1.NewPluginInstallClientFromGenerator(r.clientGenerator)
|
||||
client, err := pluginsv0alpha1.NewPluginClientFromGenerator(r.clientGenerator)
|
||||
if err != nil {
|
||||
r.client = nil
|
||||
return
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
|
||||
claims "github.com/grafana/authlib/types"
|
||||
pluginsv0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1"
|
||||
)
|
||||
|
||||
var (
|
||||
_ rest.Scoper = (*PluginMetaStorage)(nil)
|
||||
_ rest.SingularNameProvider = (*PluginMetaStorage)(nil)
|
||||
_ rest.Getter = (*PluginMetaStorage)(nil)
|
||||
_ rest.Lister = (*PluginMetaStorage)(nil)
|
||||
_ rest.Storage = (*PluginMetaStorage)(nil)
|
||||
_ rest.TableConvertor = (*PluginMetaStorage)(nil)
|
||||
)
|
||||
|
||||
type PluginMetaStorage struct {
|
||||
gr schema.GroupResource
|
||||
namespacer claims.NamespaceFormatter
|
||||
tableConverter rest.TableConvertor
|
||||
}
|
||||
|
||||
func NewPluginMetaStorage(
|
||||
namespacer claims.NamespaceFormatter,
|
||||
) *PluginMetaStorage {
|
||||
gr := schema.GroupResource{
|
||||
Group: pluginsv0alpha1.PluginMetaKind().Group(),
|
||||
Resource: strings.ToLower(pluginsv0alpha1.PluginMetaKind().Plural()),
|
||||
}
|
||||
return &PluginMetaStorage{
|
||||
gr: gr,
|
||||
namespacer: namespacer,
|
||||
tableConverter: rest.NewDefaultTableConvertor(gr),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PluginMetaStorage) New() runtime.Object {
|
||||
return pluginsv0alpha1.PluginMetaKind().ZeroValue()
|
||||
}
|
||||
|
||||
func (s *PluginMetaStorage) Destroy() {}
|
||||
|
||||
func (s *PluginMetaStorage) NamespaceScoped() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *PluginMetaStorage) GetSingularName() string {
|
||||
return strings.ToLower(pluginsv0alpha1.PluginMetaKind().Kind())
|
||||
}
|
||||
|
||||
func (s *PluginMetaStorage) NewList() runtime.Object {
|
||||
return pluginsv0alpha1.PluginMetaKind().ZeroListValue()
|
||||
}
|
||||
|
||||
func (s *PluginMetaStorage) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
|
||||
return s.tableConverter.ConvertToTable(ctx, object, tableOptions)
|
||||
}
|
||||
|
||||
func (s *PluginMetaStorage) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) {
|
||||
return s.NewList(), nil
|
||||
}
|
||||
|
||||
func (s *PluginMetaStorage) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
|
||||
return nil, apierrors.NewNotFound(s.gr, name)
|
||||
}
|
||||
@@ -30,11 +30,12 @@ var (
|
||||
|
||||
func New(cfg app.Config) (app.App, error) {
|
||||
cfg.KubeConfig.APIPath = "apis"
|
||||
client, err := k8s.NewClientRegistry(cfg.KubeConfig, k8s.DefaultClientConfig()).
|
||||
tmp, err := k8s.NewClientRegistry(cfg.KubeConfig, k8s.DefaultClientConfig()).
|
||||
ClientFor(shorturlv1alpha1.ShortURLKind())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create client")
|
||||
}
|
||||
client := shorturlv1alpha1.NewShortURLClient(tmp)
|
||||
|
||||
simpleConfig := simple.AppConfig{
|
||||
Name: "shorturl",
|
||||
@@ -81,8 +82,8 @@ func New(cfg app.Config) (app.App, error) {
|
||||
Name: req.ResourceIdentifier.Name,
|
||||
}
|
||||
|
||||
info := &shorturlv1alpha1.ShortURL{}
|
||||
if err := client.GetInto(ctx, id, info); err != nil {
|
||||
info, err := client.Get(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -93,7 +94,12 @@ func New(cfg app.Config) (app.App, error) {
|
||||
if err != nil {
|
||||
logging.FromContext(ctx).Warn("unable to create background identity", "err", err)
|
||||
} else {
|
||||
_, _ = client.Update(ctx, id, info, resource.UpdateOptions{})
|
||||
_, err = client.UpdateStatus(ctx, id, info.Status, resource.UpdateOptions{
|
||||
ResourceVersion: info.ResourceVersion,
|
||||
})
|
||||
if err != nil {
|
||||
logging.FromContext(ctx).Warn("unable to update status", "err", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -2203,6 +2203,16 @@ resource_storage_type = "db"
|
||||
# Current key provider used for envelope encryption
|
||||
encryption_provider = secret_key.v1
|
||||
|
||||
# These flags are required in on-prem installations for GitSync to work
|
||||
#
|
||||
# Whether to register the MT CRUD API
|
||||
register_api_server = true
|
||||
# Whether to create the MT secrets management database
|
||||
run_secrets_db_migrations = true
|
||||
# Whether to run the data key id migration. Requires that RunSecretsDBMigrations is also true.
|
||||
run_data_key_migration = true
|
||||
|
||||
|
||||
[secrets_manager.encryption.secret_key.v1]
|
||||
# Used to encrypt data keys
|
||||
secret_key = SW2YcwTIb9zpOOhoPsMm
|
||||
|
||||
+15
-5
@@ -2101,12 +2101,22 @@ default_datasource_uid =
|
||||
|
||||
###################################### Secrets Manager ######################################
|
||||
[secrets_manager]
|
||||
# Used for signing
|
||||
# Current key provider used for envelope encryption
|
||||
;encryption_provider = secret_key.v1
|
||||
|
||||
# These flags are required in on-prem installations for GitSync to work
|
||||
#
|
||||
# Whether to register the MT CRUD API
|
||||
;register_api_server = true
|
||||
# Whether to create the MT secrets management database
|
||||
;run_secrets_db_migrations = true
|
||||
# Whether to run the data key id migration. Requires that RunSecretsDBMigrations is also true.
|
||||
;run_data_key_migration = true
|
||||
|
||||
[secrets_manager.encryption.secret_key.v1]
|
||||
# Used to encrypt data keys
|
||||
;secret_key = SW2YcwTIb9zpOOhoPsMm
|
||||
# Current key provider used for envelope encryption, default to static value specified by secret_key
|
||||
;encryption_provider = secretKey.v1
|
||||
# List of configured key providers, space separated (Enterprise only): e.g., awskms.v1 azurekv.v1
|
||||
;available_encryption_providers =
|
||||
|
||||
|
||||
################################## Frontend development configuration ###################################
|
||||
# Warning! Any settings placed in this section will be available on `process.env.frontend_dev_{foo}` within frontend code
|
||||
|
||||
@@ -18,7 +18,7 @@ We recommend using [Homebrew](https://brew.sh/) for installing any missing depen
|
||||
```
|
||||
brew install git
|
||||
brew install go
|
||||
brew install node@22
|
||||
brew install node@24
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
@@ -204,7 +204,27 @@
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"actions": [
|
||||
{
|
||||
"fetch": {
|
||||
"body": "{}",
|
||||
"headers": [["Content-Type", "application/json"]],
|
||||
"method": "GET",
|
||||
"queryParams": [],
|
||||
"url": "/api/health"
|
||||
},
|
||||
"title": "Get instance health",
|
||||
"type": "fetch"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"targetBlank": true,
|
||||
"title": "Google Grafana",
|
||||
"url": "https://google.com/search?q=grafana"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
|
||||
@@ -20,7 +20,7 @@ Plugins enhance your Grafana experience with new ways to connect to and visualiz
|
||||
|
||||
Read on for an overview on how to get started with plugins:
|
||||
|
||||
- Plugins are available in the [plugin catalog](#plugin-catalog). They can be built by Grafana Labs, commercial partners, our community, or you can [build a plugin yourself](/developers/plugin-tools).
|
||||
- Plugins are available in the [plugin catalog](#access-the-plugin-catalog). They can be built by Grafana Labs, commercial partners, our community, or you can [build a plugin yourself](/developers/plugin-tools).
|
||||
- There are three [types of plugins](#types-of-plugins): panel, data source, and app plugins.
|
||||
- Learn [how to install](#install-a-plugin), [update](#update-a-plugin) and [verify](#verify-your-plugins) your plugins.
|
||||
|
||||
@@ -40,11 +40,11 @@ Grafana supports three types of plugins:
|
||||
|
||||
Read more in [Types of plugins](plugin-types).
|
||||
|
||||
## Plugin catalog
|
||||
## Access the Plugin catalog
|
||||
|
||||
The Grafana plugin catalog allows you to browse and manage plugins from within Grafana. Only Grafana server administrators and Organization administrators can access and use the plugin catalog. For more information about Grafana roles and permissions, refer to [Roles and permissions](../roles-and-permissions/).
|
||||
You can install and manage plugins from within Grafana. You need to have a Grafana Server administrator or Organization administrator role to access and use the plugin catalog. For more information about Grafana roles and permissions, refer to [Roles and permissions](../roles-and-permissions/).
|
||||
|
||||
The following access rules apply depending on the user role:
|
||||
For app plugins, the following access rules apply:
|
||||
|
||||
- If you are an **Org Admin**, you can configure app plugins, but you can't install, uninstall, or update them.
|
||||
- If you are a **Server Admin**, you can't configure app plugins, but you can install, uninstall, or update them.
|
||||
@@ -58,6 +58,8 @@ To browse for available plugins:
|
||||
1. Use the search box to filter based on name, keywords, organization and other metadata.
|
||||
1. Click the **Data sources**, **Panels**, or **Applications** buttons to filter by plugin type.
|
||||
|
||||
If you're not logged in, you can also access the list of available plugins in the [Plugin catalog](https://grafana.com/grafana/plugins/).
|
||||
|
||||
## Manage your plugins
|
||||
|
||||
We strongly recommend running the latest plugin version. Use [Grafana Advisor](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/administration/grafana-advisor) to check the status of your data sources and plugins.
|
||||
|
||||
@@ -65,6 +65,10 @@ The copied rules are converted to Grafana-managed rules, preserving their behavi
|
||||
|
||||
The rule query offset is taken from the `query_offset` value in the rule group configuration. If empty, it defaults to the [`rule_query_offset` configuration setting](ref:configure-grafana-rule_query_offset), which is `1m` by default.
|
||||
|
||||
- **Rule query conversion**
|
||||
|
||||
For alert rules, adds `prometheus_math` and `threshold` expressions to preserve Prometheus no data behavior, ensuring the alert stays in **Normal** state when `query` returns no data.
|
||||
|
||||
- **Missing series evaluations to resolve**
|
||||
|
||||
The [Missing series evaluations to resolve](ref:missing_series_evaluations_to_resolve) setting is set to `1` to replicate Prometheus’s alert eviction behavior.
|
||||
|
||||
@@ -159,7 +159,9 @@ Once the first notification has been sent for a new group of alerts, the group i
|
||||
|
||||
When the group interval timer elapses, the system resets the group interval timer and sends a notification only if there were group changes. This process repeats until there are no more alerts.
|
||||
|
||||
It's important to note that an alert instance exits the group after being resolved and notified of its state change. When no alerts remain, the group is deleted, and then the group wait timer handles the first notification for the next incoming alert once again.
|
||||
It's important to note that an alert instance exits the group after being resolved and notified of its state change.
|
||||
|
||||
When the group interval timer elapses and no alerts remain, the group is deleted. The [group wait timer](#group-wait) will then start again the next time a new alert arrives.
|
||||
|
||||
### Repeat interval
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ In Grafana v11, support for the deprecated AngularJS framework is turned off by
|
||||
|
||||
#### Migration/mitigation
|
||||
|
||||
To avoid disruption, ensure all plugins are up to date and migrate from any remaining AngularJS plugins to a React-based alternative. If a plugin relies on AngularJS, a warning icon and message will be displayed in the [plugins catalog](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/administration/plugin-management/#plugin-catalog) in Grafana and any dashboard panel where it's used. Additionally, a warning banner will appear in any impacted dashboards. A list of all impacted dashboards can also be generated using the [`detect-angular-dashboards`](https://github.com/grafana/detect-angular-dashboards) tool.
|
||||
To avoid disruption, ensure all plugins are up to date and migrate from any remaining AngularJS plugins to a React-based alternative. If a plugin relies on AngularJS, a warning icon and message will be displayed in the [plugins catalog](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/administration/plugin-management/#access-the-plugin-catalog) in Grafana and any dashboard panel where it's used. Additionally, a warning banner will appear in any impacted dashboards. A list of all impacted dashboards can also be generated using the [`detect-angular-dashboards`](https://github.com/grafana/detect-angular-dashboards) tool.
|
||||
|
||||
Our [documentation](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/developers/angular_deprecation/angular-plugins/) lists all known public plugins and provides migration advice when possible.
|
||||
|
||||
|
||||
@@ -71,9 +71,8 @@ After you add and configure a data source, you can use it as an input for many o
|
||||
|
||||
This documentation describes how to manage data sources in general,
|
||||
and how to configure or query the built-in data sources.
|
||||
For other data sources, refer to the list of [datasource plugins](/grafana/plugins/).
|
||||
|
||||
To develop a custom plugin, refer to [Create a data source plugin](#create-a-data-source-plugin).
|
||||
For other available plugins, refer to the list of [documented plugins](https://grafana.com/docs/plugins/) or browse the [Plugin catalog](/grafana/plugins/). To develop a custom plugin, refer to [Create a data source plugin](#create-a-data-source-plugin).
|
||||
|
||||
## Manage data sources
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ labels:
|
||||
products:
|
||||
- enterprise
|
||||
- oss
|
||||
- cloud
|
||||
title: Observability as Code
|
||||
weight: 100
|
||||
cards:
|
||||
@@ -32,11 +33,11 @@ cards:
|
||||
height: 24
|
||||
href: ./foundation-sdk/
|
||||
description: The Grafana Foundation SDK is a set of tools, types, and libraries that let you define Grafana dashboards and resources using strongly typed code.
|
||||
- title: Git Sync (experimental)
|
||||
- title: Git Sync (private preview)
|
||||
height: 24
|
||||
href: ./provision-resources/intro-git-sync/
|
||||
description: Git Sync is an experimental feature that lets you store your dashboard files in a GitHub repository and synchronize those changes with your Grafana instance.
|
||||
- title: File provisioning (experimental)
|
||||
- title: File provisioning (private preview)
|
||||
height: 24
|
||||
href: ./provision-resources/
|
||||
description: File provisioning in Grafana lets you include resources, including folders and dashboard JSON files, that are stored in a local file system.
|
||||
|
||||
@@ -2559,7 +2559,7 @@ Available to Grafana administrators only, enables installing, uninstalling, and
|
||||
Set to `true` by default.
|
||||
Setting it to `false` hides the controls.
|
||||
|
||||
For more information, refer to [Plugin catalog](../../administration/plugin-management/#plugin-catalog).
|
||||
For more information, refer to [Plugin catalog](../../administration/plugin-management/#access-the-plugin-catalog).
|
||||
|
||||
#### `plugin_admin_external_manage_enabled`
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general-
|
||||
| `alertingImportYAMLUI` | Enables a UI feature for importing rules from a Prometheus file to Grafana-managed rules | Yes |
|
||||
| `unifiedNavbars` | Enables unified navbars | |
|
||||
| `grafanaAssistantInProfilesDrilldown` | Enables integration with Grafana Assistant in Profiles Drilldown | Yes |
|
||||
| `sharingDashboardImage` | Enables image sharing functionality for dashboards | Yes |
|
||||
| `tabularNumbers` | Use fixed-width numbers globally in the UI | |
|
||||
| `dashboardDsAdHocFiltering` | Enables adhoc filtering support for the dashboard datasource | Yes |
|
||||
| `adhocFiltersInTooltips` | Enable adhoc filter buttons in visualization tooltips | Yes |
|
||||
|
||||
@@ -161,19 +161,10 @@ Query expressions are different for each data source. For more information, refe
|
||||
|
||||
1. [Enter general options](#enter-general-options).
|
||||
1. Under the **Query options** section of the page, select a target data source in the **Data source** drop-down list.
|
||||
|
||||
You can also click **Open advanced data source picker** to see more options, including adding a data source (Admins only).
|
||||
For more information about data sources, refer to [Add a data source](ref:add-a-data-source).
|
||||
|
||||
1. In the **Query type** drop-down list, select one of the following options:
|
||||
- **Label names**
|
||||
- **Label values**
|
||||
- **Metrics**
|
||||
- **Query result**
|
||||
- **Series query**
|
||||
- **Classic query**
|
||||
|
||||
1. In the **Query** field, enter a query.
|
||||
1. In the **Query type** drop-down list, select an option and fill in the query fields accordingly.
|
||||
- The query field varies according to your data source. Some data sources have custom query editors.
|
||||
- Each data source defines how the variable values are extracted. The typical implementation uses every string value returned from the data source response as a variable value. Make sure to double-check the documentation for the data source.
|
||||
- Some data sources let you provide custom "display names" for the values. For instance, the PostgreSQL, MySQL, and Microsoft SQL Server plugins handle this by looking for fields named `__text` and `__value` in the result. Other data sources may look for `text` and `value` or use a different approach. Always remember to double-check the documentation for the data source.
|
||||
@@ -185,9 +176,15 @@ Query expressions are different for each data source. For more information, refe
|
||||
- **On dashboard load** - Queries the data source every time the dashboard loads. This slows down dashboard loading, because the variable query needs to be completed before dashboard can be initialized.
|
||||
- **On time range change** - Queries the data source every time the dashboard loads and when the dashboard time range changes. Use this option if your variable options query contains a time range filter or is dependent on the dashboard time range.
|
||||
|
||||
1. (Optional) In the **Static options** section of the page, toggle on the **Use static options** switch to add custom options in addition to the query results:
|
||||
- Make entries in the **Value** and **Display text** fields.
|
||||
- Click **+ Add new option** to add another static option.
|
||||
- Repeat these steps as many times as needed.
|
||||
|
||||
1. (Optional) Configure the settings in the [Selection Options](#configure-variable-selection-options) section:
|
||||
- **Multi-value** - Enables multiple values to be selected at the same time.
|
||||
- **Include All option** - Enables an option to include all variables.
|
||||
- **Allow custom values** - Enables users to add custom values to the list.
|
||||
- **Include All option** - Enables an option to include all variables. Enter a value in the **Custom all value** field to set your own "all" option.
|
||||
|
||||
1. In the **Preview of values** section, Grafana displays a list of the current variable values. Review them to ensure they match what you expect.
|
||||
1. Click **Save dashboard**.
|
||||
|
||||
@@ -131,7 +131,7 @@ It also helps you avoid having several users build the same queries for the same
|
||||
|
||||
You can see a list of these queries in the **Saved queries** drawer:
|
||||
|
||||
{{< figure src="/media/docs/grafana/panels-visualizations/screenshot-saved-queries-v12.2png.png" max-width="550px" alt="List of saved queries and the edit query form" caption="The Saved queries drawer accessed from Dashboards" >}}
|
||||
{{< figure src="/media/docs/grafana/dashboards/screenshot-saved-queries-v12.3.png" max-width="550px" alt="List of saved queries and the edit query form" caption="The Saved queries drawer accessed from Dashboards" >}}
|
||||
|
||||
When you first open the drawer, the list of queries in the **All** tab is filtered by the data source of the panel.
|
||||
However, you can clear that filter to display all saved queries.
|
||||
@@ -150,8 +150,6 @@ In the **Saved queries** drawer, you can:
|
||||
- Edit a query title, description, tags, or the availability of the query to other users in your organization. By default, saved queries are locked for editing.
|
||||
- When you access the **Saved queries** drawer from Explore, you can use the **Edit in Explore** option to edit the body of a query.
|
||||
|
||||
Access the duplicate, lock, unlock, and delete query options through the menu in the top-right corner of the query form next to the **Edit** button.
|
||||
|
||||
To access your saved queries, click **+ Add from saved queries** in the query editor:
|
||||
|
||||
{{< figure src="/media/docs/grafana/panels-visualizations/screenshot-add-from-saved-2-v12.2.png" max-width="750px" alt="Add a saved query" >}}
|
||||
|
||||
@@ -212,23 +212,20 @@ You can add multiple layers of data to a single geomap in order to create rich,
|
||||
|
||||
#### Layer type
|
||||
|
||||
There are seven map layer types to choose from in a geomap.
|
||||
There are eight map layer types to choose from in a geomap.
|
||||
|
||||
- [Markers](#markers-layer) renders a marker at each data point.
|
||||
- [Heatmap](#heatmap-layer) visualizes a heatmap of the data.
|
||||
- [GeoJSON](#geojson-layer) renders static data from a GeoJSON file.
|
||||
- [Night / Day](#night--day-layer) renders a night / day region.
|
||||
- [Route (Beta)](#route-layer-beta) render data points as a route.
|
||||
- [Photos (Beta)](#photos-layer-beta) renders a photo at each data point.
|
||||
- [Network (Beta)](#network-layer-beta) visualizes a network graph from the data.
|
||||
- [Route](#route-layer) render data points as a route.
|
||||
- [Photos](#photos-layer) renders a photo at each data point.
|
||||
- [Network](#network-layer) visualizes a network graph from the data.
|
||||
- [Open Street Map](#open-street-map-layer) adds a map from a collaborative free geographic world database.
|
||||
- [CARTO basemap](#carto-basemap-layer) adds a layer from CARTO Raster basemaps.
|
||||
- [ArcGIS MapServer](#arcgis-mapserver-layer) adds a layer from an ESRI ArcGIS MapServer.
|
||||
- [XYZ Tile layer](#xyz-tile-layer) adds a map from a generic tile layer.
|
||||
|
||||
{{< admonition type="note" >}}
|
||||
Beta is equivalent to the [public preview](/docs/release-life-cycle/) release stage.
|
||||
{{< /admonition >}}
|
||||
- [MapLibre Style layer](#maplibre-style-layer) adds a map from a MapLibre/Mapbox style URL.
|
||||
|
||||
There are also two experimental (or alpha) layer types.
|
||||
|
||||
@@ -361,11 +358,7 @@ The Night / Day layer displays night and day regions based on the current time r
|
||||
|
||||
[Extensions for OpenLayers - DayNight](https://viglino.github.io/ol-ext/examples/layer/map.daynight.html)
|
||||
|
||||
#### Route layer (Beta)
|
||||
|
||||
{{< admonition type="caution" >}}
|
||||
The Route layer is currently in [public preview](/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
|
||||
{{< /admonition >}}
|
||||
#### Route layer
|
||||
|
||||
The Route layer renders data points as a route.
|
||||
|
||||
@@ -390,11 +383,7 @@ The layer can also render a route with arrows.
|
||||
|
||||
[Extensions for OpenLayers - Flow Line Style](http://viglino.github.io/ol-ext/examples/style/map.style.gpxline.html)
|
||||
|
||||
#### Photos layer (Beta)
|
||||
|
||||
{{< admonition type="caution" >}}
|
||||
The Photos layer is currently in [public preview](/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
|
||||
{{< /admonition >}}
|
||||
#### Photos layer
|
||||
|
||||
The Photos layer renders a photo at each data point.
|
||||
|
||||
@@ -417,11 +406,7 @@ The Photos layer renders a photo at each data point.
|
||||
|
||||
[Extensions for OpenLayers - Image Photo Style](http://viglino.github.io/ol-ext/examples/style/map.style.photo.html)
|
||||
|
||||
#### Network layer (Beta)
|
||||
|
||||
{{< admonition type="caution" >}}
|
||||
The Network layer is currently in [public preview](/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
|
||||
{{< /admonition >}}
|
||||
#### Network layer
|
||||
|
||||
The Network layer renders a network graph. This layer supports the same [data format supported by the node graph visualization](ref:data-format) with the addition of [geospatial data](#location-mode) included in the nodes data. The geospatial data is used to locate and render the nodes on the map.
|
||||
|
||||
@@ -534,6 +519,13 @@ The XYZ Tile layer is a map from a generic tile layer.
|
||||
- [Tiled Web Map Wikipedia](https://en.wikipedia.org/wiki/Tiled_web_map)
|
||||
- [List of Open Street Map Tile Servers](https://wiki.openstreetmap.org/wiki/Tile_servers)
|
||||
|
||||
#### MapLibre Style layer
|
||||
|
||||
The MapLibre Style Layer is a map defined using a MapLibre/Mapbox `style.json` URL. The style contains the URL to the tiles, layer definitions, and more. Typically, they're based on vector tiles as opposed to raster tiles.
|
||||
|
||||
- **URL template** - Set a valid style URL. For example: `https://demotiles.maplibre.org/style.json`
|
||||
- **Access Token** - An API token for mapbox maps. Only works for `mapbox://` URLs. Refer to [mapbox access tokens documentation](https://docs.mapbox.com/help/dive-deeper/access-tokens/) for more information. In other cases, you might have to include the token in the URL. For example: `https://example.com/map/style.json?key=XXX`.
|
||||
|
||||
### Basemap layer options
|
||||
|
||||
A basemap layer provides the visual foundation for a mapping application. It typically contains data with global coverage. Several base layer options
|
||||
@@ -541,12 +533,13 @@ are available each with specific configuration options to style the base map.
|
||||
|
||||
Basemap layer types can also be added as layers. You can specify an opacity.
|
||||
|
||||
There are four basemap layer types to choose from in a geomap.
|
||||
There are five basemap layer types to choose from in a geomap.
|
||||
|
||||
- [Open Street Map](#open-street-map-layer) adds a map from a collaborative free geographic world database.
|
||||
- [CARTO basemap](#carto-basemap-layer) adds a layer from CARTO Raster basemaps.
|
||||
- [ArcGIS MapServer](#arcgis-mapserver-layer) adds a layer from an ESRI ArcGIS MapServer.
|
||||
- [XYZ Tile layer](#xyz-tile-layer) adds a map from a generic tile layer.
|
||||
- [MapLibre Style layer](#maplibre-style-layer) adds a map from a MapLibre/Mapbox style URL.
|
||||
|
||||
The default basemap layer uses the CARTO map. You can define custom default base layers in the `.ini` configuration file.
|
||||
|
||||
@@ -556,7 +549,7 @@ The default basemap layer uses the CARTO map. You can define custom default base
|
||||
|
||||
You can configure the default base map using config files with Grafana’s provisioning system. For more information on all the settings, refer to the [provisioning docs page](ref:provisioning-docs-page).
|
||||
|
||||
Use the JSON configuration option `default_baselayer_config` to define the default base map. There are currently four base map options to choose from: `carto`, `esri-xyz`, `osm-standard`, `xyz`. Here are some provisioning examples for each base map option.
|
||||
Use the JSON configuration option `default_baselayer_config` to define the default base map. There are currently five base map options to choose from: `carto`, `esri-xyz`, `osm-standard`, `xyz`, `maplibre`. Here are some provisioning examples for each base map option.
|
||||
|
||||
- **carto** loads the CartoDB tile server. You can choose from `auto`, `dark`, and `light` theme for the base map and can be set as shown below. The `showLabels` tag determines whether or not Grafana shows the Country details on top of the map. Here is an example:
|
||||
|
||||
@@ -622,6 +615,17 @@ default_baselayer_config = `{
|
||||
}`
|
||||
```
|
||||
|
||||
- **maplibre** loads a custom tile server defined by the user. Set a valid style `url` for this option to properly load a default base map. Here's an example:
|
||||
|
||||
```ini
|
||||
default_baselayer_config = `{
|
||||
"type": "maplibre",
|
||||
"config": {
|
||||
"url": "https://demotiles.maplibre.org/style.json"
|
||||
}
|
||||
}`
|
||||
```
|
||||
|
||||
`enable_custom_baselayers` allows you to enable or disable custom open source base maps that are already implemented. The default is `true`.
|
||||
|
||||
### Map controls options
|
||||
@@ -709,7 +713,7 @@ Displays debug information in the upper right corner. This can be useful for deb
|
||||
|
||||
#### Tooltip
|
||||
|
||||
Tooltips are supported for the **Markers**, **Heatmap**, **Photos** (beta) layers.
|
||||
Tooltips are supported for the **Markers**, **Heatmap**, **Photos** layers.
|
||||
For these layer types, choose from the following tooltip options:
|
||||
|
||||
- **None** displays tooltips only when a data point is clicked.
|
||||
|
||||
@@ -33,7 +33,20 @@ _Logs_ are structured records of events or messages generated by a system or app
|
||||
|
||||
The logs visualization displays these records from data sources that support logs, such as Elastic, Influx, and Loki. The logs visualization has colored indicators of log status, as well as collapsible log events that help you analyze the information generated.
|
||||
|
||||

|
||||
{{< figure src="/media/docs/grafana/panels-visualizations/screenshot-logs-v12.3.png" max-width="750px" alt="Logs visualization" >}}
|
||||
|
||||
When the log line details are open, you have access to the following additional options:
|
||||
|
||||
- Explain log line in Assistant
|
||||
- Copy to clipboard
|
||||
- Anchor to the right
|
||||
- Close log details
|
||||
|
||||
{{< figure src="/media/docs/grafana/panels-visualizations/screenshot-logs-options-v12.3.png" max-width="750px" alt="Log icons" >}}
|
||||
|
||||
You can access the first three options from the log line details or from the log line menu:
|
||||
|
||||
{{< figure src="/media/docs/grafana/panels-visualizations/screenshot-log-line-menu-v12.3.png" max-width="300px" alt="The log line menu" >}}
|
||||
|
||||
{{< docs/play title="Logs Panel" url="https://play.grafana.org/d/6NmftOxZz/" >}}
|
||||
|
||||
@@ -53,7 +66,7 @@ You can also build log-formatted data from other data sources as long as the fir
|
||||
|
||||
The second field is used as the log record title regardless of whether it’s a time, numeric, or string field. Usually the second field is a text field containing multiple string elements, but if the message level (or `lvl`) is present, the visualization uses the values in it to add colors to the record, as described in [Log levels integration](ref:log-levels).
|
||||
|
||||
Subsequent fields are collapsed inside of each log record and you can open them by clicking the expand (`>`) icon.
|
||||
Subsequent fields are collapsed inside of each log record.
|
||||
|
||||
To limit the number of log lines rendered in the visualization, you can use the **Max data points** setting in the panel **Query options**. If that option isn't set, then the data source typically enforces its own default limit.
|
||||
|
||||
@@ -65,11 +78,11 @@ To limit the number of log lines rendered in the visualization, you can use the
|
||||
| 2023-02-01 11:30:00 | title=Log1 lvl=error | 1 | server2 | 2023-02-01 11:00:00 |
|
||||
| 2023-02-01 11:00:00 | title=Log1 lvl=trace | 1 | server2 | 2023-02-01 11:00:00 |
|
||||
|
||||

|
||||
{{< figure src="/media/docs/grafana/panels-visualizations/screenshot-logs-example2-v12.3.png" max-width="750px" alt="Logs example" >}}
|
||||
|
||||
## Log level
|
||||
|
||||
For logs where a **level** label is specified, we use the value of the label to determine the log level and update color accordingly. If the log doesn't have a level label specified, we try to find out if its content matches any of the supported expressions (see below for more information). The log level is always determined by the first match. In case Grafana is not able to determine a log level, it will be visualized with **unknown** log level. See [supported log levels and mappings of log level abbreviation and expressions](ref:log-levels).
|
||||
For logs where a `level` label is specified, we use the value of the label to determine the log level and update color accordingly. If the log doesn't have a level label specified, we try to find out if its content matches any of the supported expressions (see below for more information). The log level is always determined by the first match. In case Grafana is not able to determine a log level, it will be visualized with **unknown** log level. See [supported log levels and mappings of log level abbreviation and expressions](ref:log-levels).
|
||||
|
||||
## Configuration options
|
||||
|
||||
@@ -85,14 +98,18 @@ Use these settings to refine your visualization:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Option | Description |
|
||||
| --------------- | --------------- |
|
||||
| Time | Show or hide the time column. This is the timestamp associated with the log line as reported from the data source. |
|
||||
| Unique labels | Show or hide the unique labels column, which shows only non-common labels. |
|
||||
| Common labels | Show or hide the common labels. |
|
||||
| Wrap lines | Turn line wrapping on or off. |
|
||||
| Prettify JSON | Toggle the switch on to pretty print all JSON logs. This setting does not affect logs in any format other than JSON. |
|
||||
| Enable logs highlighting | Experimental. Use a predefined coloring scheme to highlight relevant parts of the log lines. Subtle colors are added to the log lines to improve readability and help with identifying important information faster. |
|
||||
| Enable log details | Toggle the switch on to see an extendable area with log details including labels and detected fields. Each field or label has a stats icon to display ad-hoc statistics in relation to all displayed logs. The default setting is on. |
|
||||
| Log details panel mode | Choose to display the log details in a sidebar panel or inline, below the log line. The default mode depends on viewport size: the default mode for smaller viewports is inline, while for larger ones, it's sidebar. You can also change mode dynamically in the panel by clicking the mode control. |
|
||||
| Enable infinite scrolling | Request more results by scrolling to the bottom of the logs list. When you reach the bottom of the list of logs, if you continue scrolling and the displayed logs are within the selected time interval, you can request to load more logs. When the sort order is **Newest first**, you receive older logs, and when the sort order is **Oldest first** you get newer logs. |
|
||||
| Show controls | Display controls to jump to the last or first log line, and filter by log level. |
|
||||
| Font size | Select between the **Default** font size and **Small** font sizes.|
|
||||
| Deduplication | Hide log messages that are duplicates of others shown, according to your selected criteria. Choose from: <ul><li>**Exact** - Ignoring ISO datetimes.</li><li>**Numerical** - Ignoring only those that differ by numbers such as IPs or latencies.</li><li>**Signatures** - Removing successive lines with identical punctuation and white space.</li></ul> |
|
||||
| Order | Set whether to show results **Newest first** or **Oldest first**. |
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ Log navigation in Explore has been significantly improved. We added pagination t
|
||||
|
||||
You can now use the Plugin catalog app to easily manage your plugins from within Grafana. Install, update, and uninstall plugins without requiring a server restart.
|
||||
|
||||
[Plugin catalog](../../administration/plugin-management/#plugin-catalog) was added as a result of this feature.
|
||||
[Plugin catalog](../../administration/plugin-management/#access-the-plugin-catalog) was added as a result of this feature.
|
||||
|
||||
### Performance improvements
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ test.use({
|
||||
viewport: { width: 1920, height: 1080 },
|
||||
});
|
||||
|
||||
test.describe(
|
||||
// Skipping due to failing test in CI
|
||||
test.skip(
|
||||
'Grouping panels',
|
||||
{
|
||||
tag: ['@dashboards'],
|
||||
|
||||
@@ -19,9 +19,7 @@ test.describe(
|
||||
// Open dashboard global variables and interpolation
|
||||
await gotoDashboardPage({ uid: DASHBOARD_UID });
|
||||
|
||||
// Get the actual timezone from the browser context (should be Pacific/Easter due to test.use)
|
||||
const timeZone = await page.evaluate(() => Intl.DateTimeFormat().resolvedOptions().timeZone);
|
||||
const example = `Example: from=now-6h&to=now&timezone=${encodeURIComponent(timeZone)}`;
|
||||
const example = `Example: from=now-6h&to=now&timezone=browser`;
|
||||
|
||||
const expectedItems: string[] = [
|
||||
'__dashboard = Templating - Global variables and interpolation',
|
||||
@@ -68,10 +66,7 @@ test.describe(
|
||||
|
||||
// Check link interpolation is working correctly
|
||||
const exampleLink = page.locator(`a:has-text("${example}")`);
|
||||
await expect(exampleLink).toHaveAttribute(
|
||||
'href',
|
||||
`https://example.com/?from=now-6h&to=now&timezone=${encodeURIComponent(timeZone)}`
|
||||
);
|
||||
await expect(exampleLink).toHaveAttribute('href', `https://example.com/?from=now-6h&to=now&timezone=browser`);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"devDependencies": {
|
||||
"@grafana/plugin-configs": "workspace:*",
|
||||
"@types/lodash": "4.17.7",
|
||||
"@types/node": "22.15.0",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/prismjs": "1.26.4",
|
||||
"@types/react": "18.3.18",
|
||||
"@types/react-dom": "18.3.5",
|
||||
|
||||
@@ -10,6 +10,7 @@ export function ExposedComponents() {
|
||||
const { component: ReusableComponent } = usePluginComponent<ReusableComponentProps>(
|
||||
'grafana-extensionexample1-app/reusable-component/v1'
|
||||
);
|
||||
const { component: AddToDashboardForm } = usePluginComponent('grafana/add-to-dashboard-form/v1');
|
||||
|
||||
if (!ReusableComponent) {
|
||||
return null;
|
||||
@@ -20,6 +21,22 @@ export function ExposedComponents() {
|
||||
<div data-testid={testIds.exposedComponentsPage.container}>
|
||||
<ReusableComponent name={'World'} />
|
||||
</div>
|
||||
{AddToDashboardForm && (
|
||||
<section>
|
||||
<h3>Save to dashboard (exposed form)</h3>
|
||||
<AddToDashboardForm
|
||||
// Create a recognizable panel for assertion
|
||||
buildPanel={() => ({
|
||||
type: 'timeseries',
|
||||
title: 'E2E Add to Dashboard Panel',
|
||||
targets: [],
|
||||
})}
|
||||
// Ensure navigation works correctly from plugin page
|
||||
options={{ useAbsolutePath: true }}
|
||||
onClose={() => {}}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
</PluginPage>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
"grafanaDependency": ">=10.4.0",
|
||||
"plugins": [],
|
||||
"extensions": {
|
||||
"exposedComponents": ["grafana-extensionexample1-app/reusable-component/v1"]
|
||||
"exposedComponents": ["grafana-extensionexample1-app/reusable-component/v1", "grafana/add-to-dashboard-form/v1"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+30
@@ -1,6 +1,7 @@
|
||||
import { test, expect } from '@grafana/plugin-e2e';
|
||||
import { testIds } from '../testIds';
|
||||
import pluginJson from '../plugin.json';
|
||||
import { ensureExtensionRegistryIsPopulated } from './utils';
|
||||
|
||||
test.describe(
|
||||
'grafana-extensionstest-app',
|
||||
@@ -12,5 +13,34 @@ test.describe(
|
||||
await page.goto(`/a/${pluginJson.id}/exposed-components`);
|
||||
await expect(page.getByTestId(testIds.appB.exposedComponent)).toHaveText('Hello World!');
|
||||
});
|
||||
|
||||
test('exposed add-to-dashboard form saves to a new dashboard', async ({ page }) => {
|
||||
await page.goto(`/a/${pluginJson.id}/exposed-components`);
|
||||
await ensureExtensionRegistryIsPopulated(page);
|
||||
|
||||
// Wait for the exposed form section to be ready
|
||||
await expect(page.getByRole('heading', { name: 'Save to dashboard (exposed form)' })).toBeVisible();
|
||||
|
||||
// Wait for any of the form buttons to render (lazy load) before clicking
|
||||
const openInNewTab = page.getByRole('button', { name: 'Open in new tab' });
|
||||
const cancelBtn = page.getByRole('button', { name: 'Cancel' });
|
||||
await Promise.race([expect(openInNewTab).toBeVisible(), expect(cancelBtn).toBeVisible()]);
|
||||
|
||||
// Now wait for the submit button to be visible, then click (role or text)
|
||||
const openDashboardByRole = page.getByRole('button', { name: 'Open dashboard' });
|
||||
const openDashboardByText = page.getByText('Open dashboard');
|
||||
if (await openDashboardByRole.isVisible().catch(() => false)) {
|
||||
await openDashboardByRole.click();
|
||||
} else {
|
||||
await expect(openDashboardByText.first()).toBeVisible();
|
||||
await openDashboardByText.first().click();
|
||||
}
|
||||
|
||||
// Navigates to /dashboard/new and prepopulates a panel from local storage
|
||||
await expect(page).toHaveURL(/\/dashboard\/new/);
|
||||
|
||||
// Panel should be created with our custom title
|
||||
await expect(page.getByText('E2E Add to Dashboard Panel').first()).toBeVisible();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"devDependencies": {
|
||||
"@grafana/plugin-configs": "workspace:*",
|
||||
"@types/lodash": "4.17.7",
|
||||
"@types/node": "22.15.0",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/prismjs": "1.26.4",
|
||||
"@types/react": "18.3.18",
|
||||
"@types/react-dom": "18.3.5",
|
||||
|
||||
@@ -539,11 +539,6 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"packages/grafana-sql/src/components/ErrorBoundary.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"packages/grafana-sql/src/components/configuration/ConnectionLimits.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 2
|
||||
@@ -666,11 +661,6 @@
|
||||
"count": 3
|
||||
}
|
||||
},
|
||||
"packages/grafana-ui/src/components/ErrorBoundary/ErrorBoundary.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"packages/grafana-ui/src/components/FormField/FormField.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 1
|
||||
@@ -1278,21 +1268,11 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/core/components/Select/ServiceAccountPicker.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/core/components/Select/TeamPicker.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/core/components/Select/UserPicker.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/core/components/SharedPreferences/SharedPreferences.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 8
|
||||
@@ -1342,11 +1322,6 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"public/app/core/components/TimelineChart/TimelineChart.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/core/config.ts": {
|
||||
"no-barrel-files/no-barrel-files": {
|
||||
"count": 2
|
||||
@@ -1483,25 +1458,17 @@
|
||||
"public/app/features/admin/UserLdapSyncInfo.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 3
|
||||
},
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/admin/UserOrgs.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 2
|
||||
},
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 3
|
||||
}
|
||||
},
|
||||
"public/app/features/admin/UserProfile.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/admin/UserSessions.tsx": {
|
||||
"public/app/features/admin/UserProfile.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
@@ -2110,11 +2077,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/dashboard-scene/saving/SaveDashboardAsForm.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 4
|
||||
}
|
||||
},
|
||||
"public/app/features/dashboard-scene/saving/SaveDashboardForm.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 1
|
||||
@@ -2404,9 +2366,6 @@
|
||||
"public/app/features/dashboard/components/DashboardSettings/TimePickerSettings.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 5
|
||||
},
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/dashboard/components/DashboardSettings/VersionsSettings.tsx": {
|
||||
@@ -2757,11 +2716,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/datasources/components/DataSourcePluginSettings.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/datasources/components/DataSourcePluginState.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 3
|
||||
@@ -2877,11 +2831,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/explore/ExploreTimeControls.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/explore/Logs/LiveLogs.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
@@ -2982,11 +2931,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/explore/TraceView/components/common/SearchBarInput.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/explore/TraceView/components/demo/trace-generators.ts": {
|
||||
"@typescript-eslint/consistent-type-assertions": {
|
||||
"count": 1
|
||||
@@ -3123,11 +3067,6 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"public/app/features/live/LiveConnectionWarning.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/live/centrifuge/LiveDataStream.ts": {
|
||||
"@typescript-eslint/consistent-type-assertions": {
|
||||
"count": 1
|
||||
@@ -3379,11 +3318,6 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"public/app/features/provisioning/File/FileStatusPage.tsx": {
|
||||
"@typescript-eslint/consistent-type-assertions": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"public/app/features/provisioning/Shared/BranchValidationError.tsx": {
|
||||
"react/no-unescaped-entities": {
|
||||
"count": 26
|
||||
@@ -3588,11 +3522,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/transformers/editors/ConcatenateTransformerEditor.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/transformers/editors/ConvertFieldTypeTransformerEditor.tsx": {
|
||||
"@typescript-eslint/consistent-type-assertions": {
|
||||
"count": 1
|
||||
@@ -3710,11 +3639,6 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"public/app/features/variables/constant/ConstantVariableEditor.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/variables/constant/reducer.ts": {
|
||||
"@typescript-eslint/consistent-type-assertions": {
|
||||
"count": 1
|
||||
@@ -3797,9 +3721,6 @@
|
||||
"public/app/features/variables/pickers/shared/VariableInput.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 1
|
||||
},
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/variables/pickers/shared/VariableOptions.tsx": {
|
||||
@@ -4014,11 +3935,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/plugins/datasource/cloud-monitoring/components/ConfigEditor/ConfigEditor.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/plugins/datasource/cloud-monitoring/components/Fields.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 1
|
||||
@@ -4217,11 +4133,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/plugins/datasource/grafana-testdata-datasource/components/CSVWaveEditor.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/plugins/datasource/grafana-testdata-datasource/components/RandomWalkEditor.tsx": {
|
||||
"@typescript-eslint/consistent-type-assertions": {
|
||||
"count": 2
|
||||
@@ -4930,11 +4841,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/plugins/panel/stat/StatPanel.tsx": {
|
||||
"react-prefer-function-component/react-prefer-function-component": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/plugins/panel/state-timeline/migrations.ts": {
|
||||
"@typescript-eslint/no-explicit-any": {
|
||||
"count": 2
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user