Compare commits
6 Commits
selectable
...
davkal-das
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
edf18e9c5f | ||
|
|
2f7ef05eda | ||
|
|
c4ee6a6425 | ||
|
|
b5320defd1 | ||
|
|
7bea99a54b | ||
|
|
6291c18ba1 |
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -85,7 +85,6 @@
|
||||
# Git Sync frontend owned by frontend team as a whole.
|
||||
|
||||
/apps/alerting/ @grafana/alerting-backend
|
||||
/apps/quotas/ @grafana/grafana-search-and-storage
|
||||
/apps/dashboard/ @grafana/grafana-app-platform-squad @grafana/dashboards-squad
|
||||
/apps/folder/ @grafana/grafana-app-platform-squad
|
||||
/apps/playlist/ @grafana/grafana-app-platform-squad
|
||||
|
||||
8
.github/commands.json
vendored
8
.github/commands.json
vendored
@@ -1226,13 +1226,5 @@
|
||||
"addToProject": {
|
||||
"url": "https://github.com/orgs/grafana/projects/69"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"name": "area/suggestions",
|
||||
"action": "addToProject",
|
||||
"addToProject": {
|
||||
"url": "https://github.com/orgs/grafana/projects/56"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
10
.github/pr-commands.json
vendored
10
.github/pr-commands.json
vendored
@@ -469,15 +469,5 @@
|
||||
"addToProject": {
|
||||
"url": "https://github.com/orgs/grafana/projects/190"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "changedfiles",
|
||||
"matches": [
|
||||
"public/app/features/panel/suggestions/**/*",
|
||||
"public/app/plugins/panel/**/suggestions.ts",
|
||||
"packages/grafana-data/src/types/suggestions*"
|
||||
],
|
||||
"action": "updateLabel",
|
||||
"addLabel": "area/suggestions"
|
||||
}
|
||||
]
|
||||
|
||||
6
.github/workflows/add-to-whats-new.yml
vendored
6
.github/workflows/add-to-whats-new.yml
vendored
@@ -1,11 +1,11 @@
|
||||
name: Add comment about adding a What's new note for either what's new or breaking changes
|
||||
name: Add comment about adding a What's new note
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
add-comment:
|
||||
if: ${{ ! github.event.pull_request.head.repo.fork && (contains(github.event.pull_request.labels.*.name, 'add to what''s new') || contains(github.event.pull_request.labels.*.name, 'breaking change') || contains(github.event.pull_request.labels.*.name, 'levitate breaking change')) }}
|
||||
if: ${{ ! github.event.pull_request.head.repo.fork && contains(github.event.pull_request.labels.*.name, 'add to what''s new') }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
@@ -13,4 +13,4 @@ jobs:
|
||||
- uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4
|
||||
with:
|
||||
message: |
|
||||
Since you've added the `What's New` or a breaking change label, consider drafting a [What's new note](https://admin.grafana.com/content-admin/#/collections/whats-new/new) for this feature.
|
||||
Since you've added the `Add to what's new` label, consider drafting a [What's new note](https://admin.grafana.com/content-admin/#/collections/whats-new/new) for this feature.
|
||||
|
||||
1
.github/workflows/auto-triager/labels.txt
vendored
1
.github/workflows/auto-triager/labels.txt
vendored
@@ -85,7 +85,6 @@ area/scenes
|
||||
area/search
|
||||
area/security
|
||||
area/streaming
|
||||
area/suggestions
|
||||
area/templating/repeating
|
||||
area/tooltip
|
||||
area/transformations
|
||||
|
||||
@@ -33,16 +33,6 @@ jobs:
|
||||
GCOM_TOKEN=ephemeral-instances-bot:gcom-token
|
||||
REGISTRY=ephemeral-instances-bot:registry
|
||||
GCP_SA_ACCOUNT_KEY_BASE64=ephemeral-instances-bot:sa-key
|
||||
# Secrets placed in the ci/common/<path> path in Vault
|
||||
common_secrets: |
|
||||
DOCKERHUB_USERNAME=dockerhub:username
|
||||
DOCKERHUB_PASSWORD=dockerhub:password
|
||||
|
||||
- name: Log in to Docker Hub to avoid unauthenticated image pull rate-limiting
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
username: ${{ env.DOCKERHUB_USERNAME }}
|
||||
password: ${{ env.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Generate a GitHub app installation token
|
||||
id: generate_token
|
||||
|
||||
@@ -14,7 +14,7 @@ ARG JS_SRC=js-builder
|
||||
|
||||
# Dependabot cannot update dependencies listed in ARGs
|
||||
# By using FROM instructions we can delegate dependency updates to dependabot
|
||||
FROM alpine:3.23.0 AS alpine-base
|
||||
FROM alpine:3.22.2 AS alpine-base
|
||||
FROM ubuntu:22.04 AS ubuntu-base
|
||||
FROM golang:1.25.5-alpine AS go-builder-base
|
||||
FROM --platform=${JS_PLATFORM} node:24-alpine AS js-builder-base
|
||||
@@ -93,7 +93,6 @@ COPY pkg/storage/unified/apistore pkg/storage/unified/apistore
|
||||
COPY pkg/semconv pkg/semconv
|
||||
COPY pkg/aggregator pkg/aggregator
|
||||
COPY apps/playlist apps/playlist
|
||||
COPY apps/quotas apps/quotas
|
||||
COPY apps/plugins apps/plugins
|
||||
COPY apps/shorturl apps/shorturl
|
||||
COPY apps/annotation apps/annotation
|
||||
|
||||
@@ -8,7 +8,7 @@ require (
|
||||
github.com/google/go-github/v70 v70.0.0
|
||||
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4
|
||||
github.com/grafana/grafana v0.0.0-00010101000000-000000000000
|
||||
github.com/grafana/grafana-app-sdk v0.48.5
|
||||
github.com/grafana/grafana-app-sdk v0.48.4
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.284.0
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0
|
||||
|
||||
@@ -618,8 +618,8 @@ github.com/grafana/dataplane/sdata v0.0.9 h1:AGL1LZnCUG4MnQtnWpBPbQ8ZpptaZs14w6k
|
||||
github.com/grafana/dataplane/sdata v0.0.9/go.mod h1:Jvs5ddpGmn6vcxT7tCTWAZ1mgi4sbcdFt9utQx5uMAU=
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI=
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
|
||||
github.com/grafana/grafana-aws-sdk v1.3.0 h1:/bfJzP93rCel1GbWoRSq0oUo424MZXt8jAp2BK9w8tM=
|
||||
|
||||
@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/alerting/alertenrichment
|
||||
go 1.25.5
|
||||
|
||||
require (
|
||||
github.com/grafana/grafana-app-sdk v0.48.5
|
||||
github.com/grafana/grafana-app-sdk v0.48.4
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250901080157-a0280d701b28
|
||||
k8s.io/apimachinery v0.34.2
|
||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912
|
||||
|
||||
@@ -23,8 +23,8 @@ github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7O
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250901080157-a0280d701b28 h1:PgMfX4OPENz/iXmtDDIW9+poZY4UD0hhmXm7flVclDo=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250901080157-a0280d701b28/go.mod h1:av5N0Naq+8VV9MLF7zAkihy/mVq5UbS2EvRSJukDHlY=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
|
||||
@@ -6,7 +6,7 @@ require (
|
||||
github.com/go-kit/log v0.2.1
|
||||
github.com/grafana/alerting v0.0.0-20251204145817-de8c2bbf9eba
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4
|
||||
github.com/grafana/grafana-app-sdk v0.48.5
|
||||
github.com/grafana/grafana-app-sdk v0.48.4
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/spf13/pflag v1.0.10
|
||||
|
||||
@@ -216,16 +216,14 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/grafana/alerting v0.0.0-20251204145817-de8c2bbf9eba h1:psKWNETD5nGxmFAlqnWsXoRyUwSa2GHNEMSEDKGKfQ4=
|
||||
github.com/grafana/alerting v0.0.0-20251204145817-de8c2bbf9eba/go.mod h1:l7v67cgP7x72ajB9UPZlumdrHqNztpKoqQ52cU8T3LU=
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI=
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
|
||||
github.com/grafana/loki/pkg/push v0.0.0-20250823105456-332df2b20000 h1:/5LKSYgLmAhwA4m6iGUD4w1YkydEWWjazn9qxCFT8W0=
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
@@ -16,14 +15,9 @@ const (
|
||||
lokiDefaultMaxQuerySize = 65536 // 64kb
|
||||
)
|
||||
|
||||
type LokiConfig struct {
|
||||
lokiclient.LokiConfig
|
||||
Transport http.RoundTripper
|
||||
}
|
||||
|
||||
type NotificationConfig struct {
|
||||
Enabled bool
|
||||
Loki LokiConfig
|
||||
Loki lokiclient.LokiConfig
|
||||
}
|
||||
|
||||
type RuntimeConfig struct {
|
||||
@@ -33,7 +27,7 @@ type RuntimeConfig struct {
|
||||
|
||||
func (n *NotificationConfig) AddFlagsWithPrefix(prefix string, flags *pflag.FlagSet) {
|
||||
flags.BoolVar(&n.Enabled, prefix+".enabled", false, "Enable notification query endpoints")
|
||||
addLokiFlags(&n.Loki.LokiConfig, prefix+".loki", flags)
|
||||
addLokiFlags(&n.Loki, prefix+".loki", flags)
|
||||
}
|
||||
|
||||
func (r *RuntimeConfig) AddFlagsWithPrefix(prefix string, flags *pflag.FlagSet) {
|
||||
|
||||
@@ -24,12 +24,10 @@ func TestRuntimeConfig(t *testing.T) {
|
||||
expected: RuntimeConfig{
|
||||
Notification: NotificationConfig{
|
||||
Enabled: false,
|
||||
Loki: LokiConfig{
|
||||
LokiConfig: lokiclient.LokiConfig{
|
||||
ReadPathURL: nil,
|
||||
MaxQueryLength: 721 * time.Hour,
|
||||
MaxQuerySize: 65536,
|
||||
},
|
||||
Loki: lokiclient.LokiConfig{
|
||||
ReadPathURL: nil,
|
||||
MaxQueryLength: 721 * time.Hour,
|
||||
MaxQuerySize: 65536,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -40,12 +38,10 @@ func TestRuntimeConfig(t *testing.T) {
|
||||
expected: RuntimeConfig{
|
||||
Notification: NotificationConfig{
|
||||
Enabled: true,
|
||||
Loki: LokiConfig{
|
||||
LokiConfig: lokiclient.LokiConfig{
|
||||
ReadPathURL: nil,
|
||||
MaxQueryLength: 721 * time.Hour,
|
||||
MaxQuerySize: 65536,
|
||||
},
|
||||
Loki: lokiclient.LokiConfig{
|
||||
ReadPathURL: nil,
|
||||
MaxQueryLength: 721 * time.Hour,
|
||||
MaxQuerySize: 65536,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -61,15 +57,13 @@ func TestRuntimeConfig(t *testing.T) {
|
||||
expected: RuntimeConfig{
|
||||
Notification: NotificationConfig{
|
||||
Enabled: false,
|
||||
Loki: LokiConfig{
|
||||
LokiConfig: lokiclient.LokiConfig{
|
||||
ReadPathURL: lokiURL,
|
||||
BasicAuthUser: "foo",
|
||||
BasicAuthPassword: "bar",
|
||||
TenantID: "baz",
|
||||
MaxQueryLength: 721 * time.Hour,
|
||||
MaxQuerySize: 65536,
|
||||
},
|
||||
Loki: lokiclient.LokiConfig{
|
||||
ReadPathURL: lokiURL,
|
||||
BasicAuthUser: "foo",
|
||||
BasicAuthPassword: "bar",
|
||||
TenantID: "baz",
|
||||
MaxQueryLength: 721 * time.Hour,
|
||||
MaxQuerySize: 65536,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -20,7 +19,6 @@ import (
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/grafana/grafana/apps/alerting/historian/pkg/apis/alertinghistorian/v0alpha1"
|
||||
"github.com/grafana/grafana/apps/alerting/historian/pkg/app/config"
|
||||
"github.com/grafana/grafana/apps/alerting/historian/pkg/app/logutil"
|
||||
)
|
||||
|
||||
@@ -49,7 +47,7 @@ type LokiReader struct {
|
||||
logger logging.Logger
|
||||
}
|
||||
|
||||
func NewLokiReader(cfg config.LokiConfig, reg prometheus.Registerer, logger logging.Logger, tracer trace.Tracer) *LokiReader {
|
||||
func NewLokiReader(cfg lokiclient.LokiConfig, reg prometheus.Registerer, logger logging.Logger, tracer trace.Tracer) *LokiReader {
|
||||
duration := instrument.NewHistogramCollector(promauto.With(reg).NewHistogramVec(prometheus.HistogramOpts{
|
||||
Namespace: Namespace,
|
||||
Subsystem: Subsystem,
|
||||
@@ -58,13 +56,9 @@ func NewLokiReader(cfg config.LokiConfig, reg prometheus.Registerer, logger logg
|
||||
Buckets: instrument.DefBuckets,
|
||||
}, instrument.HistogramCollectorBuckets))
|
||||
|
||||
requester := &http.Client{
|
||||
Transport: cfg.Transport,
|
||||
}
|
||||
|
||||
gkLogger := logutil.ToGoKitLogger(logger)
|
||||
return &LokiReader{
|
||||
client: lokiclient.NewLokiClient(cfg.LokiConfig, requester, nil, duration, gkLogger, tracer, LokiClientSpanName),
|
||||
client: lokiclient.NewLokiClient(cfg, lokiclient.NewRequester(), nil, duration, gkLogger, tracer, LokiClientSpanName),
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/alerting/notifications
|
||||
go 1.25.5
|
||||
|
||||
require (
|
||||
github.com/grafana/grafana-app-sdk v0.48.5
|
||||
github.com/grafana/grafana-app-sdk v0.48.4
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3
|
||||
k8s.io/apimachinery v0.34.2
|
||||
k8s.io/apiserver v0.34.2
|
||||
|
||||
@@ -71,8 +71,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o=
|
||||
|
||||
@@ -23,12 +23,6 @@ type Receiver struct {
|
||||
Spec ReceiverSpec `json:"spec" yaml:"spec"`
|
||||
}
|
||||
|
||||
func NewReceiver() *Receiver {
|
||||
return &Receiver{
|
||||
Spec: *NewReceiverSpec(),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Receiver) GetSpec() any {
|
||||
return o.Spec
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaReceiver = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", NewReceiver(), &ReceiverList{}, resource.WithKind("Receiver"),
|
||||
schemaReceiver = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &Receiver{}, &ReceiverList{}, resource.WithKind("Receiver"),
|
||||
resource.WithPlural("receivers"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
|
||||
FieldSelector: "spec.title",
|
||||
FieldValueFunc: func(o resource.Object) (string, error) {
|
||||
|
||||
@@ -23,12 +23,6 @@ type RoutingTree struct {
|
||||
Spec RoutingTreeSpec `json:"spec" yaml:"spec"`
|
||||
}
|
||||
|
||||
func NewRoutingTree() *RoutingTree {
|
||||
return &RoutingTree{
|
||||
Spec: *NewRoutingTreeSpec(),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *RoutingTree) GetSpec() any {
|
||||
return o.Spec
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaRoutingTree = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", NewRoutingTree(), &RoutingTreeList{}, resource.WithKind("RoutingTree"),
|
||||
schemaRoutingTree = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &RoutingTree{}, &RoutingTreeList{}, resource.WithKind("RoutingTree"),
|
||||
resource.WithPlural("routingtrees"), resource.WithScope(resource.NamespacedScope))
|
||||
kindRoutingTree = resource.Kind{
|
||||
Schema: schemaRoutingTree,
|
||||
|
||||
@@ -23,12 +23,6 @@ type TemplateGroup struct {
|
||||
Spec TemplateGroupSpec `json:"spec" yaml:"spec"`
|
||||
}
|
||||
|
||||
func NewTemplateGroup() *TemplateGroup {
|
||||
return &TemplateGroup{
|
||||
Spec: *NewTemplateGroupSpec(),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *TemplateGroup) GetSpec() any {
|
||||
return o.Spec
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaTemplateGroup = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", NewTemplateGroup(), &TemplateGroupList{}, resource.WithKind("TemplateGroup"),
|
||||
schemaTemplateGroup = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TemplateGroup{}, &TemplateGroupList{}, resource.WithKind("TemplateGroup"),
|
||||
resource.WithPlural("templategroups"), resource.WithScope(resource.NamespacedScope))
|
||||
kindTemplateGroup = resource.Kind{
|
||||
Schema: schemaTemplateGroup,
|
||||
|
||||
@@ -23,12 +23,6 @@ type TimeInterval struct {
|
||||
Spec TimeIntervalSpec `json:"spec" yaml:"spec"`
|
||||
}
|
||||
|
||||
func NewTimeInterval() *TimeInterval {
|
||||
return &TimeInterval{
|
||||
Spec: *NewTimeIntervalSpec(),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *TimeInterval) GetSpec() any {
|
||||
return o.Spec
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaTimeInterval = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", NewTimeInterval(), &TimeIntervalList{}, resource.WithKind("TimeInterval"),
|
||||
schemaTimeInterval = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TimeInterval{}, &TimeIntervalList{}, resource.WithKind("TimeInterval"),
|
||||
resource.WithPlural("timeintervals"), resource.WithScope(resource.NamespacedScope))
|
||||
kindTimeInterval = resource.Kind{
|
||||
Schema: schemaTimeInterval,
|
||||
|
||||
@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/alerting/rules
|
||||
go 1.25.5
|
||||
|
||||
require (
|
||||
github.com/grafana/grafana-app-sdk v0.48.5
|
||||
github.com/grafana/grafana-app-sdk v0.48.4
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3
|
||||
github.com/prometheus/common v0.67.3
|
||||
k8s.io/apimachinery v0.34.2
|
||||
|
||||
@@ -48,8 +48,8 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
|
||||
|
||||
@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/annotation
|
||||
go 1.25.5
|
||||
|
||||
require (
|
||||
github.com/grafana/grafana-app-sdk v0.48.5
|
||||
github.com/grafana/grafana-app-sdk v0.48.4
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3
|
||||
k8s.io/apimachinery v0.34.2
|
||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912
|
||||
|
||||
@@ -48,8 +48,8 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
|
||||
|
||||
@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/collections
|
||||
go 1.25.5
|
||||
|
||||
require (
|
||||
github.com/grafana/grafana-app-sdk v0.48.5
|
||||
github.com/grafana/grafana-app-sdk v0.48.4
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2
|
||||
github.com/stretchr/testify v1.11.1
|
||||
k8s.io/apimachinery v0.34.2
|
||||
|
||||
@@ -33,8 +33,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2 h1:X0cnaFdR+iz+sDSuoZmkryFSjOirchHe2MdKSRwBWgM=
|
||||
|
||||
@@ -8,8 +8,9 @@ import (
|
||||
func (stars *StarsSpec) Add(group, kind, name string) {
|
||||
for i, r := range stars.Resource {
|
||||
if r.Group == group && r.Kind == kind {
|
||||
stars.Resource[i].Names = append(r.Names, name)
|
||||
stars.Normalize()
|
||||
r.Names = append(r.Names, name)
|
||||
slices.Sort(r.Names)
|
||||
stars.Resource[i].Names = slices.Compact(r.Names)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -45,15 +46,8 @@ func (stars *StarsSpec) Normalize() {
|
||||
resources := make([]StarsResource, 0, len(stars.Resource))
|
||||
for _, r := range stars.Resource {
|
||||
if len(r.Names) > 0 {
|
||||
unique := make([]string, 0, len(r.Names))
|
||||
found := make(map[string]bool, len(r.Names))
|
||||
for _, name := range r.Names {
|
||||
if !found[name] {
|
||||
unique = append(unique, name)
|
||||
found[name] = true
|
||||
}
|
||||
}
|
||||
r.Names = unique
|
||||
slices.Sort(r.Names)
|
||||
r.Names = slices.Compact(r.Names) // removes any duplicates
|
||||
resources = append(resources, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestStarsWrite(t *testing.T) {
|
||||
Resource: []StarsResource{{
|
||||
Group: "g",
|
||||
Kind: "k",
|
||||
Names: []string{"a", "b", "x", "c"}, // added c to the end
|
||||
Names: []string{"a", "b", "c", "x"}, // added "b" (and sorted)
|
||||
}},
|
||||
},
|
||||
}, {
|
||||
|
||||
@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/correlations
|
||||
go 1.25.5
|
||||
|
||||
require (
|
||||
github.com/grafana/grafana-app-sdk v0.48.5
|
||||
github.com/grafana/grafana-app-sdk v0.48.4
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3
|
||||
k8s.io/apimachinery v0.34.2
|
||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912
|
||||
|
||||
@@ -48,8 +48,8 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
|
||||
|
||||
@@ -11,7 +11,8 @@ do-generate: install-app-sdk update-app-sdk ## Run Grafana App SDK code generati
|
||||
--tsgenpath=../../packages/grafana-schema/src/schema \
|
||||
--grouping=group \
|
||||
--defencoding=none \
|
||||
--genoperatorstate=false
|
||||
--genoperatorstate=false \
|
||||
--noschemasinmanifest
|
||||
|
||||
.PHONY: post-generate-cleanup
|
||||
post-generate-cleanup: ## Clean up the generated code
|
||||
|
||||
@@ -5,7 +5,7 @@ go 1.25.5
|
||||
require (
|
||||
cuelang.org/go v0.11.1
|
||||
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4
|
||||
github.com/grafana/grafana-app-sdk v0.48.5
|
||||
github.com/grafana/grafana-app-sdk v0.48.4
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.284.0
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e
|
||||
@@ -57,7 +57,6 @@ require (
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-plugin v1.7.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||
github.com/jaegertracing/jaeger-idl v0.5.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
|
||||
@@ -85,8 +85,8 @@ github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 h1:Muoy+FMGr
|
||||
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4/go.mod h1:qeWYbnWzaYGl88JlL9+DsP1GT2Cudm58rLtx13fKZdw=
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI=
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
|
||||
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
|
||||
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.284.0 h1:1bK7eWsnPBLUWDcWJWe218Ik5ad0a5JpEL4mH9ry7Ws=
|
||||
@@ -112,8 +112,6 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-plugin v1.7.0 h1:YghfQH/0QmPNc/AZMTFE3ac8fipZyZECHdDPshfk+mA=
|
||||
github.com/hashicorp/go-plugin v1.7.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
|
||||
github.com/jaegertracing/jaeger-idl v0.5.0 h1:zFXR5NL3Utu7MhPg8ZorxtCBjHrL3ReM1VoB65FOFGE=
|
||||
|
||||
@@ -768,10 +768,6 @@ VariableRefresh: *"never" | "onDashboardLoad" | "onTimeRangeChanged"
|
||||
// Accepted values are `dontHide` (show label and value), `hideLabel` (show value only), `hideVariable` (show nothing).
|
||||
VariableHide: *"dontHide" | "hideLabel" | "hideVariable"
|
||||
|
||||
// Determine whether regex applies to variable value or display text
|
||||
// Accepted values are `value` (apply to value used in queries) or `text` (apply to display text shown to users)
|
||||
VariableRegexApplyTo: *"value" | "text"
|
||||
|
||||
// Determine the origin of the adhoc variable filter
|
||||
FilterOrigin: "dashboard"
|
||||
|
||||
@@ -807,7 +803,6 @@ QueryVariableSpec: {
|
||||
datasource?: DataSourceRef
|
||||
query: DataQueryKind
|
||||
regex: string | *""
|
||||
regexApplyTo?: VariableRegexApplyTo
|
||||
sort: VariableSort
|
||||
definition?: string
|
||||
options: [...VariableOption] | *[]
|
||||
|
||||
@@ -772,10 +772,6 @@ VariableRefresh: *"never" | "onDashboardLoad" | "onTimeRangeChanged"
|
||||
// Accepted values are `dontHide` (show label and value), `hideLabel` (show value only), `hideVariable` (show nothing), `inControlsMenu` (show in a drop-down menu).
|
||||
VariableHide: *"dontHide" | "hideLabel" | "hideVariable" | "inControlsMenu"
|
||||
|
||||
// Determine whether regex applies to variable value or display text
|
||||
// Accepted values are `value` (apply to value used in queries) or `text` (apply to display text shown to users)
|
||||
VariableRegexApplyTo: *"value" | "text"
|
||||
|
||||
// Determine the origin of the adhoc variable filter
|
||||
FilterOrigin: "dashboard"
|
||||
|
||||
@@ -810,7 +806,6 @@ QueryVariableSpec: {
|
||||
description?: string
|
||||
query: DataQueryKind
|
||||
regex: string | *""
|
||||
regexApplyTo?: VariableRegexApplyTo
|
||||
sort: VariableSort
|
||||
definition?: string
|
||||
options: [...VariableOption] | *[]
|
||||
|
||||
@@ -222,8 +222,6 @@ lineage: schemas: [{
|
||||
// Optional field, if you want to extract part of a series name or metric node segment.
|
||||
// Named capture groups can be used to separate the display text and value.
|
||||
regex?: string
|
||||
// Determine whether regex applies to variable value or display text
|
||||
regexApplyTo?: #VariableRegexApplyTo
|
||||
// Additional static options for query variable
|
||||
staticOptions?: [...#VariableOption]
|
||||
// Ordering of static options in relation to options returned from data source for query variable
|
||||
@@ -251,10 +249,6 @@ lineage: schemas: [{
|
||||
// Accepted values are 0 (show label and value), 1 (show value only), 2 (show nothing), 3 (show under the controls dropdown menu).
|
||||
#VariableHide: 0 | 1 | 2 | 3 @cuetsy(kind="enum",memberNames="dontHide|hideLabel|hideVariable|inControlsMenu") @grafana(TSVeneer="type")
|
||||
|
||||
// Determine whether regex applies to variable value or display text
|
||||
// Accepted values are "value" (apply to value used in queries) or "text" (apply to display text shown to users)
|
||||
#VariableRegexApplyTo: "value" | "text" @cuetsy(kind="type")
|
||||
|
||||
// Sort variable options
|
||||
// Accepted values are:
|
||||
// `0`: No sorting
|
||||
|
||||
@@ -25,13 +25,6 @@ type Dashboard struct {
|
||||
Status DashboardStatus `json:"status" yaml:"status"`
|
||||
}
|
||||
|
||||
func NewDashboard() *Dashboard {
|
||||
return &Dashboard{
|
||||
Spec: *NewDashboardSpec(),
|
||||
Status: *NewDashboardStatus(),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Dashboard) GetSpec() any {
|
||||
return o.Spec
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v0alpha1", NewDashboard(), &DashboardList{}, resource.WithKind("Dashboard"),
|
||||
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v0alpha1", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"),
|
||||
resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope))
|
||||
kindDashboard = resource.Kind{
|
||||
Schema: schemaDashboard,
|
||||
|
||||
@@ -23,12 +23,6 @@ type Snapshot struct {
|
||||
Spec SnapshotSpec `json:"spec" yaml:"spec"`
|
||||
}
|
||||
|
||||
func NewSnapshot() *Snapshot {
|
||||
return &Snapshot{
|
||||
Spec: *NewSnapshotSpec(),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Snapshot) GetSpec() any {
|
||||
return o.Spec
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaSnapshot = resource.NewSimpleSchema("dashboard.grafana.app", "v0alpha1", NewSnapshot(), &SnapshotList{}, resource.WithKind("Snapshot"),
|
||||
schemaSnapshot = resource.NewSimpleSchema("dashboard.grafana.app", "v0alpha1", &Snapshot{}, &SnapshotList{}, resource.WithKind("Snapshot"),
|
||||
resource.WithPlural("snapshots"), resource.WithScope(resource.NamespacedScope))
|
||||
kindSnapshot = resource.Kind{
|
||||
Schema: schemaSnapshot,
|
||||
|
||||
@@ -222,8 +222,6 @@ lineage: schemas: [{
|
||||
// Optional field, if you want to extract part of a series name or metric node segment.
|
||||
// Named capture groups can be used to separate the display text and value.
|
||||
regex?: string
|
||||
// Determine whether regex applies to variable value or display text
|
||||
regexApplyTo?: #VariableRegexApplyTo
|
||||
// Additional static options for query variable
|
||||
staticOptions?: [...#VariableOption]
|
||||
// Ordering of static options in relation to options returned from data source for query variable
|
||||
@@ -251,10 +249,6 @@ lineage: schemas: [{
|
||||
// Accepted values are 0 (show label and value), 1 (show value only), 2 (show nothing), 3 (show under the controls dropdown menu).
|
||||
#VariableHide: 0 | 1 | 2 | 3 @cuetsy(kind="enum",memberNames="dontHide|hideLabel|hideVariable|inControlsMenu") @grafana(TSVeneer="type")
|
||||
|
||||
// Determine whether regex applies to variable value or display text
|
||||
// Accepted values are "value" (apply to value used in queries) or "text" (apply to display text shown to users)
|
||||
#VariableRegexApplyTo: "value" | "text" @cuetsy(kind="type")
|
||||
|
||||
// Sort variable options
|
||||
// Accepted values are:
|
||||
// `0`: No sorting
|
||||
|
||||
@@ -25,13 +25,6 @@ type Dashboard struct {
|
||||
Status DashboardStatus `json:"status" yaml:"status"`
|
||||
}
|
||||
|
||||
func NewDashboard() *Dashboard {
|
||||
return &Dashboard{
|
||||
Spec: *NewDashboardSpec(),
|
||||
Status: *NewDashboardStatus(),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Dashboard) GetSpec() any {
|
||||
return o.Spec
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v1beta1", NewDashboard(), &DashboardList{}, resource.WithKind("Dashboard"),
|
||||
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v1beta1", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"),
|
||||
resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope))
|
||||
kindDashboard = resource.Kind{
|
||||
Schema: schemaDashboard,
|
||||
|
||||
@@ -25,13 +25,6 @@ type Dashboard struct {
|
||||
Status DashboardStatus `json:"status" yaml:"status"`
|
||||
}
|
||||
|
||||
func NewDashboard() *Dashboard {
|
||||
return &Dashboard{
|
||||
Spec: *NewDashboardSpec(),
|
||||
Status: *NewDashboardStatus(),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Dashboard) GetSpec() any {
|
||||
return o.Spec
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2alpha1", NewDashboard(), &DashboardList{}, resource.WithKind("Dashboard"),
|
||||
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2alpha1", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"),
|
||||
resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope))
|
||||
kindDashboard = resource.Kind{
|
||||
Schema: schemaDashboard,
|
||||
|
||||
@@ -772,10 +772,6 @@ VariableRefresh: *"never" | "onDashboardLoad" | "onTimeRangeChanged"
|
||||
// Accepted values are `dontHide` (show label and value), `hideLabel` (show value only), `hideVariable` (show nothing).
|
||||
VariableHide: *"dontHide" | "hideLabel" | "hideVariable"
|
||||
|
||||
// Determine whether regex applies to variable value or display text
|
||||
// Accepted values are `value` (apply to value used in queries) or `text` (apply to display text shown to users)
|
||||
VariableRegexApplyTo: *"value" | "text"
|
||||
|
||||
// Determine the origin of the adhoc variable filter
|
||||
FilterOrigin: "dashboard"
|
||||
|
||||
@@ -811,7 +807,6 @@ QueryVariableSpec: {
|
||||
datasource?: DataSourceRef
|
||||
query: DataQueryKind
|
||||
regex: string | *""
|
||||
regexApplyTo?: VariableRegexApplyTo
|
||||
sort: VariableSort
|
||||
definition?: string
|
||||
options: [...VariableOption] | *[]
|
||||
|
||||
@@ -1364,7 +1364,6 @@ type DashboardQueryVariableSpec struct {
|
||||
Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
|
||||
Query DashboardDataQueryKind `json:"query"`
|
||||
Regex string `json:"regex"`
|
||||
RegexApplyTo *DashboardVariableRegexApplyTo `json:"regexApplyTo,omitempty"`
|
||||
Sort DashboardVariableSort `json:"sort"`
|
||||
Definition *string `json:"definition,omitempty"`
|
||||
Options []DashboardVariableOption `json:"options"`
|
||||
@@ -1394,7 +1393,6 @@ func NewDashboardQueryVariableSpec() *DashboardQueryVariableSpec {
|
||||
SkipUrlSync: false,
|
||||
Query: *NewDashboardDataQueryKind(),
|
||||
Regex: "",
|
||||
RegexApplyTo: (func(input DashboardVariableRegexApplyTo) *DashboardVariableRegexApplyTo { return &input })(DashboardVariableRegexApplyToValue),
|
||||
Options: []DashboardVariableOption{},
|
||||
Multi: false,
|
||||
IncludeAll: false,
|
||||
@@ -1445,16 +1443,6 @@ const (
|
||||
DashboardVariableRefreshOnTimeRangeChanged DashboardVariableRefresh = "onTimeRangeChanged"
|
||||
)
|
||||
|
||||
// Determine whether regex applies to variable value or display text
|
||||
// Accepted values are `value` (apply to value used in queries) or `text` (apply to display text shown to users)
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardVariableRegexApplyTo string
|
||||
|
||||
const (
|
||||
DashboardVariableRegexApplyToValue DashboardVariableRegexApplyTo = "value"
|
||||
DashboardVariableRegexApplyToText DashboardVariableRegexApplyTo = "text"
|
||||
)
|
||||
|
||||
// Sort variable options
|
||||
// Accepted values are:
|
||||
// `disabled`: No sorting
|
||||
|
||||
@@ -3646,12 +3646,6 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardQueryVariableSpec(ref common.Re
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"regexApplyTo": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"sort": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
|
||||
@@ -25,13 +25,6 @@ type Dashboard struct {
|
||||
Status DashboardStatus `json:"status" yaml:"status"`
|
||||
}
|
||||
|
||||
func NewDashboard() *Dashboard {
|
||||
return &Dashboard{
|
||||
Spec: *NewDashboardSpec(),
|
||||
Status: *NewDashboardStatus(),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Dashboard) GetSpec() any {
|
||||
return o.Spec
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// schema is unexported to prevent accidental overwrites
|
||||
var (
|
||||
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2beta1", NewDashboard(), &DashboardList{}, resource.WithKind("Dashboard"),
|
||||
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2beta1", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"),
|
||||
resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope))
|
||||
kindDashboard = resource.Kind{
|
||||
Schema: schemaDashboard,
|
||||
|
||||
@@ -776,10 +776,6 @@ VariableRefresh: *"never" | "onDashboardLoad" | "onTimeRangeChanged"
|
||||
// Accepted values are `dontHide` (show label and value), `hideLabel` (show value only), `hideVariable` (show nothing), `inControlsMenu` (show in a drop-down menu).
|
||||
VariableHide: *"dontHide" | "hideLabel" | "hideVariable" | "inControlsMenu"
|
||||
|
||||
// Determine whether regex applies to variable value or display text
|
||||
// Accepted values are `value` (apply to value used in queries) or `text` (apply to display text shown to users)
|
||||
VariableRegexApplyTo: *"value" | "text"
|
||||
|
||||
// Determine the origin of the adhoc variable filter
|
||||
FilterOrigin: "dashboard"
|
||||
|
||||
@@ -814,7 +810,6 @@ QueryVariableSpec: {
|
||||
description?: string
|
||||
query: DataQueryKind
|
||||
regex: string | *""
|
||||
regexApplyTo?: VariableRegexApplyTo
|
||||
sort: VariableSort
|
||||
definition?: string
|
||||
options: [...VariableOption] | *[]
|
||||
|
||||
@@ -1367,7 +1367,6 @@ type DashboardQueryVariableSpec struct {
|
||||
Description *string `json:"description,omitempty"`
|
||||
Query DashboardDataQueryKind `json:"query"`
|
||||
Regex string `json:"regex"`
|
||||
RegexApplyTo *DashboardVariableRegexApplyTo `json:"regexApplyTo,omitempty"`
|
||||
Sort DashboardVariableSort `json:"sort"`
|
||||
Definition *string `json:"definition,omitempty"`
|
||||
Options []DashboardVariableOption `json:"options"`
|
||||
@@ -1397,7 +1396,6 @@ func NewDashboardQueryVariableSpec() *DashboardQueryVariableSpec {
|
||||
SkipUrlSync: false,
|
||||
Query: *NewDashboardDataQueryKind(),
|
||||
Regex: "",
|
||||
RegexApplyTo: (func(input DashboardVariableRegexApplyTo) *DashboardVariableRegexApplyTo { return &input })(DashboardVariableRegexApplyToValue),
|
||||
Options: []DashboardVariableOption{},
|
||||
Multi: false,
|
||||
IncludeAll: false,
|
||||
@@ -1449,16 +1447,6 @@ const (
|
||||
DashboardVariableRefreshOnTimeRangeChanged DashboardVariableRefresh = "onTimeRangeChanged"
|
||||
)
|
||||
|
||||
// Determine whether regex applies to variable value or display text
|
||||
// Accepted values are `value` (apply to value used in queries) or `text` (apply to display text shown to users)
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardVariableRegexApplyTo string
|
||||
|
||||
const (
|
||||
DashboardVariableRegexApplyToValue DashboardVariableRegexApplyTo = "value"
|
||||
DashboardVariableRegexApplyToText DashboardVariableRegexApplyTo = "text"
|
||||
)
|
||||
|
||||
// Sort variable options
|
||||
// Accepted values are:
|
||||
// `disabled`: No sorting
|
||||
|
||||
@@ -3656,12 +3656,6 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableSpec(ref common.Ref
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"regexApplyTo": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"sort": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
|
||||
24
apps/dashboard/pkg/apis/dashboard_manifest.go
generated
24
apps/dashboard/pkg/apis/dashboard_manifest.go
generated
File diff suppressed because one or more lines are too long
@@ -12,6 +12,13 @@ import (
|
||||
)
|
||||
|
||||
func RegisterConversions(s *runtime.Scheme, dsIndexProvider schemaversion.DataSourceIndexProvider, leIndexProvider schemaversion.LibraryElementIndexProvider) error {
|
||||
// Wrap the provider once with 10s caching for all conversions.
|
||||
// This prevents repeated DB queries across multiple conversion calls while allowing
|
||||
// the cache to refresh periodically, making it suitable for long-lived singleton usage.
|
||||
dsIndexProvider = schemaversion.WrapIndexProviderWithCache(dsIndexProvider)
|
||||
// Wrap library element provider with caching as well
|
||||
leIndexProvider = schemaversion.WrapLibraryElementProviderWithCache(leIndexProvider)
|
||||
|
||||
// v0 conversions
|
||||
if err := s.AddConversionFunc((*dashv0.Dashboard)(nil), (*dashv1.Dashboard)(nil),
|
||||
withConversionMetrics(dashv0.APIVERSION, dashv1.APIVERSION, func(a, b interface{}, scope conversion.Scope) error {
|
||||
@@ -55,13 +62,13 @@ func RegisterConversions(s *runtime.Scheme, dsIndexProvider schemaversion.DataSo
|
||||
// v2alpha1 conversions
|
||||
if err := s.AddConversionFunc((*dashv2alpha1.Dashboard)(nil), (*dashv0.Dashboard)(nil),
|
||||
withConversionMetrics(dashv2alpha1.APIVERSION, dashv0.APIVERSION, func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_V2alpha1_to_V0(a.(*dashv2alpha1.Dashboard), b.(*dashv0.Dashboard), scope)
|
||||
return Convert_V2alpha1_to_V0(a.(*dashv2alpha1.Dashboard), b.(*dashv0.Dashboard), scope, dsIndexProvider)
|
||||
})); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*dashv2alpha1.Dashboard)(nil), (*dashv1.Dashboard)(nil),
|
||||
withConversionMetrics(dashv2alpha1.APIVERSION, dashv1.APIVERSION, func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_V2alpha1_to_V1beta1(a.(*dashv2alpha1.Dashboard), b.(*dashv1.Dashboard), scope)
|
||||
return Convert_V2alpha1_to_V1beta1(a.(*dashv2alpha1.Dashboard), b.(*dashv1.Dashboard), scope, dsIndexProvider)
|
||||
})); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,454 +0,0 @@
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
dashv0 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
|
||||
dashv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
|
||||
dashv2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
|
||||
dashv2beta1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1"
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/migration"
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
|
||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// countingDataSourceProvider tracks how many times Index() is called
|
||||
type countingDataSourceProvider struct {
|
||||
datasources []schemaversion.DataSourceInfo
|
||||
callCount atomic.Int64
|
||||
}
|
||||
|
||||
func newCountingDataSourceProvider(datasources []schemaversion.DataSourceInfo) *countingDataSourceProvider {
|
||||
return &countingDataSourceProvider{
|
||||
datasources: datasources,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *countingDataSourceProvider) Index(_ context.Context) *schemaversion.DatasourceIndex {
|
||||
p.callCount.Add(1)
|
||||
return schemaversion.NewDatasourceIndex(p.datasources)
|
||||
}
|
||||
|
||||
func (p *countingDataSourceProvider) getCallCount() int64 {
|
||||
return p.callCount.Load()
|
||||
}
|
||||
|
||||
// countingLibraryElementProvider tracks how many times GetLibraryElementInfo() is called
|
||||
type countingLibraryElementProvider struct {
|
||||
elements []schemaversion.LibraryElementInfo
|
||||
callCount atomic.Int64
|
||||
}
|
||||
|
||||
func newCountingLibraryElementProvider(elements []schemaversion.LibraryElementInfo) *countingLibraryElementProvider {
|
||||
return &countingLibraryElementProvider{
|
||||
elements: elements,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *countingLibraryElementProvider) GetLibraryElementInfo(_ context.Context) []schemaversion.LibraryElementInfo {
|
||||
p.callCount.Add(1)
|
||||
return p.elements
|
||||
}
|
||||
|
||||
func (p *countingLibraryElementProvider) getCallCount() int64 {
|
||||
return p.callCount.Load()
|
||||
}
|
||||
|
||||
// createTestV0Dashboard creates a minimal v0 dashboard for testing
|
||||
// The dashboard has a datasource with UID only (no type) to force provider lookup
|
||||
// and includes library panels to test library element provider caching
|
||||
func createTestV0Dashboard(namespace, title string) *dashv0.Dashboard {
|
||||
return &dashv0.Dashboard{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-dashboard",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: common.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"title": title,
|
||||
"schemaVersion": schemaversion.LATEST_VERSION,
|
||||
// Variables with datasource reference that requires lookup
|
||||
"templating": map[string]interface{}{
|
||||
"list": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "query_var",
|
||||
"type": "query",
|
||||
"query": "label_values(up, job)",
|
||||
// Datasource with UID only - type needs to be looked up
|
||||
"datasource": map[string]interface{}{
|
||||
"uid": "ds1",
|
||||
// type is intentionally omitted to trigger provider lookup
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"panels": []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": 1,
|
||||
"title": "Test Panel",
|
||||
"type": "timeseries",
|
||||
"targets": []interface{}{
|
||||
map[string]interface{}{
|
||||
// Datasource with UID only - type needs to be looked up
|
||||
"datasource": map[string]interface{}{
|
||||
"uid": "ds1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// Library panel reference - triggers library element provider lookup
|
||||
map[string]interface{}{
|
||||
"id": 2,
|
||||
"title": "Library Panel with Horizontal Repeat",
|
||||
"type": "library-panel-ref",
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 8,
|
||||
},
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": "lib-panel-repeat-h",
|
||||
"name": "Library Panel with Horizontal Repeat",
|
||||
},
|
||||
},
|
||||
// Another library panel reference
|
||||
map[string]interface{}{
|
||||
"id": 3,
|
||||
"title": "Library Panel without Repeat",
|
||||
"type": "library-panel-ref",
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 3,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 16,
|
||||
},
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": "lib-panel-no-repeat",
|
||||
"name": "Library Panel without Repeat",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// createTestV1Dashboard creates a minimal v1beta1 dashboard for testing
|
||||
// The dashboard has a datasource with UID only (no type) to force provider lookup
|
||||
// and includes library panels to test library element provider caching
|
||||
func createTestV1Dashboard(namespace, title string) *dashv1.Dashboard {
|
||||
return &dashv1.Dashboard{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-dashboard",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: common.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"title": title,
|
||||
"schemaVersion": schemaversion.LATEST_VERSION,
|
||||
// Variables with datasource reference that requires lookup
|
||||
"templating": map[string]interface{}{
|
||||
"list": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "query_var",
|
||||
"type": "query",
|
||||
"query": "label_values(up, job)",
|
||||
// Datasource with UID only - type needs to be looked up
|
||||
"datasource": map[string]interface{}{
|
||||
"uid": "ds1",
|
||||
// type is intentionally omitted to trigger provider lookup
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"panels": []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": 1,
|
||||
"title": "Test Panel",
|
||||
"type": "timeseries",
|
||||
"targets": []interface{}{
|
||||
map[string]interface{}{
|
||||
// Datasource with UID only - type needs to be looked up
|
||||
"datasource": map[string]interface{}{
|
||||
"uid": "ds1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// Library panel reference - triggers library element provider lookup
|
||||
map[string]interface{}{
|
||||
"id": 2,
|
||||
"title": "Library Panel with Vertical Repeat",
|
||||
"type": "library-panel-ref",
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 4,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 8,
|
||||
},
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": "lib-panel-repeat-v",
|
||||
"name": "Library Panel with Vertical Repeat",
|
||||
},
|
||||
},
|
||||
// Another library panel reference
|
||||
map[string]interface{}{
|
||||
"id": 3,
|
||||
"title": "Library Panel without Repeat",
|
||||
"type": "library-panel-ref",
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 3,
|
||||
"w": 6,
|
||||
"x": 6,
|
||||
"y": 8,
|
||||
},
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": "lib-panel-no-repeat",
|
||||
"name": "Library Panel without Repeat",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// TestConversionCaching_V0_to_V2alpha1 verifies caching works when converting V0 to V2alpha1
|
||||
func TestConversionCaching_V0_to_V2alpha1(t *testing.T) {
|
||||
datasources := []schemaversion.DataSourceInfo{
|
||||
{UID: "ds1", Type: "prometheus", Name: "Prometheus", Default: true},
|
||||
}
|
||||
elements := []schemaversion.LibraryElementInfo{
|
||||
{UID: "lib-panel-repeat-h", Name: "Library Panel with Horizontal Repeat", Type: "timeseries"},
|
||||
{UID: "lib-panel-no-repeat", Name: "Library Panel without Repeat", Type: "graph"},
|
||||
}
|
||||
|
||||
underlyingDS := newCountingDataSourceProvider(datasources)
|
||||
underlyingLE := newCountingLibraryElementProvider(elements)
|
||||
|
||||
cachedDS := schemaversion.WrapIndexProviderWithCache(underlyingDS, time.Minute)
|
||||
cachedLE := schemaversion.WrapLibraryElementProviderWithCache(underlyingLE, time.Minute)
|
||||
|
||||
migration.ResetForTesting()
|
||||
migration.Initialize(cachedDS, cachedLE, migration.DefaultCacheTTL)
|
||||
|
||||
// Convert multiple dashboards in the same namespace
|
||||
numDashboards := 5
|
||||
namespace := "default"
|
||||
|
||||
for i := 0; i < numDashboards; i++ {
|
||||
source := createTestV0Dashboard(namespace, "Dashboard "+string(rune('A'+i)))
|
||||
target := &dashv2alpha1.Dashboard{}
|
||||
|
||||
err := Convert_V0_to_V2alpha1(source, target, nil, cachedDS, cachedLE)
|
||||
require.NoError(t, err, "conversion %d should succeed", i)
|
||||
require.NotNil(t, target.Spec)
|
||||
}
|
||||
|
||||
// With caching, the underlying datasource provider should only be called once per namespace
|
||||
// The test dashboard has datasources without type that require lookup
|
||||
assert.Equal(t, int64(1), underlyingDS.getCallCount(),
|
||||
"datasource provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
// Library element provider should also be called only once per namespace due to caching
|
||||
assert.Equal(t, int64(1), underlyingLE.getCallCount(),
|
||||
"library element provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
}
|
||||
|
||||
// TestConversionCaching_V0_to_V2beta1 verifies caching works when converting V0 to V2beta1
|
||||
func TestConversionCaching_V0_to_V2beta1(t *testing.T) {
|
||||
datasources := []schemaversion.DataSourceInfo{
|
||||
{UID: "ds1", Type: "prometheus", Name: "Prometheus", Default: true},
|
||||
}
|
||||
elements := []schemaversion.LibraryElementInfo{
|
||||
{UID: "lib-panel-repeat-h", Name: "Library Panel with Horizontal Repeat", Type: "timeseries"},
|
||||
{UID: "lib-panel-no-repeat", Name: "Library Panel without Repeat", Type: "graph"},
|
||||
}
|
||||
|
||||
underlyingDS := newCountingDataSourceProvider(datasources)
|
||||
underlyingLE := newCountingLibraryElementProvider(elements)
|
||||
|
||||
cachedDS := schemaversion.WrapIndexProviderWithCache(underlyingDS, time.Minute)
|
||||
cachedLE := schemaversion.WrapLibraryElementProviderWithCache(underlyingLE, time.Minute)
|
||||
|
||||
migration.ResetForTesting()
|
||||
migration.Initialize(cachedDS, cachedLE, migration.DefaultCacheTTL)
|
||||
|
||||
numDashboards := 5
|
||||
namespace := "default"
|
||||
|
||||
for i := 0; i < numDashboards; i++ {
|
||||
source := createTestV0Dashboard(namespace, "Dashboard "+string(rune('A'+i)))
|
||||
target := &dashv2beta1.Dashboard{}
|
||||
|
||||
err := Convert_V0_to_V2beta1(source, target, nil, cachedDS, cachedLE)
|
||||
require.NoError(t, err, "conversion %d should succeed", i)
|
||||
require.NotNil(t, target.Spec)
|
||||
}
|
||||
|
||||
assert.Equal(t, int64(1), underlyingDS.getCallCount(),
|
||||
"datasource provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
assert.Equal(t, int64(1), underlyingLE.getCallCount(),
|
||||
"library element provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
}
|
||||
|
||||
// TestConversionCaching_V1beta1_to_V2alpha1 verifies caching works when converting V1beta1 to V2alpha1
|
||||
func TestConversionCaching_V1beta1_to_V2alpha1(t *testing.T) {
|
||||
datasources := []schemaversion.DataSourceInfo{
|
||||
{UID: "ds1", Type: "prometheus", Name: "Prometheus", Default: true},
|
||||
}
|
||||
elements := []schemaversion.LibraryElementInfo{
|
||||
{UID: "lib-panel-repeat-v", Name: "Library Panel with Vertical Repeat", Type: "timeseries"},
|
||||
{UID: "lib-panel-no-repeat", Name: "Library Panel without Repeat", Type: "graph"},
|
||||
}
|
||||
|
||||
underlyingDS := newCountingDataSourceProvider(datasources)
|
||||
underlyingLE := newCountingLibraryElementProvider(elements)
|
||||
|
||||
cachedDS := schemaversion.WrapIndexProviderWithCache(underlyingDS, time.Minute)
|
||||
cachedLE := schemaversion.WrapLibraryElementProviderWithCache(underlyingLE, time.Minute)
|
||||
|
||||
migration.ResetForTesting()
|
||||
migration.Initialize(cachedDS, cachedLE, migration.DefaultCacheTTL)
|
||||
|
||||
numDashboards := 5
|
||||
namespace := "default"
|
||||
|
||||
for i := 0; i < numDashboards; i++ {
|
||||
source := createTestV1Dashboard(namespace, "Dashboard "+string(rune('A'+i)))
|
||||
target := &dashv2alpha1.Dashboard{}
|
||||
|
||||
err := Convert_V1beta1_to_V2alpha1(source, target, nil, cachedDS, cachedLE)
|
||||
require.NoError(t, err, "conversion %d should succeed", i)
|
||||
require.NotNil(t, target.Spec)
|
||||
}
|
||||
|
||||
assert.Equal(t, int64(1), underlyingDS.getCallCount(),
|
||||
"datasource provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
assert.Equal(t, int64(1), underlyingLE.getCallCount(),
|
||||
"library element provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
}
|
||||
|
||||
// TestConversionCaching_V1beta1_to_V2beta1 verifies caching works when converting V1beta1 to V2beta1
|
||||
func TestConversionCaching_V1beta1_to_V2beta1(t *testing.T) {
|
||||
datasources := []schemaversion.DataSourceInfo{
|
||||
{UID: "ds1", Type: "prometheus", Name: "Prometheus", Default: true},
|
||||
}
|
||||
elements := []schemaversion.LibraryElementInfo{
|
||||
{UID: "lib-panel-repeat-v", Name: "Library Panel with Vertical Repeat", Type: "timeseries"},
|
||||
{UID: "lib-panel-no-repeat", Name: "Library Panel without Repeat", Type: "graph"},
|
||||
}
|
||||
|
||||
underlyingDS := newCountingDataSourceProvider(datasources)
|
||||
underlyingLE := newCountingLibraryElementProvider(elements)
|
||||
|
||||
cachedDS := schemaversion.WrapIndexProviderWithCache(underlyingDS, time.Minute)
|
||||
cachedLE := schemaversion.WrapLibraryElementProviderWithCache(underlyingLE, time.Minute)
|
||||
|
||||
migration.ResetForTesting()
|
||||
migration.Initialize(cachedDS, cachedLE, migration.DefaultCacheTTL)
|
||||
|
||||
numDashboards := 5
|
||||
namespace := "default"
|
||||
|
||||
for i := 0; i < numDashboards; i++ {
|
||||
source := createTestV1Dashboard(namespace, "Dashboard "+string(rune('A'+i)))
|
||||
target := &dashv2beta1.Dashboard{}
|
||||
|
||||
err := Convert_V1beta1_to_V2beta1(source, target, nil, cachedDS, cachedLE)
|
||||
require.NoError(t, err, "conversion %d should succeed", i)
|
||||
require.NotNil(t, target.Spec)
|
||||
}
|
||||
|
||||
assert.Equal(t, int64(1), underlyingDS.getCallCount(),
|
||||
"datasource provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
assert.Equal(t, int64(1), underlyingLE.getCallCount(),
|
||||
"library element provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
}
|
||||
|
||||
// TestConversionCaching_MultipleNamespaces verifies that different namespaces get separate cache entries
|
||||
func TestConversionCaching_MultipleNamespaces(t *testing.T) {
|
||||
datasources := []schemaversion.DataSourceInfo{
|
||||
{UID: "ds1", Type: "prometheus", Name: "Prometheus", Default: true},
|
||||
}
|
||||
elements := []schemaversion.LibraryElementInfo{
|
||||
{UID: "lib-panel-repeat-h", Name: "Library Panel with Horizontal Repeat", Type: "timeseries"},
|
||||
{UID: "lib-panel-no-repeat", Name: "Library Panel without Repeat", Type: "graph"},
|
||||
}
|
||||
|
||||
underlyingDS := newCountingDataSourceProvider(datasources)
|
||||
underlyingLE := newCountingLibraryElementProvider(elements)
|
||||
|
||||
cachedDS := schemaversion.WrapIndexProviderWithCache(underlyingDS, time.Minute)
|
||||
cachedLE := schemaversion.WrapLibraryElementProviderWithCache(underlyingLE, time.Minute)
|
||||
|
||||
migration.ResetForTesting()
|
||||
migration.Initialize(cachedDS, cachedLE, migration.DefaultCacheTTL)
|
||||
|
||||
namespaces := []string{"default", "org-2", "org-3"}
|
||||
numDashboardsPerNs := 3
|
||||
|
||||
for _, ns := range namespaces {
|
||||
for i := 0; i < numDashboardsPerNs; i++ {
|
||||
source := createTestV0Dashboard(ns, "Dashboard "+string(rune('A'+i)))
|
||||
target := &dashv2alpha1.Dashboard{}
|
||||
|
||||
err := Convert_V0_to_V2alpha1(source, target, nil, cachedDS, cachedLE)
|
||||
require.NoError(t, err, "conversion for namespace %s should succeed", ns)
|
||||
}
|
||||
}
|
||||
|
||||
// With caching, each namespace should result in one call to the underlying provider
|
||||
expectedCalls := int64(len(namespaces))
|
||||
assert.Equal(t, expectedCalls, underlyingDS.getCallCount(),
|
||||
"datasource provider should be called once per namespace (%d namespaces)", len(namespaces))
|
||||
assert.Equal(t, expectedCalls, underlyingLE.getCallCount(),
|
||||
"library element provider should be called once per namespace (%d namespaces)", len(namespaces))
|
||||
}
|
||||
|
||||
// TestConversionCaching_CacheDisabled verifies that TTL=0 disables caching
|
||||
func TestConversionCaching_CacheDisabled(t *testing.T) {
|
||||
datasources := []schemaversion.DataSourceInfo{
|
||||
{UID: "ds1", Type: "prometheus", Name: "Prometheus", Default: true},
|
||||
}
|
||||
elements := []schemaversion.LibraryElementInfo{
|
||||
{UID: "lib-panel-repeat-h", Name: "Library Panel with Horizontal Repeat", Type: "timeseries"},
|
||||
{UID: "lib-panel-no-repeat", Name: "Library Panel without Repeat", Type: "graph"},
|
||||
}
|
||||
|
||||
underlyingDS := newCountingDataSourceProvider(datasources)
|
||||
underlyingLE := newCountingLibraryElementProvider(elements)
|
||||
|
||||
// TTL of 0 should disable caching - the wrapper returns the underlying provider directly
|
||||
cachedDS := schemaversion.WrapIndexProviderWithCache(underlyingDS, 0)
|
||||
cachedLE := schemaversion.WrapLibraryElementProviderWithCache(underlyingLE, 0)
|
||||
|
||||
migration.ResetForTesting()
|
||||
migration.Initialize(cachedDS, cachedLE, migration.DefaultCacheTTL)
|
||||
|
||||
numDashboards := 3
|
||||
namespace := "default"
|
||||
|
||||
for i := 0; i < numDashboards; i++ {
|
||||
source := createTestV0Dashboard(namespace, "Dashboard "+string(rune('A'+i)))
|
||||
target := &dashv2alpha1.Dashboard{}
|
||||
|
||||
err := Convert_V0_to_V2alpha1(source, target, nil, cachedDS, cachedLE)
|
||||
require.NoError(t, err, "conversion %d should succeed", i)
|
||||
}
|
||||
|
||||
// Without caching, each conversion calls the underlying provider multiple times
|
||||
// (once for each datasource lookup needed - variables and panels)
|
||||
// The key check is that the count is GREATER than 1 per conversion (no caching benefit)
|
||||
assert.Greater(t, underlyingDS.getCallCount(), int64(numDashboards),
|
||||
"with cache disabled, conversions should call datasource provider multiple times")
|
||||
// Library element provider is also called for each conversion without caching
|
||||
assert.GreaterOrEqual(t, underlyingLE.getCallCount(), int64(numDashboards),
|
||||
"with cache disabled, conversions should call library element provider multiple times")
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
|
||||
dashv0 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
|
||||
dashv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
|
||||
dashv2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
|
||||
@@ -119,14 +121,6 @@ func countPanelsV0V1(spec map[string]interface{}) int {
|
||||
return count
|
||||
}
|
||||
|
||||
// countTargetsFromPanel counts the number of targets/queries in a panel.
|
||||
func countTargetsFromPanel(panelMap map[string]interface{}) int {
|
||||
if targets, ok := panelMap["targets"].([]interface{}); ok {
|
||||
return len(targets)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// countQueriesV0V1 counts data queries in v0alpha1 or v1beta1 dashboard spec
|
||||
// Note: Row panels are layout containers and should not have queries.
|
||||
// We ignore any queries on row panels themselves, but count queries in their collapsed panels.
|
||||
@@ -151,7 +145,9 @@ func countQueriesV0V1(spec map[string]interface{}) int {
|
||||
|
||||
// Count queries in regular panels (NOT row panels)
|
||||
if panelType != "row" {
|
||||
count += countTargetsFromPanel(panelMap)
|
||||
if targets, ok := panelMap["targets"].([]interface{}); ok {
|
||||
count += len(targets)
|
||||
}
|
||||
}
|
||||
|
||||
// Count queries in collapsed panels inside row panels
|
||||
@@ -159,7 +155,9 @@ func countQueriesV0V1(spec map[string]interface{}) int {
|
||||
if collapsedPanels, ok := panelMap["panels"].([]interface{}); ok {
|
||||
for _, cp := range collapsedPanels {
|
||||
if cpMap, ok := cp.(map[string]interface{}); ok {
|
||||
count += countTargetsFromPanel(cpMap)
|
||||
if targets, ok := cpMap["targets"].([]interface{}); ok {
|
||||
count += len(targets)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -444,3 +442,77 @@ func collectDashboardStats(dashboard interface{}) dashboardStats {
|
||||
}
|
||||
return dashboardStats{}
|
||||
}
|
||||
|
||||
// withConversionDataLossDetection wraps a conversion function to detect data loss
|
||||
func withConversionDataLossDetection(sourceFuncName, targetFuncName string, conversionFunc func(a, b interface{}, scope conversion.Scope) error) func(a, b interface{}, scope conversion.Scope) error {
|
||||
return func(a, b interface{}, scope conversion.Scope) error {
|
||||
// Collect source statistics
|
||||
var sourceStats dashboardStats
|
||||
switch source := a.(type) {
|
||||
case *dashv0.Dashboard:
|
||||
if source.Spec.Object != nil {
|
||||
sourceStats = collectStatsV0V1(source.Spec.Object)
|
||||
}
|
||||
case *dashv1.Dashboard:
|
||||
if source.Spec.Object != nil {
|
||||
sourceStats = collectStatsV0V1(source.Spec.Object)
|
||||
}
|
||||
case *dashv2alpha1.Dashboard:
|
||||
sourceStats = collectStatsV2alpha1(source.Spec)
|
||||
case *dashv2beta1.Dashboard:
|
||||
sourceStats = collectStatsV2beta1(source.Spec)
|
||||
}
|
||||
|
||||
// Execute the conversion
|
||||
err := conversionFunc(a, b, scope)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Collect target statistics
|
||||
var targetStats dashboardStats
|
||||
switch target := b.(type) {
|
||||
case *dashv0.Dashboard:
|
||||
if target.Spec.Object != nil {
|
||||
targetStats = collectStatsV0V1(target.Spec.Object)
|
||||
}
|
||||
case *dashv1.Dashboard:
|
||||
if target.Spec.Object != nil {
|
||||
targetStats = collectStatsV0V1(target.Spec.Object)
|
||||
}
|
||||
case *dashv2alpha1.Dashboard:
|
||||
targetStats = collectStatsV2alpha1(target.Spec)
|
||||
case *dashv2beta1.Dashboard:
|
||||
targetStats = collectStatsV2beta1(target.Spec)
|
||||
}
|
||||
|
||||
// Detect if data was lost
|
||||
if dataLossErr := detectConversionDataLoss(sourceStats, targetStats, sourceFuncName, targetFuncName); dataLossErr != nil {
|
||||
logger.Error("Dashboard conversion data loss detected",
|
||||
"sourceFunc", sourceFuncName,
|
||||
"targetFunc", targetFuncName,
|
||||
"sourcePanels", sourceStats.panelCount,
|
||||
"targetPanels", targetStats.panelCount,
|
||||
"sourceQueries", sourceStats.queryCount,
|
||||
"targetQueries", targetStats.queryCount,
|
||||
"sourceAnnotations", sourceStats.annotationCount,
|
||||
"targetAnnotations", targetStats.annotationCount,
|
||||
"sourceLinks", sourceStats.linkCount,
|
||||
"targetLinks", targetStats.linkCount,
|
||||
"error", dataLossErr,
|
||||
)
|
||||
return dataLossErr
|
||||
}
|
||||
|
||||
logger.Debug("Dashboard conversion completed without data loss",
|
||||
"sourceFunc", sourceFuncName,
|
||||
"targetFunc", targetFuncName,
|
||||
"panels", targetStats.panelCount,
|
||||
"queries", targetStats.queryCount,
|
||||
"annotations", targetStats.annotationCount,
|
||||
"links", targetStats.linkCount,
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,7 @@ func TestConversionMatrixExist(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
versions := []metav1.Object{
|
||||
&dashv0.Dashboard{Spec: common.Unstructured{Object: map[string]any{"title": "dashboardV0"}}},
|
||||
@@ -89,7 +89,7 @@ func TestDashboardConversionToAllVersions(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
@@ -309,7 +309,7 @@ func TestMigratedDashboardsConversion(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
@@ -428,7 +428,7 @@ func setupTestConversionScheme(t *testing.T) *runtime.Scheme {
|
||||
t.Helper()
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := RegisterConversions(scheme, dsProvider, leProvider)
|
||||
@@ -527,7 +527,7 @@ func TestConversionMetrics(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -694,7 +694,7 @@ func TestConversionMetricsWrapper(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -864,7 +864,7 @@ func TestSchemaVersionExtraction(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -910,7 +910,7 @@ func TestConversionLogging(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -1003,7 +1003,7 @@ func TestConversionLogLevels(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
t.Run("log levels and structured fields verification", func(t *testing.T) {
|
||||
// Create test wrapper to verify logging behavior
|
||||
@@ -1076,7 +1076,7 @@ func TestConversionLoggingFields(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
t.Run("verify all log fields are present", func(t *testing.T) {
|
||||
// Test that the conversion wrapper includes all expected structured fields
|
||||
|
||||
@@ -17,9 +17,7 @@ import (
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
|
||||
)
|
||||
|
||||
func getLogger() logging.Logger {
|
||||
return logging.DefaultLogger.With("logger", "dashboard.conversion")
|
||||
}
|
||||
var logger = logging.DefaultLogger.With("logger", "dashboard.conversion")
|
||||
|
||||
// getErroredSchemaVersionFunc determines the schema version function that errored
|
||||
func getErroredSchemaVersionFunc(err error) string {
|
||||
@@ -199,9 +197,9 @@ func withConversionMetrics(sourceVersionAPI, targetVersionAPI string, conversion
|
||||
)
|
||||
|
||||
if errorType == "schema_minimum_version_error" {
|
||||
getLogger().Warn("Dashboard conversion failed", logFields...)
|
||||
logger.Warn("Dashboard conversion failed", logFields...)
|
||||
} else {
|
||||
getLogger().Error("Dashboard conversion failed", logFields...)
|
||||
logger.Error("Dashboard conversion failed", logFields...)
|
||||
}
|
||||
} else {
|
||||
// Record success metrics
|
||||
@@ -237,7 +235,7 @@ func withConversionMetrics(sourceVersionAPI, targetVersionAPI string, conversion
|
||||
)
|
||||
}
|
||||
|
||||
getLogger().Debug("Dashboard conversion succeeded", successLogFields...)
|
||||
logger.Debug("Dashboard conversion succeeded", successLogFields...)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -76,9 +76,9 @@
|
||||
"barGlow": false,
|
||||
"centerGlow": false,
|
||||
"rounded": true,
|
||||
"spotlight": false,
|
||||
"gradient": false
|
||||
"spotlight": false
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -155,9 +155,9 @@
|
||||
"barGlow": false,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": false,
|
||||
"gradient": false
|
||||
"spotlight": false
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -234,9 +234,9 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": false,
|
||||
"gradient": false
|
||||
"spotlight": false
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -313,9 +313,9 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": true,
|
||||
"gradient": false
|
||||
"spotlight": true
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -392,9 +392,9 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": true,
|
||||
"gradient": false
|
||||
"spotlight": true
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -471,9 +471,9 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": false,
|
||||
"spotlight": true,
|
||||
"gradient": false
|
||||
"spotlight": true
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -550,9 +550,9 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": false,
|
||||
"spotlight": true,
|
||||
"gradient": false
|
||||
"spotlight": true
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -642,9 +642,9 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": true,
|
||||
"gradient": false
|
||||
"spotlight": true
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -721,9 +721,9 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": true,
|
||||
"gradient": false
|
||||
"spotlight": true
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -800,9 +800,9 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": true,
|
||||
"gradient": false
|
||||
"spotlight": true
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -879,9 +879,9 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": true,
|
||||
"gradient": false
|
||||
"spotlight": true
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -975,9 +975,9 @@
|
||||
"barGlow": false,
|
||||
"centerGlow": false,
|
||||
"rounded": false,
|
||||
"spotlight": false,
|
||||
"gradient": false
|
||||
"spotlight": false
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1054,9 +1054,9 @@
|
||||
"barGlow": false,
|
||||
"centerGlow": false,
|
||||
"rounded": false,
|
||||
"spotlight": false,
|
||||
"gradient": false
|
||||
"spotlight": false
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1133,9 +1133,9 @@
|
||||
"barGlow": false,
|
||||
"centerGlow": false,
|
||||
"rounded": false,
|
||||
"spotlight": false,
|
||||
"gradient": true
|
||||
"spotlight": false
|
||||
},
|
||||
"gradient": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1212,9 +1212,9 @@
|
||||
"barGlow": false,
|
||||
"centerGlow": false,
|
||||
"rounded": false,
|
||||
"spotlight": false,
|
||||
"gradient": false
|
||||
"spotlight": false
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1291,9 +1291,9 @@
|
||||
"barGlow": false,
|
||||
"centerGlow": false,
|
||||
"rounded": false,
|
||||
"spotlight": false,
|
||||
"gradient": false
|
||||
"spotlight": false
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1387,9 +1387,9 @@
|
||||
"barGlow": false,
|
||||
"centerGlow": false,
|
||||
"rounded": false,
|
||||
"spotlight": false,
|
||||
"gradient": true
|
||||
"spotlight": false
|
||||
},
|
||||
"gradient": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1470,9 +1470,9 @@
|
||||
"barGlow": false,
|
||||
"centerGlow": false,
|
||||
"rounded": false,
|
||||
"spotlight": false,
|
||||
"gradient": true
|
||||
"spotlight": false
|
||||
},
|
||||
"gradient": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1553,9 +1553,9 @@
|
||||
"barGlow": false,
|
||||
"centerGlow": false,
|
||||
"rounded": false,
|
||||
"spotlight": false,
|
||||
"gradient": true
|
||||
"spotlight": false
|
||||
},
|
||||
"gradient": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1645,10 +1645,10 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": true,
|
||||
"gradient": true
|
||||
"spotlight": true
|
||||
},
|
||||
"glow": "both",
|
||||
"gradient": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1731,10 +1731,10 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": true,
|
||||
"gradient": true
|
||||
"spotlight": true
|
||||
},
|
||||
"glow": "both",
|
||||
"gradient": "scheme",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1831,10 +1831,10 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": true,
|
||||
"gradient": true
|
||||
"spotlight": true
|
||||
},
|
||||
"glow": "both",
|
||||
"gradient": "scheme",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1919,10 +1919,10 @@
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"sparkline": false,
|
||||
"spotlight": true,
|
||||
"gradient": true
|
||||
"spotlight": true
|
||||
},
|
||||
"glow": "both",
|
||||
"gradient": "scheme",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -2005,10 +2005,10 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": true,
|
||||
"gradient": true
|
||||
"spotlight": true
|
||||
},
|
||||
"glow": "both",
|
||||
"gradient": "hue",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -2091,10 +2091,10 @@
|
||||
"barGlow": true,
|
||||
"centerGlow": true,
|
||||
"rounded": true,
|
||||
"spotlight": true,
|
||||
"gradient": true
|
||||
"spotlight": true
|
||||
},
|
||||
"glow": "both",
|
||||
"gradient": "hue",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -2147,4 +2147,4 @@
|
||||
"title": "Panel tests - Gauge (new)",
|
||||
"uid": "panel-tests-gauge-new",
|
||||
"weekStart": ""
|
||||
}
|
||||
}
|
||||
@@ -956,9 +956,9 @@
|
||||
"barGlow": false,
|
||||
"centerGlow": false,
|
||||
"rounded": false,
|
||||
"spotlight": false,
|
||||
"gradient": false
|
||||
"spotlight": false
|
||||
},
|
||||
"gradient": "none",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1162,4 +1162,4 @@
|
||||
"title": "Panel tests - Old gauge to new",
|
||||
"uid": "panel-tests-old-gauge-to-new",
|
||||
"weekStart": ""
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"refresh": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "query_var",
|
||||
"type": "query",
|
||||
@@ -81,7 +81,6 @@
|
||||
"allValue": ".*",
|
||||
"multi": true,
|
||||
"regex": "/.*9090.*/",
|
||||
"regexApplyTo": "text",
|
||||
"skipUrlSync": false,
|
||||
"refresh": 2,
|
||||
"sort": 1,
|
||||
@@ -108,7 +107,7 @@
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "staging",
|
||||
"text": "staging",
|
||||
"value": "staging"
|
||||
},
|
||||
{
|
||||
@@ -336,7 +335,6 @@
|
||||
"allValue": "*",
|
||||
"multi": true,
|
||||
"regex": "/host[0-9]+/",
|
||||
"regexApplyTo": "value",
|
||||
"skipUrlSync": false,
|
||||
"refresh": 1,
|
||||
"sort": 2,
|
||||
@@ -356,4 +354,4 @@
|
||||
},
|
||||
"links": []
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,10 +237,5 @@
|
||||
"title": "V10 Table Thresholds Test",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -244,10 +244,5 @@
|
||||
"title": "V10 Table Thresholds Test",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -206,10 +206,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -213,10 +213,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -203,10 +203,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -216,10 +216,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -351,10 +351,5 @@
|
||||
"title": "V13 Graph Thresholds Migration Test",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -362,10 +362,5 @@
|
||||
"title": "V13 Graph Thresholds Migration Test",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -129,10 +129,5 @@
|
||||
"title": "Dashboard with minimal graph panel settings",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -132,10 +132,5 @@
|
||||
"title": "Dashboard with minimal graph panel settings",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -210,10 +210,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -217,10 +217,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -1004,10 +1004,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -1023,10 +1023,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -223,10 +223,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -231,10 +231,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -1455,10 +1455,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -1481,10 +1481,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -719,10 +719,5 @@
|
||||
"title": "V16 Grid Layout Migration Test Dashboard",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -739,10 +739,5 @@
|
||||
"title": "V16 Grid Layout Migration Test Dashboard",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -1655,10 +1655,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -1707,10 +1707,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -636,10 +636,5 @@
|
||||
"title": "V17 MinSpan to MaxPerRow Migration Test Dashboard",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -657,10 +657,5 @@
|
||||
"title": "V17 MinSpan to MaxPerRow Migration Test Dashboard",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -401,10 +401,5 @@
|
||||
"title": "V18 Gauge Options Migration Test Dashboard",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -412,10 +412,5 @@
|
||||
"title": "V18 Gauge Options Migration Test Dashboard",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -434,10 +434,5 @@
|
||||
"title": "V19 Panel Links Migration Test Dashboard",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -447,10 +447,5 @@
|
||||
"title": "V19 Panel Links Migration Test Dashboard",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -354,10 +354,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -365,10 +365,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
@@ -426,10 +426,5 @@
|
||||
"title": "V20 Variable Syntax Migration Test Dashboard",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
"status": {}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user