diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 59025d0b7cb..30bba5db0ff 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1305,6 +1305,7 @@ embed.go @grafana/grafana-as-code /.github/actionlint.yaml @grafana/grafana-developer-enablement-squad /.github/workflows/pr-test-docker.yml @grafana/grafana-developer-enablement-squad /.github/workflows/update-schema-types.yml @grafana/plugins-platform-frontend +/.github/workflows/defaults-ini-docs-reminder.yml @grafana/docs-tooling @jtvdez # Generated files not requiring owner approval /packages/grafana-data/src/types/featureToggles.gen.ts @grafanabot diff --git a/.github/workflows/add-to-whats-new.yml b/.github/workflows/add-to-whats-new.yml index a6a8bb8ea2e..c388d2799a4 100644 --- a/.github/workflows/add-to-whats-new.yml +++ b/.github/workflows/add-to-whats-new.yml @@ -1,11 +1,11 @@ -name: Add comment about adding a What's new note +name: Add comment about adding a What's new note for either what's new or breaking changes 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') }} + 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')) }} 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 `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. + 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. diff --git a/.github/workflows/defaults-ini-docs-reminder.yml b/.github/workflows/defaults-ini-docs-reminder.yml new file mode 100644 index 00000000000..98104c914b0 --- /dev/null +++ b/.github/workflows/defaults-ini-docs-reminder.yml @@ -0,0 +1,24 @@ +name: Remind about config documentation updates +on: + pull_request: + types: [opened] + paths: + - 'conf/defaults.ini' + +jobs: + add-comment: + if: ${{ ! github.event.pull_request.head.repo.fork }} + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4 + with: + message: | + Hi there! 👋 This PR modifies `conf/defaults.ini`. + + If this change introduces user-facing configuration options or modifies existing ones, please remember to update [`docs/sources/setup-grafana/configure-grafana/_index.md`](https://github.com/grafana/grafana/blob/main/docs/sources/setup-grafana/configure-grafana/_index.md). + + If this change is internal-only (experimental flags, internal refactoring, etc.), you can ignore this reminder. + + Questions? Reach out to the #docs channel on Slack. diff --git a/.github/workflows/ephemeral-instances-pr-comment.yml b/.github/workflows/ephemeral-instances-pr-comment.yml index d78b5b8f599..c116e43a443 100644 --- a/.github/workflows/ephemeral-instances-pr-comment.yml +++ b/.github/workflows/ephemeral-instances-pr-comment.yml @@ -33,6 +33,16 @@ 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 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 diff --git a/apps/advisor/go.mod b/apps/advisor/go.mod index 53531280f4b..941d8b9bc0f 100644 --- a/apps/advisor/go.mod +++ b/apps/advisor/go.mod @@ -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.4 + github.com/grafana/grafana-app-sdk v0.48.5 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 @@ -149,7 +149,7 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/google/wire v0.7.0 // indirect - github.com/grafana/alerting v0.0.0-20251202151018-58fa500f3232 // indirect + github.com/grafana/alerting v0.0.0-20251204145817-de8c2bbf9eba // indirect github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // indirect github.com/grafana/dataplane/sdata v0.0.9 // indirect github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect @@ -288,6 +288,7 @@ require ( golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.14.0 // indirect golang.org/x/tools v0.39.0 // indirect + golang.org/x/tools/godoc v0.1.0-deprecated // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect gonum.org/v1/gonum v0.16.0 // indirect diff --git a/apps/advisor/go.sum b/apps/advisor/go.sum index add4334f691..4695785bbd1 100644 --- a/apps/advisor/go.sum +++ b/apps/advisor/go.sum @@ -606,8 +606,8 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/grafana/alerting v0.0.0-20251202151018-58fa500f3232 h1:I9l/BxoqxTlPUVx05t8OsqbdP/qwqOeD2E5makeeIz0= -github.com/grafana/alerting v0.0.0-20251202151018-58fa500f3232/go.mod h1:l7v67cgP7x72ajB9UPZlumdrHqNztpKoqQ52cU8T3LU= +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/authlib v0.0.0-20250930082137-a40e2c2b094f h1:Cbm6OKkOcJ+7CSZsGsEJzktC/SIa5bxVeYKQLuYK86o= github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f/go.mod h1:axY0cdOg3q0TZHwpHnIz5x16xZ8ZBxJHShsSHHXcHQg= github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 h1:Muoy+FMGrHj3GdFbvsMzUT7eusgii9PKf9L1ZaXDDbY= @@ -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.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 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/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= diff --git a/apps/advisor/kinds/cue.mod/module.cue b/apps/advisor/kinds/cue.mod/module.cue index eec596c8515..20d5e478697 100644 --- a/apps/advisor/kinds/cue.mod/module.cue +++ b/apps/advisor/kinds/cue.mod/module.cue @@ -1,4 +1,4 @@ module: "github.com/grafana/grafana/apps/advisor/kinds" language: { - version: "v0.9.0" + version: "v0.11.0" } diff --git a/apps/alerting/alertenrichment/go.mod b/apps/alerting/alertenrichment/go.mod index 95466bad6bb..bb020e52bff 100644 --- a/apps/alerting/alertenrichment/go.mod +++ b/apps/alerting/alertenrichment/go.mod @@ -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.4 + github.com/grafana/grafana-app-sdk v0.48.5 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 diff --git a/apps/alerting/alertenrichment/go.sum b/apps/alerting/alertenrichment/go.sum index 5dff965c88b..ef36568611c 100644 --- a/apps/alerting/alertenrichment/go.sum +++ b/apps/alerting/alertenrichment/go.sum @@ -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.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 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/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= diff --git a/apps/alerting/historian/go.mod b/apps/alerting/historian/go.mod index 11e0d0f2406..21ad42c90af 100644 --- a/apps/alerting/historian/go.mod +++ b/apps/alerting/historian/go.mod @@ -3,69 +3,151 @@ module github.com/grafana/grafana/apps/alerting/historian go 1.25.5 require ( - github.com/grafana/grafana-app-sdk v0.48.4 + 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/logging v0.48.3 + github.com/prometheus/client_golang v1.23.2 + github.com/spf13/pflag v1.0.10 + github.com/stretchr/testify v1.11.1 + go.opentelemetry.io/otel v1.38.0 + go.opentelemetry.io/otel/trace v1.38.0 k8s.io/apimachinery v0.34.2 k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 ) require ( + dario.cat/mergo v1.0.2 // indirect + github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect + github.com/Masterminds/sprig/v3 v3.3.0 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/aws/aws-sdk-go v1.55.7 // indirect + github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/evanphx/json-patch v5.9.11+incompatible // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/getkin/kin-openapi v0.133.0 // indirect + github.com/go-logfmt/logfmt v0.6.1 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/errors v0.22.3 // indirect github.com/go-openapi/jsonpointer v0.22.1 // indirect github.com/go-openapi/jsonreference v0.21.2 // indirect + github.com/go-openapi/strfmt v0.24.0 // indirect github.com/go-openapi/swag v0.23.1 // indirect github.com/go-openapi/swag/jsonname v0.25.1 // indirect github.com/go-test/deep v1.1.1 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/gofrs/uuid v4.4.0+incompatible // indirect + github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/gogo/status v1.1.1 // indirect + github.com/golang-jwt/jwt/v5 v5.3.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v1.0.0 // indirect + github.com/google/btree v1.1.3 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grafana/grafana-app-sdk/logging v0.48.3 // indirect + github.com/grafana/loki/pkg/push v0.0.0-20250823105456-332df2b20000 // indirect + github.com/grafana/otel-profiling-go v0.5.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-metrics v0.5.4 // indirect + github.com/hashicorp/go-msgpack/v2 v2.1.2 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-sockaddr v1.0.7 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/hashicorp/memberlist v0.5.2 // indirect + github.com/huandu/xstrings v1.5.0 // indirect + github.com/jaegertracing/jaeger-idl v0.5.0 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect + github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.9.0 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mdlayher/socket v0.4.1 // indirect + github.com/mdlayher/vsock v1.2.1 // indirect + github.com/miekg/dns v1.1.63 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect + github.com/oklog/run v1.1.0 // indirect + github.com/oklog/ulid v1.3.1 // indirect github.com/onsi/ginkgo/v2 v2.22.2 // indirect github.com/onsi/gomega v1.36.2 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/alertmanager v0.28.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.67.3 // indirect + github.com/prometheus/common/sigv4 v0.1.0 // indirect + github.com/prometheus/exporter-toolkit v0.14.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect - github.com/spf13/pflag v1.0.10 // indirect + github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect + github.com/shopspring/decimal v1.4.0 // indirect + github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect + github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect + github.com/uber/jaeger-lib v2.4.1+incompatible // indirect github.com/woodsbury/decimal128 v1.3.0 // indirect github.com/x448/float16 v0.8.4 // indirect + go.mongodb.org/mongo-driver v1.17.4 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/otel v1.38.0 // indirect + go.opentelemetry.io/contrib/bridges/prometheus v0.61.0 // indirect + go.opentelemetry.io/contrib/exporters/autoexport v0.61.0 // indirect + go.opentelemetry.io/contrib/propagators/jaeger v1.38.0 // indirect + go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0 // indirect + go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.59.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.12.2 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.37.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 // indirect + go.opentelemetry.io/otel/log v0.12.2 // indirect go.opentelemetry.io/otel/metric v1.38.0 // indirect go.opentelemetry.io/otel/sdk v1.38.0 // indirect - go.opentelemetry.io/otel/trace v1.38.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.12.2 // indirect + go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect go.opentelemetry.io/proto/otlp v1.9.0 // indirect + go.uber.org/atomic v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/crypto v0.45.0 // indirect + golang.org/x/mod v0.30.0 // indirect golang.org/x/net v0.47.0 // indirect golang.org/x/oauth2 v0.33.0 // indirect golang.org/x/sync v0.18.0 // indirect @@ -73,12 +155,17 @@ require ( golang.org/x/term v0.37.0 // indirect golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.14.0 // indirect + golang.org/x/tools v0.39.0 // indirect + golang.org/x/tools/godoc v0.1.0-deprecated // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba // indirect google.golang.org/grpc v1.77.0 // indirect google.golang.org/protobuf v1.36.10 // indirect + gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/mail.v2 v2.3.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.2 // indirect k8s.io/apiextensions-apiserver v0.34.2 // indirect @@ -90,3 +177,6 @@ require ( sigs.k8s.io/structured-merge-diff/v6 v6.3.1 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) + +// Use our fork of the upstream Alertmanager. +replace github.com/prometheus/alertmanager => github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604 diff --git a/apps/alerting/historian/go.sum b/apps/alerting/historian/go.sum index c447da4e325..b4d2d1dc2e2 100644 --- a/apps/alerting/historian/go.sum +++ b/apps/alerting/historian/go.sum @@ -1,83 +1,326 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= +github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= +github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= +github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE= +github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous= github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ= github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE= +github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/errors v0.22.3 h1:k6Hxa5Jg1TUyZnOwV2Lh81j8ayNw5VVYLvKrp4zFKFs= +github.com/go-openapi/errors v0.22.3/go.mod h1:+WvbaBBULWCOna//9B9TbLNGSFOfF8lY9dw4hGiEiKQ= github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo92JUxBNk= github.com/go-openapi/jsonpointer v0.22.1/go.mod h1:pQT9OsLkfz1yWoMgYFy4x3U5GY5nUlsOn1qSBH5MkCM= github.com/go-openapi/jsonreference v0.21.2 h1:Wxjda4M/BBQllegefXrY/9aq1fxBA8sI5M/lFU6tSWU= github.com/go-openapi/jsonreference v0.21.2/go.mod h1:pp3PEjIsJ9CZDGCNOyXIQxsNuroxm8FAJ/+quA0yKzQ= +github.com/go-openapi/strfmt v0.24.0 h1:dDsopqbI3wrrlIzeXRbqMihRNnjzGC+ez4NQaAAJLuc= +github.com/go-openapi/strfmt v0.24.0/go.mod h1:Lnn1Bk9rZjXxU9VMADbEEOo7D7CDyKGLsSKekhFr7s4= github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= github.com/go-openapi/swag/jsonname v0.25.1 h1:Sgx+qbwa4ej6AomWC6pEfXrA6uP2RkaNjA9BR8a1RJU= github.com/go-openapi/swag/jsonname v0.25.1/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg= +github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +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.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 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/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= +github.com/grafana/loki/pkg/push v0.0.0-20250823105456-332df2b20000/go.mod h1:/ZklAgE1i4f3Z8uriXwESmCr1VLF8lBGaJspuaGuf78= +github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= +github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= +github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604 h1:aXfUhVN/Ewfpbko2CCtL65cIiGgwStOo4lWH2b6gw2U= +github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604/go.mod h1:O/QP1BCm0HHIzbKvgMzqb5sSyH88rzkFk84F4TfJjBU= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-metrics v0.5.4 h1:8mmPiIJkTPPEbAiV97IxdAGNdRdaWwVap1BU6elejKY= +github.com/hashicorp/go-metrics v0.5.4/go.mod h1:CG5yz4NZ/AI/aQt9Ucm/vdBnbh7fvmv4lxZ350i+QQI= +github.com/hashicorp/go-msgpack/v2 v2.1.2 h1:4Ee8FTp834e+ewB71RDrQ0VKpyFdrKOjvYtnQ/ltVj0= +github.com/hashicorp/go-msgpack/v2 v2.1.2/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= +github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +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/memberlist v0.5.2 h1:rJoNPWZ0juJBgqn48gjy59K5H4rNgvUoM1kUD7bXiuI= +github.com/hashicorp/memberlist v0.5.2/go.mod h1:Ri9p/tRShbjYnpNf4FFPXG7wxEGY4Nrcn6E7jrVa//4= +github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= +github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jaegertracing/jaeger-idl v0.5.0 h1:zFXR5NL3Utu7MhPg8ZorxtCBjHrL3ReM1VoB65FOFGE= +github.com/jaegertracing/jaeger-idl v0.5.0/go.mod h1:ON90zFo9eoyXrt9F/KN8YeF3zxcnujaisMweFY/rg5k= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= +github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= +github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ= +github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE= +github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= +github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= @@ -85,137 +328,518 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= +github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.67.3 h1:shd26MlnwTw5jksTDhC7rTQIteBxy+ZZDr3t7F2xN2Q= github.com/prometheus/common v0.67.3/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI= +github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= +github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= +github.com/prometheus/exporter-toolkit v0.14.0 h1:NMlswfibpcZZ+H0sZBiTjrA3/aBFHkNZqE+iCj5EmRg= +github.com/prometheus/exporter-toolkit v0.14.0/go.mod h1:Gu5LnVvt7Nr/oqTBUC23WILZepW0nffNo10XdhQcwWA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU= github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs= +github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M= +github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 h1:OfRzdxCzDhp+rsKWXuOO2I/quKMJ/+TQwVbIP/gltZg= +github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92/go.mod h1:7/OT02F6S6I7v6WXb+IjhMuZEYfH/RJ5RwEWnEo5BMg= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= +github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= +github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0= github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= +go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/bridges/prometheus v0.61.0 h1:RyrtJzu5MAmIcbRrwg75b+w3RlZCP0vJByDVzcpAe3M= +go.opentelemetry.io/contrib/bridges/prometheus v0.61.0/go.mod h1:tirr4p9NXbzjlbruiRGp53IzlYrDk5CO2fdHj0sSSaY= +go.opentelemetry.io/contrib/exporters/autoexport v0.61.0 h1:XfzKtKSrbtYk9TNCF8dkO0Y9M7IOfb4idCwBOTwGBiI= +go.opentelemetry.io/contrib/exporters/autoexport v0.61.0/go.mod h1:N6otC+qXTD5bAnbK2O1f/1SXq3cX+3KYSWrkBUqG0cw= +go.opentelemetry.io/contrib/propagators/jaeger v1.38.0 h1:nXGeLvT1QtCAhkASkP/ksjkTKZALIaQBIW+JSIw1KIc= +go.opentelemetry.io/contrib/propagators/jaeger v1.38.0/go.mod h1:oMvOXk78ZR3KEuPMBgp/ThAMDy9ku/eyUVztr+3G6Wo= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0 h1:oPW/SRFyHgIgxrvNhSBzqvZER2N5kRlci3/rGTOuyWo= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0/go.mod h1:B9Oka5QVD0bnmZNO6gBbBta6nohD/1Z+f9waH2oXyBs= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4= +go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 h1:06ZeJRe5BnYXceSM9Vya83XXVaNGe3H1QqsvqRANQq8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2/go.mod h1:DvPtKE63knkDVP88qpatBj81JxN+w1bqfVbsbCbj1WY= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2 h1:tPLwQlXbJ8NSOfZc4OkgU5h2A38M4c9kfHSVc4PFQGs= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2/go.mod h1:QTnxBwT/1rBIgAG1goq6xMydfYOBKU6KTiYF4fp5zL8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 h1:vl9obrcoWVKp/lwl8tRE33853I8Xru9HFbw/skNeLs8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0/go.mod h1:GAXRxmLJcVM3u22IjTg74zWBrRCKq8BnOqUVLodpcpw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0 h1:Oe2z/BCg5q7k4iXC3cqJxKYg0ieRiOqF0cecFYdPTwk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0/go.mod h1:ZQM5lAJpOsKnYagGg/zV2krVqTtaVdYdDkhMoX6Oalg= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4= +go.opentelemetry.io/otel/exporters/prometheus v0.59.0 h1:HHf+wKS6o5++XZhS98wvILrLVgHxjA/AMjqHKes+uzo= +go.opentelemetry.io/otel/exporters/prometheus v0.59.0/go.mod h1:R8GpRXTZrqvXHDEGVH5bF6+JqAZcK8PjJcZ5nGhEWiE= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.12.2 h1:12vMqzLLNZtXuXbJhSENRg+Vvx+ynNilV8twBLBsXMY= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.12.2/go.mod h1:ZccPZoPOoq8x3Trik/fCsba7DEYDUnN6yX79pgp2BUQ= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.37.0 h1:6VjV6Et+1Hd2iLZEPtdV7vie80Yyqf7oikJLjQ/myi0= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.37.0/go.mod h1:u8hcp8ji5gaM/RfcOo8z9NMnf1pVLfVY7lBY2VOGuUU= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 h1:kJxSDN4SgWWTjG/hPp3O7LCGLcHXFlvS2/FFOrwL+SE= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0/go.mod h1:mgIOzS7iZeKJdeB8/NYHrJ48fdGc71Llo5bJ1J4DWUE= +go.opentelemetry.io/otel/log v0.12.2 h1:yob9JVHn2ZY24byZeaXpTVoPS6l+UrrxmxmPKohXTwc= +go.opentelemetry.io/otel/log v0.12.2/go.mod h1:ShIItIxSYxufUMt+1H5a2wbckGli3/iCfuEbVZi/98E= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/log v0.12.2 h1:yNoETvTByVKi7wHvYS6HMcZrN5hFLD7I++1xIZ/k6W0= +go.opentelemetry.io/otel/sdk/log v0.12.2/go.mod h1:DcpdmUXHJgSqN/dh+XMWa7Vf89u9ap0/AAk/XGLnEzY= +go.opentelemetry.io/otel/sdk/log/logtest v0.0.0-20250521073539-a85ae98dcedc h1:uqxdywfHqqCl6LmZzI3pUnXT1RGFYyUgxj0AkWPFxi0= +go.opentelemetry.io/otel/sdk/log/logtest v0.0.0-20250521073539-a85ae98dcedc/go.mod h1:TY/N/FT7dmFrP/r5ym3g0yysP1DefqGpAZr4f82P0dE= go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= +golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo= golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +golang.org/x/tools/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk= +golang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba h1:B14OtaXuMaCQsl2deSvNkyPKIzq3BjfxQp8d00QyWx4= google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:G5IanEx8/PgI9w6CFcYQf7jMtHQhZruvfM1i3qOqk5U= google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba h1:UKgtfRM7Yh93Sya0Fo8ZzhDP4qBckrrxEr2oF5UIVb8= google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk= +gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY= k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw= k8s.io/apiextensions-apiserver v0.34.2 h1:WStKftnGeoKP4AZRz/BaAAEJvYp4mlZGN0UCv+uvsqo= @@ -230,6 +854,10 @@ k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZ k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= diff --git a/apps/alerting/historian/kinds/cue.mod/module.cue b/apps/alerting/historian/kinds/cue.mod/module.cue index 2f45dd38aec..e3ca09eba43 100644 --- a/apps/alerting/historian/kinds/cue.mod/module.cue +++ b/apps/alerting/historian/kinds/cue.mod/module.cue @@ -1,2 +1,4 @@ module: "github.com/grafana/grafana/apps/alerting/historian/kinds" -language: version: "v0.8.2" +language: { + version: "v0.11.0" +} diff --git a/apps/alerting/historian/pkg/app/app.go b/apps/alerting/historian/pkg/app/app.go index 2996a21a231..5ef3a0412d8 100644 --- a/apps/alerting/historian/pkg/app/app.go +++ b/apps/alerting/historian/pkg/app/app.go @@ -5,22 +5,30 @@ import ( "net/http" "github.com/grafana/grafana-app-sdk/app" + "github.com/grafana/grafana-app-sdk/logging" "github.com/grafana/grafana-app-sdk/simple" + "github.com/prometheus/client_golang/prometheus" + "go.opentelemetry.io/otel" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "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/notification" ) func New(cfg app.Config) (app.App, error) { + reg := prometheus.DefaultRegisterer + tracer := otel.GetTracerProvider().Tracer("historian.alerting.app") + logger := logging.DefaultLogger.With("app", "historian.alerting.app") + runtimeConfig := cfg.SpecificConfig.(config.RuntimeConfig) alertStateHandler := runtimeConfig.GetAlertStateHistoryHandler if alertStateHandler == nil { alertStateHandler = NewErrorHandler("no alert state handler") } - notificationHandler := NewErrorHandler("unimplemented") + notificationHandler := notification.New(runtimeConfig.Notification, reg, logger, tracer) simpleConfig := simple.AppConfig{ Name: "alerting.historian", @@ -36,7 +44,7 @@ func New(cfg app.Config) (app.App, error) { Namespaced: true, Path: "/notification/query", Method: "POST", - }: notificationHandler, + }: notificationHandler.QueryHandler, }, }, // TODO: Remove when SDK is fixed. diff --git a/apps/alerting/historian/pkg/app/config/config.go b/apps/alerting/historian/pkg/app/config/config.go index 5a40503dea8..cb3b3caa711 100644 --- a/apps/alerting/historian/pkg/app/config/config.go +++ b/apps/alerting/historian/pkg/app/config/config.go @@ -1,9 +1,81 @@ package config import ( + "net/http" + "net/url" + "time" + + "github.com/spf13/pflag" + + "github.com/grafana/alerting/notify/historian/lokiclient" "github.com/grafana/grafana-app-sdk/simple" ) +const ( + lokiDefaultMaxQueryLength = 721 * time.Hour // 30d1h, matches the default value in Loki + lokiDefaultMaxQuerySize = 65536 // 64kb +) + +type LokiConfig struct { + lokiclient.LokiConfig + Transport http.RoundTripper +} + +type NotificationConfig struct { + Enabled bool + Loki LokiConfig +} + type RuntimeConfig struct { GetAlertStateHistoryHandler simple.AppCustomRouteHandler + Notification NotificationConfig +} + +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) +} + +func (r *RuntimeConfig) AddFlagsWithPrefix(prefix string, flags *pflag.FlagSet) { + r.Notification.AddFlagsWithPrefix(prefix+".notification", flags) +} + +func (r *RuntimeConfig) AddFlags(flags *pflag.FlagSet) { + r.AddFlagsWithPrefix("alerting.historian", flags) +} + +type urlVar struct { + u **url.URL +} + +// String implements flag.Value +func (v urlVar) String() string { + if v.u == nil || *v.u == nil { + return "" + } + return (*v.u).Redacted() +} + +// Set implements flag.Value +func (v urlVar) Set(s string) error { + u, err := url.Parse(s) + if err != nil { + return err + } + *v.u = u + return nil +} + +// Type implements flag.Value +func (v urlVar) Type() string { + return "url" +} + +func addLokiFlags(l *lokiclient.LokiConfig, prefix string, flags *pflag.FlagSet) { + flags.Var(urlVar{&l.ReadPathURL}, prefix+".read-url", "URL to Loki instance for performing queries") + flags.StringVar(&l.BasicAuthUser, prefix+".user", "", "Basic auth Username to authenticate to the Loki instance") + flags.StringVar(&l.BasicAuthPassword, prefix+".password", "", "Basic auth password to authenticate to the Loki instance") + flags.StringVar(&l.TenantID, prefix+".tenant-id", "", "Value to use for X-Scope-OrgID") + flags.DurationVar(&l.MaxQueryLength, prefix+".max-query-length", lokiDefaultMaxQueryLength, "Maximum allowed time range for queries") + flags.IntVar(&l.MaxQuerySize, prefix+".max-query-size", lokiDefaultMaxQuerySize, "Maximum allowed size of a query string passed to Loki") } diff --git a/apps/alerting/historian/pkg/app/config/config_test.go b/apps/alerting/historian/pkg/app/config/config_test.go new file mode 100644 index 00000000000..7f8ab623a7a --- /dev/null +++ b/apps/alerting/historian/pkg/app/config/config_test.go @@ -0,0 +1,99 @@ +package config + +import ( + "net/url" + "testing" + "time" + + "github.com/grafana/alerting/notify/historian/lokiclient" + "github.com/spf13/pflag" + "github.com/stretchr/testify/require" +) + +func TestRuntimeConfig(t *testing.T) { + lokiURL := mustParseURL("http://localhost:3100") + + tests := []struct { + name string + args []string + expected RuntimeConfig + }{ + { + name: "default config", + args: []string{}, + expected: RuntimeConfig{ + Notification: NotificationConfig{ + Enabled: false, + Loki: LokiConfig{ + LokiConfig: lokiclient.LokiConfig{ + ReadPathURL: nil, + MaxQueryLength: 721 * time.Hour, + MaxQuerySize: 65536, + }, + }, + }, + }, + }, + { + name: "with notification enabled", + args: []string{"--alerting.historian.notification.enabled"}, + expected: RuntimeConfig{ + Notification: NotificationConfig{ + Enabled: true, + Loki: LokiConfig{ + LokiConfig: lokiclient.LokiConfig{ + ReadPathURL: nil, + MaxQueryLength: 721 * time.Hour, + MaxQuerySize: 65536, + }, + }, + }, + }, + }, + { + name: "with loki options", + args: []string{ + "--alerting.historian.notification.loki.read-url=http://localhost:3100", + "--alerting.historian.notification.loki.user=foo", + "--alerting.historian.notification.loki.password=bar", + "--alerting.historian.notification.loki.tenant-id=baz", + }, + 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, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := &RuntimeConfig{} + flags := pflag.NewFlagSet("test", pflag.ContinueOnError) + + cfg.AddFlags(flags) + + err := flags.Parse(tt.args) + require.NoError(t, err) + require.Equal(t, tt.expected, *cfg) + }) + } +} + +func mustParseURL(s string) *url.URL { + u, err := url.Parse(s) + if err != nil { + panic(err) + } + return u +} diff --git a/apps/alerting/historian/pkg/app/logutil/logging.go b/apps/alerting/historian/pkg/app/logutil/logging.go new file mode 100644 index 00000000000..e3315159355 --- /dev/null +++ b/apps/alerting/historian/pkg/app/logutil/logging.go @@ -0,0 +1,62 @@ +package logutil + +import ( + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/grafana/grafana-app-sdk/logging" +) + +func ToGoKitLogger(logger logging.Logger) log.Logger { + return &sdk2gkLogger{logger: logger} +} + +type sdk2gkLogger struct { + logger logging.Logger +} + +func (s *sdk2gkLogger) Log(keyvals ...interface{}) error { + var ( + outMsg = "" + outLevel = interface{}(level.InfoValue()) + outKeyvals = []interface{}{} + ) + + if len(keyvals) == 0 { + s.logger.Info("") + return nil + } + + if len(keyvals)%2 == 1 { + keyvals = append(keyvals, nil) + } + + for i := 0; i < len(keyvals); i += 2 { + k, v := keyvals[i], keyvals[i+1] + + if keyvals[i] == "msg" { + outMsg = v.(string) + continue + } + + if k == level.Key() { + outLevel = v + continue + } + + outKeyvals = append(outKeyvals, k) + outKeyvals = append(outKeyvals, v) + } + + switch outLevel { + case level.DebugValue(): + s.logger.Debug(outMsg, outKeyvals...) + case level.InfoValue(): + s.logger.Info(outMsg, outKeyvals...) + case level.WarnValue(): + s.logger.Warn(outMsg, outKeyvals...) + case level.ErrorValue(): + s.logger.Error(outMsg, outKeyvals...) + } + + return nil +} diff --git a/apps/alerting/historian/pkg/app/logutil/logging_test.go b/apps/alerting/historian/pkg/app/logutil/logging_test.go new file mode 100644 index 00000000000..516f68c7233 --- /dev/null +++ b/apps/alerting/historian/pkg/app/logutil/logging_test.go @@ -0,0 +1,101 @@ +package logutil + +import ( + "context" + "testing" + + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/grafana/grafana-app-sdk/logging" + "github.com/stretchr/testify/require" +) + +type ent struct { + level string + msg string + kvs []any +} +type fakeLogger struct { + logs []ent +} + +func (f *fakeLogger) Debug(msg string, args ...any) { + f.logs = append(f.logs, ent{"debug", msg, args}) +} +func (f *fakeLogger) Info(msg string, args ...any) { + f.logs = append(f.logs, ent{"info", msg, args}) +} +func (f *fakeLogger) Warn(msg string, args ...any) { + f.logs = append(f.logs, ent{"warn", msg, args}) +} +func (f *fakeLogger) Error(msg string, args ...any) { + f.logs = append(f.logs, ent{"error", msg, args}) +} +func (f *fakeLogger) With(args ...any) logging.Logger { + return nil +} +func (f *fakeLogger) WithContext(context.Context) logging.Logger { + return nil +} + +func setup() (*fakeLogger, log.Logger) { + fake := &fakeLogger{} + return fake, ToGoKitLogger(fake) +} + +func TestToGoKitLogger(t *testing.T) { + t.Run("debug / 1 args", func(t *testing.T) { + fake, gk := setup() + require.NoError(t, level.Debug(gk).Log("msg", "hello world", "foo")) + require.Equal(t, "debug", fake.logs[0].level) + require.Equal(t, "hello world", fake.logs[0].msg) + require.Len(t, fake.logs[0].kvs, 2) + require.Equal(t, "foo", fake.logs[0].kvs[0]) + require.Equal(t, "(MISSING)", fake.logs[0].kvs[1].(error).Error()) + }) + t.Run("debug / 2 args", func(t *testing.T) { + fake, gk := setup() + require.NoError(t, level.Debug(gk).Log("msg", "hello world", "foo", "bar")) + require.Equal(t, []ent{{"debug", "hello world", []any{"foo", "bar"}}}, fake.logs) + }) + t.Run("debug / 4 args", func(t *testing.T) { + fake, gk := setup() + require.NoError(t, level.Debug(gk).Log("msg", "hello world", "foo", "bar", "baz", 1)) + require.Equal(t, []ent{{"debug", "hello world", []any{"foo", "bar", "baz", 1}}}, fake.logs) + }) + t.Run("debug / no args", func(t *testing.T) { + fake, gk := setup() + require.NoError(t, level.Debug(gk).Log("msg", "hello world")) + require.Equal(t, []ent{{"debug", "hello world", []any{}}}, fake.logs) + }) + t.Run("info / no args", func(t *testing.T) { + fake, gk := setup() + require.NoError(t, level.Info(gk).Log("msg", "hello world")) + require.Equal(t, []ent{{"info", "hello world", []any{}}}, fake.logs) + }) + t.Run("warn / no args", func(t *testing.T) { + fake, gk := setup() + require.NoError(t, level.Warn(gk).Log("msg", "hello world")) + require.Equal(t, []ent{{"warn", "hello world", []any{}}}, fake.logs) + }) + t.Run("error / no args", func(t *testing.T) { + fake, gk := setup() + require.NoError(t, level.Error(gk).Log("msg", "hello world")) + require.Equal(t, []ent{{"error", "hello world", []any{}}}, fake.logs) + }) + t.Run("no level / no args", func(t *testing.T) { + fake, gk := setup() + require.NoError(t, gk.Log("msg", "hello world")) + require.Equal(t, []ent{{"info", "hello world", []any{}}}, fake.logs) + }) + t.Run("no level / 2 args / no msg", func(t *testing.T) { + fake, gk := setup() + require.NoError(t, gk.Log("foo", "bar")) + require.Equal(t, []ent{{"info", "", []any{"foo", "bar"}}}, fake.logs) + }) + t.Run("no level / no args / no msg", func(t *testing.T) { + fake, gk := setup() + require.NoError(t, gk.Log()) + require.Equal(t, []ent{{"info", "", nil}}, fake.logs) + }) +} diff --git a/apps/alerting/historian/pkg/app/notification/lokireader.go b/apps/alerting/historian/pkg/app/notification/lokireader.go new file mode 100644 index 00000000000..c26519e59b4 --- /dev/null +++ b/apps/alerting/historian/pkg/app/notification/lokireader.go @@ -0,0 +1,238 @@ +package notification + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "regexp" + "sort" + "strings" + "time" + + "github.com/grafana/alerting/notify/historian" + "github.com/grafana/alerting/notify/historian/lokiclient" + "github.com/grafana/dskit/instrument" + "github.com/grafana/grafana-app-sdk/logging" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "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" +) + +const ( + LokiClientSpanName = "grafana.apps.alerting.historian.client" + defaultQueryRange = 6 * time.Hour + defaultLimit = 100 + maxLimit = 1000 + Namespace = "grafana" + Subsystem = "alerting" +) + +var ( + // ErrInvalidQuery is returned if the query is invalid. + ErrInvalidQuery = errors.New("invalid query") + + validLabelKeyRegex = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$") +) + +type lokiClient interface { + RangeQuery(ctx context.Context, logQL string, start, end, limit int64) (lokiclient.QueryRes, error) +} + +type LokiReader struct { + client lokiClient + logger logging.Logger +} + +func NewLokiReader(cfg config.LokiConfig, reg prometheus.Registerer, logger logging.Logger, tracer trace.Tracer) *LokiReader { + duration := instrument.NewHistogramCollector(promauto.With(reg).NewHistogramVec(prometheus.HistogramOpts{ + Namespace: Namespace, + Subsystem: Subsystem, + Name: "notification_history_read_request_duration_seconds", + Help: "Histogram of read request durations to the notification history store.", + 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), + logger: logger, + } +} + +// Query retrieves notification history entries from an external Loki instance. +func (h *LokiReader) Query(ctx context.Context, query Query) (QueryResult, error) { + logql, err := buildQuery(query) + if err != nil { + return QueryResult{}, err + } + + now := time.Now().UTC() + from := now.Add(-defaultQueryRange) + if query.From != nil { + from = *query.From + } + to := now + if query.To != nil { + to = *query.To + } + + limit := int64(defaultLimit) + if query.Limit != nil { + limit = *query.Limit + } + + if limit > maxLimit { + return QueryResult{}, fmt.Errorf("%w: limit (%d) over maximum allowed (%d)", ErrInvalidQuery, limit, maxLimit) + } + + entries, err := h.runQuery(ctx, logql, from, to, limit) + if err != nil { + return QueryResult{}, err + } + + return QueryResult{ + Entries: entries, + }, nil +} + +// buildQuery creates the LogQL to perform the requested query. +func buildQuery(query Query) (string, error) { + selectors := []string{ + fmt.Sprintf(`%s=%q`, historian.LabelFrom, historian.LabelFromValue), + } + + if query.RuleUID != nil { + selectors = append(selectors, + fmt.Sprintf(`%s=%q`, historian.LabelRuleUID, *query.RuleUID)) + } + + logql := fmt.Sprintf(`{%s} | json`, strings.Join(selectors, `,`)) + + // Add receiver filter if specified. + if query.Receiver != nil && *query.Receiver != "" { + logql += fmt.Sprintf(` | receiver = %q`, *query.Receiver) + } + + // Add status filter if specified. + if query.Status != nil && *query.Status != "" { + logql += fmt.Sprintf(` | status = %q`, *query.Status) + } + + // Add group labels filter if specified. + if query.GroupLabels != nil { + for _, matcher := range *query.GroupLabels { + // Validate the matcher close to where it is used to form the query, + // to reduce the risk of introducing a query injection bug. + if !validLabelKeyRegex.MatchString(matcher.Label) { + return "", fmt.Errorf("%w: group label: %q", ErrInvalidQuery, matcher.Label) + } + switch matcher.Type { + case "=", "!=", "=~", "!~": + default: + return "", fmt.Errorf("%w: matcher type: %s", ErrInvalidQuery, matcher.Type) + } + logql += fmt.Sprintf(` | groupLabels_%s %s %q`, matcher.Label, matcher.Type, matcher.Value) + } + } + + // Add outcome filter if specified. + if query.Outcome != nil && *query.Outcome != "" { + switch *query.Outcome { + case v0alpha1.CreateNotificationqueryRequestNotificationOutcomeSuccess: + logql += ` | error = ""` + case v0alpha1.CreateNotificationqueryRequestNotificationOutcomeError: + logql += ` | error != ""` + } + } + + return logql, nil +} + +// runQuery runs the query and collects results. +func (l *LokiReader) runQuery(ctx context.Context, logql string, from, to time.Time, limit int64) ([]Entry, error) { + entries := make([]Entry, 0) + r, err := l.client.RangeQuery(ctx, logql, from.UnixNano(), to.UnixNano(), limit) + if err != nil { + return nil, fmt.Errorf("loki range query: %w", err) + } + + for _, stream := range r.Data.Result { + for _, s := range stream.Values { + entry, err := parseLokiEntry(s) + if err != nil { + l.logger.Warn("Ignoring notification history entry", "err", err) + continue + } + entries = append(entries, entry) + } + } + + // We need to sort as results might be from a combination of streams. + sort.Slice(entries, func(i, j int) bool { + return entries[i].Timestamp.After(entries[j].Timestamp) + }) + + l.logger.Debug("Notification history query complete", "entries", len(entries)) + + return entries, nil +} + +// parseLokiEntry unmarshals the JSON stored in the entry. +func parseLokiEntry(s lokiclient.Sample) (Entry, error) { + var lokiEntry historian.NotificationHistoryLokiEntry + err := json.Unmarshal([]byte(s.V), &lokiEntry) + if err != nil { + return Entry{}, fmt.Errorf("failed to unmarshal entry [%s]: %w", s.T, err) + } + + if lokiEntry.SchemaVersion != 1 { + return Entry{}, fmt.Errorf("unsupported schema version [%s]: %d", s.T, lokiEntry.SchemaVersion) + } + + outcome := OutcomeSuccess + var entryError *string + if lokiEntry.Error != "" { + outcome = OutcomeError + entryError = &lokiEntry.Error + } + + groupLabels := lokiEntry.GroupLabels + if groupLabels == nil { + groupLabels = make(map[string]string) + } + + alerts := make([]EntryAlert, len(lokiEntry.Alerts)) + for i, a := range lokiEntry.Alerts { + alerts[i] = EntryAlert{ + Status: a.Status, + Labels: a.Labels, + Annotations: a.Annotations, + StartsAt: a.StartsAt, + EndsAt: a.EndsAt, + } + } + + return Entry{ + Timestamp: s.T, + Receiver: lokiEntry.Receiver, + Status: Status(lokiEntry.Status), + Outcome: outcome, + GroupKey: lokiEntry.GroupKey, + GroupLabels: groupLabels, + Alerts: alerts, + Retry: lokiEntry.Retry, + Error: entryError, + Duration: lokiEntry.Duration, + PipelineTime: lokiEntry.PipelineTime, + }, nil +} diff --git a/apps/alerting/historian/pkg/app/notification/lokireader_test.go b/apps/alerting/historian/pkg/app/notification/lokireader_test.go new file mode 100644 index 00000000000..708c9d10df1 --- /dev/null +++ b/apps/alerting/historian/pkg/app/notification/lokireader_test.go @@ -0,0 +1,596 @@ +package notification + +import ( + "context" + "encoding/json" + "fmt" + "testing" + "time" + + "github.com/grafana/alerting/notify/historian" + "github.com/grafana/alerting/notify/historian/lokiclient" + "github.com/grafana/grafana-app-sdk/logging" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/grafana/grafana/apps/alerting/historian/pkg/apis/alertinghistorian/v0alpha1" +) + +// mockLokiClient implements the lokiClient interface for testing +type mockLokiClient struct { + mock.Mock +} + +func (m *mockLokiClient) RangeQuery(ctx context.Context, logQL string, start, end, limit int64) (lokiclient.QueryRes, error) { + args := m.Called(ctx, logQL, start, end, limit) + return args.Get(0).(lokiclient.QueryRes), args.Error(1) +} + +func TestLokiReader_Query(t *testing.T) { + now := time.Now().UTC() + testTimestamp := now.Add(-1 * time.Hour) + + tests := []struct { + name string + query Query + lokiResponse lokiclient.QueryRes + responseError error + experr error + validateFn func(t *testing.T, result QueryResult) + }{ + { + name: "successful query with results", + query: Query{ + RuleUID: stringPtr("test-rule-uid"), + }, + lokiResponse: createMockLokiResponse(testTimestamp), + validateFn: func(t *testing.T, result QueryResult) { + assert.Len(t, result.Entries, 1) + assert.Equal(t, "test-receiver", result.Entries[0].Receiver) + assert.Equal(t, Status("firing"), result.Entries[0].Status) + assert.Equal(t, OutcomeSuccess, result.Entries[0].Outcome) + }, + }, + { + name: "query with custom time range", + query: Query{ + RuleUID: stringPtr("test-rule-uid"), + From: timePtr(now.Add(-2 * time.Hour)), + To: timePtr(now), + }, + lokiResponse: createMockLokiResponse(testTimestamp), + }, + { + name: "query with custom limit", + query: Query{ + RuleUID: stringPtr("test-rule-uid"), + Limit: int64Ptr(100), + }, + lokiResponse: createMockLokiResponse(testTimestamp), + }, + { + name: "query with max limit", + query: Query{ + RuleUID: stringPtr("test-rule-uid"), + Limit: int64Ptr(1000), + }, + lokiResponse: createMockLokiResponse(testTimestamp), + }, + { + name: "query with over max limit", + query: Query{ + RuleUID: stringPtr("test-rule-uid"), + Limit: int64Ptr(1001), + }, + lokiResponse: createMockLokiResponse(testTimestamp), + experr: ErrInvalidQuery, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mockClient := &mockLokiClient{} + mockClient.On("RangeQuery", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(tt.lokiResponse, tt.responseError) + + reader := &LokiReader{ + client: mockClient, + logger: &logging.NoOpLogger{}, + } + + result, err := reader.Query(context.Background(), tt.query) + if tt.experr != nil { + assert.ErrorIs(t, err, ErrInvalidQuery) + return + } + + require.NoError(t, err) + if tt.validateFn != nil { + tt.validateFn(t, result) + } + + mockClient.AssertExpectations(t) + }) + } +} + +func TestBuildQuery(t *testing.T) { + tests := []struct { + name string + query Query + expected string + experr error + }{ + { + name: "query with no filters", + query: Query{}, + expected: fmt.Sprintf(`{%s=%q} | json`, + historian.LabelFrom, historian.LabelFromValue), + }, + { + name: "query with rule uid filter", + query: Query{ + RuleUID: stringPtr("test-rule-uid"), + }, + expected: fmt.Sprintf(`{%s=%q,%s=%q} | json`, + historian.LabelFrom, historian.LabelFromValue, + historian.LabelRuleUID, "test-rule-uid"), + }, + { + name: "query with receiver filter", + query: Query{ + RuleUID: stringPtr("test-rule-uid"), + Receiver: stringPtr("email-receiver"), + }, + expected: fmt.Sprintf(`{%s=%q,%s=%q} | json | receiver = "email-receiver"`, + historian.LabelFrom, historian.LabelFromValue, + historian.LabelRuleUID, "test-rule-uid"), + }, + { + name: "query with status filter", + query: Query{ + RuleUID: stringPtr("test-rule-uid"), + Status: createStatusPtr(v0alpha1.CreateNotificationqueryRequestNotificationStatusFiring), + }, + expected: fmt.Sprintf(`{%s=%q,%s=%q} | json | status = "firing"`, + historian.LabelFrom, historian.LabelFromValue, + historian.LabelRuleUID, "test-rule-uid"), + }, + { + name: "query with success outcome filter", + query: Query{ + RuleUID: stringPtr("test-rule-uid"), + Outcome: outcomePtr(v0alpha1.CreateNotificationqueryRequestNotificationOutcomeSuccess), + }, + expected: fmt.Sprintf(`{%s=%q,%s=%q} | json | error = ""`, + historian.LabelFrom, historian.LabelFromValue, + historian.LabelRuleUID, "test-rule-uid"), + }, + { + name: "query with error outcome filter", + query: Query{ + RuleUID: stringPtr("test-rule-uid"), + Outcome: outcomePtr(v0alpha1.CreateNotificationqueryRequestNotificationOutcomeError), + }, + expected: fmt.Sprintf(`{%s=%q,%s=%q} | json | error != ""`, + historian.LabelFrom, historian.LabelFromValue, + historian.LabelRuleUID, "test-rule-uid"), + }, + { + name: "query with many filters", + query: Query{ + RuleUID: stringPtr("test-rule-uid"), + Receiver: stringPtr("email-receiver"), + Status: createStatusPtr(v0alpha1.CreateNotificationqueryRequestNotificationStatusResolved), + Outcome: outcomePtr(v0alpha1.CreateNotificationqueryRequestNotificationOutcomeSuccess), + }, + expected: fmt.Sprintf(`{%s=%q,%s=%q} | json | receiver = "email-receiver" | status = "resolved" | error = ""`, + historian.LabelFrom, historian.LabelFromValue, + historian.LabelRuleUID, "test-rule-uid"), + }, + { + name: "query with group label matcher", + query: Query{ + GroupLabels: &Matchers{{Type: "=", Label: "foo", Value: "bar"}}, + }, + expected: fmt.Sprintf(`{%s=%q} | json | groupLabels_foo = "bar"`, + historian.LabelFrom, historian.LabelFromValue), + }, + { + name: "query with many group label matchers", + query: Query{ + GroupLabels: &Matchers{ + {Type: "=", Label: "f1", Value: "b1"}, + {Type: "!=", Label: "f2", Value: "b2"}, + {Type: "=~", Label: "f3", Value: "b3"}, + {Type: "!~", Label: "f4", Value: "b4"}, + }, + }, + expected: fmt.Sprintf(`{%s=%q} | json | groupLabels_f1 = "b1" | groupLabels_f2 != "b2"`+ + ` | groupLabels_f3 =~ "b3" | groupLabels_f4 !~ "b4"`, + historian.LabelFrom, historian.LabelFromValue), + }, + { + name: "query with invalid group label with space", + query: Query{ + GroupLabels: &Matchers{{Type: "=", Label: "fo o", Value: "bar"}}, + }, + experr: ErrInvalidQuery, + }, + { + name: "query with invalid group label starting with number", + query: Query{ + GroupLabels: &Matchers{{Type: "=", Label: "1foo", Value: "bar"}}, + }, + experr: ErrInvalidQuery, + }, + { + name: "query with invalid group label with attempted injection", + query: Query{ + GroupLabels: &Matchers{{Type: "=", Label: "\" = \"ship\"", Value: "bar"}}, + }, + experr: ErrInvalidQuery, + }, + { + name: "query with invalid group operator", + query: Query{ + GroupLabels: &Matchers{{Type: "|=", Label: "foo", Value: "bar"}}, + }, + experr: ErrInvalidQuery, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := buildQuery(tt.query) + if tt.experr != nil { + require.ErrorIs(t, err, tt.experr) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expected, result) + } + }) + } +} + +func TestParseLokiEntry(t *testing.T) { + now := time.Now().UTC() + timestamp := now + + tests := []struct { + name string + sample lokiclient.Sample + wantErr bool + want Entry + }{ + { + name: "valid entry with success outcome", + sample: lokiclient.Sample{ + T: timestamp, + V: createLokiEntryJSON(t, historian.NotificationHistoryLokiEntry{ + SchemaVersion: 1, + Receiver: "test-receiver", + Status: "firing", + Error: "", + GroupKey: "key:thing", + GroupLabels: map[string]string{ + "alertname": "test-alert", + }, + Alerts: []historian.NotificationHistoryLokiEntryAlert{ + { + Status: "firing", + Labels: map[string]string{ + "severity": "critical", + }, + Annotations: map[string]string{ + "summary": "Test alert", + }, + StartsAt: now, + EndsAt: now.Add(1 * time.Hour), + }, + }, + Retry: false, + Duration: 100, + PipelineTime: now, + }), + }, + wantErr: false, + want: Entry{ + Timestamp: timestamp, + Receiver: "test-receiver", + Status: Status("firing"), + Outcome: OutcomeSuccess, + GroupKey: "key:thing", + GroupLabels: map[string]string{ + "alertname": "test-alert", + }, + Alerts: []EntryAlert{ + { + Status: "firing", + Labels: map[string]string{ + "severity": "critical", + }, + Annotations: map[string]string{ + "summary": "Test alert", + }, + StartsAt: now, + EndsAt: now.Add(1 * time.Hour), + }, + }, + Retry: false, + Error: nil, + Duration: 100, + PipelineTime: now, + }, + }, + { + name: "valid entry with error outcome", + sample: lokiclient.Sample{ + T: timestamp, + V: createLokiEntryJSON(t, historian.NotificationHistoryLokiEntry{ + SchemaVersion: 1, + Receiver: "test-receiver", + Status: "firing", + Error: "notification failed", + GroupKey: "key:thing", + GroupLabels: map[string]string{}, + Alerts: []historian.NotificationHistoryLokiEntryAlert{}, + PipelineTime: now, + }), + }, + wantErr: false, + want: Entry{ + Timestamp: timestamp, + Receiver: "test-receiver", + Status: Status("firing"), + Outcome: OutcomeError, + GroupKey: "key:thing", + GroupLabels: map[string]string{}, + Alerts: []EntryAlert{}, + Error: stringPtr("notification failed"), + PipelineTime: now, + }, + }, + { + name: "entry with nil group labels", + sample: lokiclient.Sample{ + T: timestamp, + V: createLokiEntryJSONWithNilLabels(t, now), + }, + wantErr: false, + want: Entry{ + Timestamp: timestamp, + Receiver: "test-receiver", + Status: Status("firing"), + Outcome: OutcomeSuccess, + GroupLabels: map[string]string{}, + Alerts: []EntryAlert{}, + PipelineTime: now, + }, + }, + { + name: "invalid JSON", + sample: lokiclient.Sample{ + T: timestamp, + V: "invalid json", + }, + wantErr: true, + }, + { + name: "unsupported schema version", + sample: lokiclient.Sample{ + T: timestamp, + V: createLokiEntryJSON(t, historian.NotificationHistoryLokiEntry{ + SchemaVersion: 99, + Receiver: "test-receiver", + PipelineTime: now, + }), + }, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := parseLokiEntry(tt.sample) + if tt.wantErr { + assert.Error(t, err) + return + } + + require.NoError(t, err) + assert.Equal(t, tt.want.Timestamp, got.Timestamp) + assert.Equal(t, tt.want.Receiver, got.Receiver) + assert.Equal(t, tt.want.Status, got.Status) + assert.Equal(t, tt.want.Outcome, got.Outcome) + assert.Equal(t, tt.want.GroupKey, got.GroupKey) + assert.Equal(t, tt.want.GroupLabels, got.GroupLabels) + assert.Equal(t, tt.want.Retry, got.Retry) + assert.Equal(t, tt.want.Duration, got.Duration) + assert.Equal(t, tt.want.PipelineTime, got.PipelineTime) + + if tt.want.Error != nil { + require.NotNil(t, got.Error) + assert.Equal(t, *tt.want.Error, *got.Error) + } else { + assert.Nil(t, got.Error) + } + + assert.Equal(t, len(tt.want.Alerts), len(got.Alerts)) + for i := range tt.want.Alerts { + assert.Equal(t, tt.want.Alerts[i].Status, got.Alerts[i].Status) + assert.Equal(t, tt.want.Alerts[i].Labels, got.Alerts[i].Labels) + assert.Equal(t, tt.want.Alerts[i].Annotations, got.Alerts[i].Annotations) + assert.Equal(t, tt.want.Alerts[i].StartsAt, got.Alerts[i].StartsAt) + assert.Equal(t, tt.want.Alerts[i].EndsAt, got.Alerts[i].EndsAt) + } + }) + } +} + +func TestLokiReader_RunQuery(t *testing.T) { + now := time.Now().UTC() + + entry1Time := now.Add(-3 * time.Hour) + entry2Time := now.Add(-2 * time.Hour) + entry3Time := now.Add(-1 * time.Hour) + + mockResponse := lokiclient.QueryRes{ + Data: lokiclient.QueryData{ + Result: []lokiclient.Stream{ + { + Values: []lokiclient.Sample{ + { + T: entry1Time, + V: createLokiEntryJSON(t, historian.NotificationHistoryLokiEntry{ + SchemaVersion: 1, + Receiver: "receiver-1", + Status: "firing", + GroupLabels: map[string]string{}, + Alerts: []historian.NotificationHistoryLokiEntryAlert{}, + PipelineTime: now, + }), + }, + { + T: entry3Time, + V: createLokiEntryJSON(t, historian.NotificationHistoryLokiEntry{ + SchemaVersion: 1, + Receiver: "receiver-3", + Status: "firing", + GroupLabels: map[string]string{}, + Alerts: []historian.NotificationHistoryLokiEntryAlert{}, + PipelineTime: now, + }), + }, + }, + }, + { + Values: []lokiclient.Sample{ + { + T: entry2Time, + V: createLokiEntryJSON(t, historian.NotificationHistoryLokiEntry{ + SchemaVersion: 1, + Receiver: "receiver-2", + Status: "firing", + GroupLabels: map[string]string{}, + Alerts: []historian.NotificationHistoryLokiEntryAlert{}, + PipelineTime: now, + }), + }, + }, + }, + }, + }, + } + + mockClient := &mockLokiClient{} + mockClient.On("RangeQuery", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(mockResponse, nil) + + reader := &LokiReader{ + client: mockClient, + logger: &logging.NoOpLogger{}, + } + + entries, err := reader.runQuery(context.Background(), "test query", now.Add(-6*time.Hour), now, 1000) + require.NoError(t, err) + require.Len(t, entries, 3) + + mockClient.AssertExpectations(t) + + assert.Equal(t, "receiver-3", entries[0].Receiver) + assert.Equal(t, "receiver-2", entries[1].Receiver) + assert.Equal(t, "receiver-1", entries[2].Receiver) + assert.Equal(t, entries[0].Timestamp, entry3Time) + assert.Equal(t, entries[1].Timestamp, entry2Time) + assert.Equal(t, entries[2].Timestamp, entry1Time) +} + +// Helper functions + +func stringPtr(s string) *string { + return &s +} + +func int64Ptr(i int64) *int64 { + return &i +} + +func timePtr(t time.Time) *time.Time { + return &t +} + +func createStatusPtr(s v0alpha1.CreateNotificationqueryRequestNotificationStatus) *v0alpha1.CreateNotificationqueryRequestNotificationStatus { + return &s +} + +func outcomePtr(o v0alpha1.CreateNotificationqueryRequestNotificationOutcome) *v0alpha1.CreateNotificationqueryRequestNotificationOutcome { + return &o +} + +func createMockLokiResponse(timestamp time.Time) lokiclient.QueryRes { + return lokiclient.QueryRes{ + Data: lokiclient.QueryData{ + Result: []lokiclient.Stream{ + { + Values: []lokiclient.Sample{ + { + T: timestamp, + V: createLokiEntryJSON(nil, historian.NotificationHistoryLokiEntry{ + SchemaVersion: 1, + Receiver: "test-receiver", + Status: "firing", + Error: "", + GroupKey: "key:thing", + GroupLabels: map[string]string{ + "alertname": "test-alert", + }, + Alerts: []historian.NotificationHistoryLokiEntryAlert{ + { + Status: "firing", + Labels: map[string]string{ + "severity": "critical", + }, + Annotations: map[string]string{ + "summary": "Test alert", + }, + StartsAt: timestamp, + EndsAt: timestamp.Add(1 * time.Hour), + }, + }, + Retry: false, + Duration: 100, + PipelineTime: timestamp, + }), + }, + }, + }, + }, + }, + } +} + +func createLokiEntryJSON(t *testing.T, entry historian.NotificationHistoryLokiEntry) string { + data, err := json.Marshal(entry) + if t != nil && err != nil { + t.Fatalf("failed to marshal entry: %v", err) + } + return string(data) +} + +func createLokiEntryJSONWithNilLabels(t *testing.T, timestamp time.Time) string { + // Create JSON with explicit null for group_labels + jsonStr := fmt.Sprintf(`{ + "schemaVersion": 1, + "receiver": "test-receiver", + "status": "firing", + "error": "", + "groupLabels": null, + "alerts": [], + "retry": false, + "duration": 0, + "pipelineTime": "%s" + }`, timestamp.Format(time.RFC3339Nano)) + return jsonStr +} diff --git a/apps/alerting/historian/pkg/app/notification/notification.go b/apps/alerting/historian/pkg/app/notification/notification.go new file mode 100644 index 00000000000..2a28e258de2 --- /dev/null +++ b/apps/alerting/historian/pkg/app/notification/notification.go @@ -0,0 +1,77 @@ +package notification + +import ( + "context" + "encoding/json" + "errors" + "net/http" + + "github.com/grafana/grafana-app-sdk/app" + "github.com/grafana/grafana-app-sdk/logging" + "github.com/prometheus/client_golang/prometheus" + "go.opentelemetry.io/otel/trace" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/grafana/grafana/apps/alerting/historian/pkg/apis/alertinghistorian/v0alpha1" + "github.com/grafana/grafana/apps/alerting/historian/pkg/app/config" +) + +type Notification struct { + loki *LokiReader + logger logging.Logger +} + +func New(cfg config.NotificationConfig, reg prometheus.Registerer, logger logging.Logger, tracer trace.Tracer) *Notification { + if !cfg.Enabled { + return &Notification{} + } + return &Notification{ + loki: NewLokiReader(cfg.Loki, reg, logger, tracer), + logger: logger, + } +} + +func (n *Notification) QueryHandler(ctx context.Context, writer app.CustomRouteResponseWriter, request *app.CustomRouteRequest) error { + if n.loki == nil { + return &apierrors.StatusError{ + ErrStatus: metav1.Status{ + Status: metav1.StatusFailure, + Code: http.StatusUnprocessableEntity, + Message: "notification history disabled", + }} + } + + var body v0alpha1.CreateNotificationqueryRequestBody + err := json.NewDecoder(request.Body).Decode(&body) + if err != nil { + return &apierrors.StatusError{ + ErrStatus: metav1.Status{ + Status: metav1.StatusFailure, + Code: http.StatusBadRequest, + Message: err.Error(), + }} + } + + response, err := n.loki.Query(ctx, body) + if err != nil { + if errors.Is(err, ErrInvalidQuery) { + return &apierrors.StatusError{ + ErrStatus: metav1.Status{ + Status: metav1.StatusFailure, + Code: http.StatusBadRequest, + Message: err.Error(), + }} + } + return &apierrors.StatusError{ + ErrStatus: metav1.Status{ + Status: metav1.StatusFailure, + Code: http.StatusInternalServerError, + Message: err.Error(), + }} + } + + writer.Header().Add("Content-Type", "application/json") + writer.WriteHeader(http.StatusOK) + return json.NewEncoder(writer).Encode(response) +} diff --git a/apps/alerting/historian/pkg/app/notification/types.go b/apps/alerting/historian/pkg/app/notification/types.go new file mode 100644 index 00000000000..4a784a5ac25 --- /dev/null +++ b/apps/alerting/historian/pkg/app/notification/types.go @@ -0,0 +1,28 @@ +package notification + +import ( + "github.com/grafana/grafana/apps/alerting/historian/pkg/apis/alertinghistorian/v0alpha1" +) + +// Aliases to shorten names. +// In the future, we may have to make these distinct types from the API, +// to handle differences in API versions, but that's not necessary for now. + +type Query = v0alpha1.CreateNotificationqueryRequestBody + +type Matchers = v0alpha1.CreateNotificationqueryRequestMatchers + +type QueryResult = v0alpha1.CreateNotificationquery + +type Status = v0alpha1.NotificationStatus + +type Outcome = v0alpha1.NotificationOutcome + +const ( + OutcomeSuccess = v0alpha1.NotificationOutcomeSuccess + OutcomeError = v0alpha1.NotificationOutcomeError +) + +type Entry = v0alpha1.NotificationEntry + +type EntryAlert = v0alpha1.NotificationEntryAlert diff --git a/apps/alerting/notifications/go.mod b/apps/alerting/notifications/go.mod index 80dd39f9ca7..f72c4c9775b 100644 --- a/apps/alerting/notifications/go.mod +++ b/apps/alerting/notifications/go.mod @@ -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.4 + github.com/grafana/grafana-app-sdk v0.48.5 github.com/grafana/grafana-app-sdk/logging v0.48.3 k8s.io/apimachinery v0.34.2 k8s.io/apiserver v0.34.2 diff --git a/apps/alerting/notifications/go.sum b/apps/alerting/notifications/go.sum index 6ab34248ef8..57b099ab2f1 100644 --- a/apps/alerting/notifications/go.sum +++ b/apps/alerting/notifications/go.sum @@ -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.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 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/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= diff --git a/apps/alerting/notifications/kinds/cue.mod/module.cue b/apps/alerting/notifications/kinds/cue.mod/module.cue index f8a02e23e2f..d5af2d37220 100644 --- a/apps/alerting/notifications/kinds/cue.mod/module.cue +++ b/apps/alerting/notifications/kinds/cue.mod/module.cue @@ -1,4 +1,4 @@ module: "github.com/grafana/grafana/apps/alerting/notifications/kinds" language: { - version: "v0.9.0" + version: "v0.11.0" } diff --git a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/receiver_object_gen.go b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/receiver_object_gen.go index 00bb1a34745..de0a0d5320f 100644 --- a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/receiver_object_gen.go +++ b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/receiver_object_gen.go @@ -23,6 +23,12 @@ type Receiver struct { Spec ReceiverSpec `json:"spec" yaml:"spec"` } +func NewReceiver() *Receiver { + return &Receiver{ + Spec: *NewReceiverSpec(), + } +} + func (o *Receiver) GetSpec() any { return o.Spec } diff --git a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/receiver_schema_gen.go b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/receiver_schema_gen.go index ea4e3b8e363..27047b00601 100644 --- a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/receiver_schema_gen.go +++ b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/receiver_schema_gen.go @@ -12,7 +12,7 @@ import ( // schema is unexported to prevent accidental overwrites var ( - schemaReceiver = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &Receiver{}, &ReceiverList{}, resource.WithKind("Receiver"), + schemaReceiver = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", NewReceiver(), &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) { diff --git a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/routingtree_object_gen.go b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/routingtree_object_gen.go index e59f0dada5c..354e009d77f 100644 --- a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/routingtree_object_gen.go +++ b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/routingtree_object_gen.go @@ -23,6 +23,12 @@ type RoutingTree struct { Spec RoutingTreeSpec `json:"spec" yaml:"spec"` } +func NewRoutingTree() *RoutingTree { + return &RoutingTree{ + Spec: *NewRoutingTreeSpec(), + } +} + func (o *RoutingTree) GetSpec() any { return o.Spec } diff --git a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/routingtree_schema_gen.go b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/routingtree_schema_gen.go index 6838c9cdebd..2a1812a2846 100644 --- a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/routingtree_schema_gen.go +++ b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/routingtree_schema_gen.go @@ -10,7 +10,7 @@ import ( // schema is unexported to prevent accidental overwrites var ( - schemaRoutingTree = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &RoutingTree{}, &RoutingTreeList{}, resource.WithKind("RoutingTree"), + schemaRoutingTree = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", NewRoutingTree(), &RoutingTreeList{}, resource.WithKind("RoutingTree"), resource.WithPlural("routingtrees"), resource.WithScope(resource.NamespacedScope)) kindRoutingTree = resource.Kind{ Schema: schemaRoutingTree, diff --git a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/templategroup_object_gen.go b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/templategroup_object_gen.go index 0866bcb258c..d755a887a3f 100644 --- a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/templategroup_object_gen.go +++ b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/templategroup_object_gen.go @@ -23,6 +23,12 @@ type TemplateGroup struct { Spec TemplateGroupSpec `json:"spec" yaml:"spec"` } +func NewTemplateGroup() *TemplateGroup { + return &TemplateGroup{ + Spec: *NewTemplateGroupSpec(), + } +} + func (o *TemplateGroup) GetSpec() any { return o.Spec } diff --git a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/templategroup_schema_gen.go b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/templategroup_schema_gen.go index 0be8cb1c6de..ba92e2c4c4c 100644 --- a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/templategroup_schema_gen.go +++ b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/templategroup_schema_gen.go @@ -10,7 +10,7 @@ import ( // schema is unexported to prevent accidental overwrites var ( - schemaTemplateGroup = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TemplateGroup{}, &TemplateGroupList{}, resource.WithKind("TemplateGroup"), + schemaTemplateGroup = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", NewTemplateGroup(), &TemplateGroupList{}, resource.WithKind("TemplateGroup"), resource.WithPlural("templategroups"), resource.WithScope(resource.NamespacedScope)) kindTemplateGroup = resource.Kind{ Schema: schemaTemplateGroup, diff --git a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/timeinterval_object_gen.go b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/timeinterval_object_gen.go index 0ef813ee40c..e87b49dc958 100644 --- a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/timeinterval_object_gen.go +++ b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/timeinterval_object_gen.go @@ -23,6 +23,12 @@ type TimeInterval struct { Spec TimeIntervalSpec `json:"spec" yaml:"spec"` } +func NewTimeInterval() *TimeInterval { + return &TimeInterval{ + Spec: *NewTimeIntervalSpec(), + } +} + func (o *TimeInterval) GetSpec() any { return o.Spec } diff --git a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/timeinterval_schema_gen.go b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/timeinterval_schema_gen.go index 715bfbc0fe7..d342cb90637 100644 --- a/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/timeinterval_schema_gen.go +++ b/apps/alerting/notifications/pkg/apis/alertingnotifications/v0alpha1/timeinterval_schema_gen.go @@ -10,7 +10,7 @@ import ( // schema is unexported to prevent accidental overwrites var ( - schemaTimeInterval = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TimeInterval{}, &TimeIntervalList{}, resource.WithKind("TimeInterval"), + schemaTimeInterval = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", NewTimeInterval(), &TimeIntervalList{}, resource.WithKind("TimeInterval"), resource.WithPlural("timeintervals"), resource.WithScope(resource.NamespacedScope)) kindTimeInterval = resource.Kind{ Schema: schemaTimeInterval, diff --git a/apps/alerting/rules/go.mod b/apps/alerting/rules/go.mod index 7286ccf5376..63da00536a6 100644 --- a/apps/alerting/rules/go.mod +++ b/apps/alerting/rules/go.mod @@ -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.4 + github.com/grafana/grafana-app-sdk v0.48.5 github.com/grafana/grafana-app-sdk/logging v0.48.3 github.com/prometheus/common v0.67.3 k8s.io/apimachinery v0.34.2 diff --git a/apps/alerting/rules/go.sum b/apps/alerting/rules/go.sum index c447da4e325..3df8e8b5ebe 100644 --- a/apps/alerting/rules/go.sum +++ b/apps/alerting/rules/go.sum @@ -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.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 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/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= diff --git a/apps/annotation/go.mod b/apps/annotation/go.mod index a042d852413..946c42fe38f 100644 --- a/apps/annotation/go.mod +++ b/apps/annotation/go.mod @@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/annotation go 1.25.5 require ( - github.com/grafana/grafana-app-sdk v0.48.4 + github.com/grafana/grafana-app-sdk v0.48.5 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 diff --git a/apps/annotation/go.sum b/apps/annotation/go.sum index c447da4e325..3df8e8b5ebe 100644 --- a/apps/annotation/go.sum +++ b/apps/annotation/go.sum @@ -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.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 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/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= diff --git a/apps/annotation/kinds/cue.mod/module.cue b/apps/annotation/kinds/cue.mod/module.cue index a7f0a62536f..3e191cc59b7 100644 --- a/apps/annotation/kinds/cue.mod/module.cue +++ b/apps/annotation/kinds/cue.mod/module.cue @@ -1,2 +1,4 @@ module: "github.com/grafana/grafana/apps/annotation/kinds" -language: version: "v0.8.2" +language: { + version: "v0.11.0" +} diff --git a/apps/collections/go.mod b/apps/collections/go.mod index 81872ad4505..00575d7e6d4 100644 --- a/apps/collections/go.mod +++ b/apps/collections/go.mod @@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/collections go 1.25.5 require ( - github.com/grafana/grafana-app-sdk v0.48.4 + github.com/grafana/grafana-app-sdk v0.48.5 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2 github.com/stretchr/testify v1.11.1 k8s.io/apimachinery v0.34.2 diff --git a/apps/collections/go.sum b/apps/collections/go.sum index 22bf6a8cbcd..75a19848d73 100644 --- a/apps/collections/go.sum +++ b/apps/collections/go.sum @@ -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.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 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/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= diff --git a/apps/collections/kinds/cue.mod/module.cue b/apps/collections/kinds/cue.mod/module.cue index 6280fd8f227..9675fc32a51 100644 --- a/apps/collections/kinds/cue.mod/module.cue +++ b/apps/collections/kinds/cue.mod/module.cue @@ -1,4 +1,4 @@ module: "github.com/grafana/grafana/apps/preferences/kinds" language: { - version: "v0.9.0" + version: "v0.11.0" } diff --git a/apps/correlations/go.mod b/apps/correlations/go.mod index e1c9242aa14..29bc91e70a6 100644 --- a/apps/correlations/go.mod +++ b/apps/correlations/go.mod @@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/correlations go 1.25.5 require ( - github.com/grafana/grafana-app-sdk v0.48.4 + github.com/grafana/grafana-app-sdk v0.48.5 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 diff --git a/apps/correlations/go.sum b/apps/correlations/go.sum index c447da4e325..3df8e8b5ebe 100644 --- a/apps/correlations/go.sum +++ b/apps/correlations/go.sum @@ -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.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 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/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= diff --git a/apps/correlations/kinds/cue.mod/module.cue b/apps/correlations/kinds/cue.mod/module.cue index 2238cffd9a5..ba35847baeb 100644 --- a/apps/correlations/kinds/cue.mod/module.cue +++ b/apps/correlations/kinds/cue.mod/module.cue @@ -1,2 +1,4 @@ module: "github.com/grafana/grafana/apps/correlations/kinds" -language: version: "v0.8.2" +language: { + version: "v0.11.0" +} diff --git a/apps/dashboard/Makefile b/apps/dashboard/Makefile index fa75513d964..7ff9b946dc9 100644 --- a/apps/dashboard/Makefile +++ b/apps/dashboard/Makefile @@ -11,9 +11,7 @@ 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 \ - --noschemasinmanifest \ - --useoldmanifestkinds + --genoperatorstate=false .PHONY: post-generate-cleanup post-generate-cleanup: ## Clean up the generated code diff --git a/apps/dashboard/go.mod b/apps/dashboard/go.mod index 4baf37a3657..0a19120fe80 100644 --- a/apps/dashboard/go.mod +++ b/apps/dashboard/go.mod @@ -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.4 + github.com/grafana/grafana-app-sdk v0.48.5 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 diff --git a/apps/dashboard/go.sum b/apps/dashboard/go.sum index 9c8cde10af6..0faeaaf78ba 100644 --- a/apps/dashboard/go.sum +++ b/apps/dashboard/go.sum @@ -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.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 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/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= diff --git a/apps/dashboard/kinds/cue.mod/module.cue b/apps/dashboard/kinds/cue.mod/module.cue index a3b88f8aa81..f8c354c37fb 100644 --- a/apps/dashboard/kinds/cue.mod/module.cue +++ b/apps/dashboard/kinds/cue.mod/module.cue @@ -1,4 +1,4 @@ module: "github.com/grafana/grafana/sdkkinds/dashboard" language: { - version: "v0.9.0" + version: "v0.11.0" } diff --git a/apps/dashboard/kinds/dashboard.cue b/apps/dashboard/kinds/dashboard.cue index e8dfea3bf98..5d04cf1e331 100644 --- a/apps/dashboard/kinds/dashboard.cue +++ b/apps/dashboard/kinds/dashboard.cue @@ -1,12 +1,5 @@ package kinds -import ( - v0 "github.com/grafana/grafana/sdkkinds/dashboard/v0alpha1" - v1 "github.com/grafana/grafana/sdkkinds/dashboard/v1beta1" - v2alpha1 "github.com/grafana/grafana/sdkkinds/dashboard/v2alpha1" - v2beta1 "github.com/grafana/grafana/sdkkinds/dashboard/v2beta1" -) - // Status is the shared status of all dashboard versions. DashboardStatus: { // Optional conversion status. @@ -31,50 +24,3 @@ ConversionStatus: { // The original value map[string]any source?: _ } - -dashboard: { - kind: "Dashboard" - pluralName: "Dashboards" - current: "v1beta1" - codegen: { - ts: { - enabled: true - config: { - enumsAsUnionTypes: true - } - } - go: { - enabled: true - config: { - allowMarshalEmptyDisjunctions: true - } - } - } - - versions: { - "v0alpha1": { - schema: { - spec: v0.DashboardSpec - status: DashboardStatus - } - } - "v1beta1": { - schema: { - spec: v1.DashboardSpec - status: DashboardStatus - } - } - "v2alpha1": { - schema: { - spec: v2alpha1.DashboardSpec - status: DashboardStatus - } - } - "v2beta1": { - schema: { - spec: v2beta1.DashboardSpec - status: DashboardStatus - } - } - } -} diff --git a/apps/dashboard/kinds/manifest.cue b/apps/dashboard/kinds/manifest.cue index f1044a39e24..9fb17910664 100644 --- a/apps/dashboard/kinds/manifest.cue +++ b/apps/dashboard/kinds/manifest.cue @@ -1,10 +1,82 @@ package kinds +import ( + v0 "github.com/grafana/grafana/sdkkinds/dashboard/v0alpha1" + v1 "github.com/grafana/grafana/sdkkinds/dashboard/v1beta1" + v2alpha1 "github.com/grafana/grafana/sdkkinds/dashboard/v2alpha1" + v2beta1 "github.com/grafana/grafana/sdkkinds/dashboard/v2beta1" +) + manifest: { - appName: "dashboard" - groupOverride: "dashboard.grafana.app" - kinds: [ - dashboard, - snapshot, - ] + appName: "dashboard" + groupOverride: "dashboard.grafana.app" + preferredVersion: "v1beta1" + + versions: { + "v0alpha1": { + codegen: { + ts: {enabled: false} + go: {enabled: true} + } + kinds: [ + { + kind: "Dashboard" + pluralName: "Dashboards" + schema: { + spec: v0.DashboardSpec + status: DashboardStatus + } + }, + snapshotV0alpha1, // Only exists in v0alpha (for now) + ] + } + "v1beta1": { + codegen: { + ts: {enabled: false} + go: {enabled: true} + } + kinds: [ + { + kind: "Dashboard" + pluralName: "Dashboards" + schema: { + spec: v1.DashboardSpec + status: DashboardStatus + } + } + ] + } + "v2alpha1": { + codegen: { + ts: {enabled: false} + go: {enabled: true} + } + kinds: [ + { + kind: "Dashboard" + pluralName: "Dashboards" + schema: { + spec: v2alpha1.DashboardSpec + status: DashboardStatus + } + } + ] + } + "v2beta1": { + codegen: { + ts: {enabled: false} + go: {enabled: true} + } + kinds: [ + { + kind: "Dashboard" + pluralName: "Dashboards" + schema: { + spec: v2beta1.DashboardSpec + status: DashboardStatus + } + } + ] + } + } } diff --git a/apps/dashboard/kinds/snapshot.cue b/apps/dashboard/kinds/snapshot.cue index c224daf8492..00f445881b5 100644 --- a/apps/dashboard/kinds/snapshot.cue +++ b/apps/dashboard/kinds/snapshot.cue @@ -1,46 +1,30 @@ package kinds -snapshot: { +snapshotV0alpha1: { kind: "Snapshot" pluralName: "Snapshots" - scope: "Namespaced" - current: "v0alpha1" - - codegen: { - ts: { - enabled: true - } - go: { - enabled: true - } - } - - versions: { - "v0alpha1": { - schema: { - spec: { - // Snapshot title - title?: string - - // Optionally auto-remove the snapshot at a future date (Unix timestamp in seconds) - expires?: int64 | *0 - - // When set to true, the snapshot exists in a remote server - external?: bool | *false - - // The external URL where the snapshot can be seen - externalUrl?: string - - // The URL that created the dashboard originally - originalUrl?: string - - // Snapshot creation timestamp - timestamp?: string + schema: { + spec: { + // Snapshot title + title?: string + + // Optionally auto-remove the snapshot at a future date (Unix timestamp in seconds) + expires?: int64 | *0 + + // When set to true, the snapshot exists in a remote server + external?: bool | *false + + // The external URL where the snapshot can be seen + externalUrl?: string + + // The URL that created the dashboard originally + originalUrl?: string + + // Snapshot creation timestamp + timestamp?: string - // The raw dashboard (unstructured for now) - dashboard?: [string]: _ - } - } + // The raw dashboard (unstructured for now) + dashboard?: [string]: _ } } -} +} \ No newline at end of file diff --git a/apps/dashboard/pkg/apis/dashboard/cuevalidator/validator.go b/apps/dashboard/pkg/apis/dashboard/cuevalidator/validator.go index 38792ade026..2a3c075eb56 100644 --- a/apps/dashboard/pkg/apis/dashboard/cuevalidator/validator.go +++ b/apps/dashboard/pkg/apis/dashboard/cuevalidator/validator.go @@ -4,26 +4,65 @@ import ( "sync" "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" cuejson "cuelang.org/go/encoding/json" ) -// Validator provides thread-safe CUE schema validation. +const ( + // maxValidations limits how many validations can use the same context before it's recreated. + // This prevents unbounded memory growth while still allowing schema reuse for performance. + // After this many validations, the context is discarded and a new one is created. + maxValidations = 100 +) + +// Validator provides thread-safe CUE schema validation with periodic context recreation. // // CUE is not safe for concurrent use: https://github.com/cue-lang/cue/discussions/1205#discussioncomment-1189238 // This validator uses a mutex to protect concurrent access to the underlying CUE validation. +// +// To prevent memory leaks from CUE's internal caching, we reuse a context for up to maxValidations +// validations, then recreate it. This balances performance (schema reuse) with memory safety +// (periodic garbage collection of cached values). +// +// See https://github.com/grafana/grafana/issues/114344#issuecomment-3605562491 for details +// about the memory leak issue and this fix. type Validator struct { - schema cue.Value - mu sync.Mutex + schemaSource string + schemaPath cue.Path + mu sync.Mutex + ctx *cue.Context + compiledSchema cue.Value + validationCount int } -func NewValidator(schema cue.Value) *Validator { +// NewValidatorFromSource creates a new validator from a schema source string and path. +// This prevents memory leaks by periodically recreating the CUE context after maxValidations uses. +func NewValidatorFromSource(schemaSource string, schemaPath cue.Path) *Validator { + cueCtx := cuecontext.New() + compiledSchema := cueCtx.CompileString(schemaSource).LookupPath(schemaPath) return &Validator{ - schema: schema, + schemaSource: schemaSource, + schemaPath: schemaPath, + ctx: cueCtx, + compiledSchema: compiledSchema, } } func (v *Validator) Validate(data []byte) error { v.mu.Lock() defer v.mu.Unlock() - return cuejson.Validate(data, v.schema) + + // Increment validation count + v.validationCount++ + + // If we've reached the maximum number of validations, recreate the context + if v.validationCount >= maxValidations { + // Recreate context to allow GC to reclaim cached values + v.ctx = cuecontext.New() + v.compiledSchema = v.ctx.CompileString(v.schemaSource).LookupPath(v.schemaPath) + v.validationCount = 0 + } + + // Validate using the current compiled schema + return cuejson.Validate(data, v.compiledSchema) } diff --git a/apps/dashboard/pkg/apis/dashboard/utils.go b/apps/dashboard/pkg/apis/dashboard/utils.go index a5979151a90..f1453d548a0 100644 --- a/apps/dashboard/pkg/apis/dashboard/utils.go +++ b/apps/dashboard/pkg/apis/dashboard/utils.go @@ -6,6 +6,8 @@ import ( "github.com/grafana/grafana/pkg/apimachinery/utils" ) +const GrafanaDatasourceUID = "grafana" + // SetPluginIDMeta sets the repo name to "plugin" and the path to the plugin ID func SetPluginIDMeta(obj *unstructured.Unstructured, pluginID string) { if pluginID == "" { diff --git a/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_object_gen.go b/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_object_gen.go index a267e0c8df8..ac8a0a61685 100644 --- a/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_object_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_object_gen.go @@ -25,6 +25,13 @@ 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 } diff --git a/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_schema_gen.go b/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_schema_gen.go index 5b2da44ec05..1ec0884202f 100644 --- a/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_schema_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_schema_gen.go @@ -10,7 +10,7 @@ import ( // schema is unexported to prevent accidental overwrites var ( - schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v0alpha1", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"), + schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v0alpha1", NewDashboard(), &DashboardList{}, resource.WithKind("Dashboard"), resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope)) kindDashboard = resource.Kind{ Schema: schemaDashboard, diff --git a/apps/dashboard/pkg/apis/dashboard/v0alpha1/snapshot_object_gen.go b/apps/dashboard/pkg/apis/dashboard/v0alpha1/snapshot_object_gen.go index d917cebc0bf..64924eac264 100644 --- a/apps/dashboard/pkg/apis/dashboard/v0alpha1/snapshot_object_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v0alpha1/snapshot_object_gen.go @@ -23,6 +23,12 @@ type Snapshot struct { Spec SnapshotSpec `json:"spec" yaml:"spec"` } +func NewSnapshot() *Snapshot { + return &Snapshot{ + Spec: *NewSnapshotSpec(), + } +} + func (o *Snapshot) GetSpec() any { return o.Spec } diff --git a/apps/dashboard/pkg/apis/dashboard/v0alpha1/snapshot_schema_gen.go b/apps/dashboard/pkg/apis/dashboard/v0alpha1/snapshot_schema_gen.go index b6086c5fd1f..596c5bb2890 100644 --- a/apps/dashboard/pkg/apis/dashboard/v0alpha1/snapshot_schema_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v0alpha1/snapshot_schema_gen.go @@ -10,7 +10,7 @@ import ( // schema is unexported to prevent accidental overwrites var ( - schemaSnapshot = resource.NewSimpleSchema("dashboard.grafana.app", "v0alpha1", &Snapshot{}, &SnapshotList{}, resource.WithKind("Snapshot"), + schemaSnapshot = resource.NewSimpleSchema("dashboard.grafana.app", "v0alpha1", NewSnapshot(), &SnapshotList{}, resource.WithKind("Snapshot"), resource.WithPlural("snapshots"), resource.WithScope(resource.NamespacedScope)) kindSnapshot = resource.Kind{ Schema: schemaSnapshot, diff --git a/apps/dashboard/pkg/apis/dashboard/v0alpha1/validation.go b/apps/dashboard/pkg/apis/dashboard/v0alpha1/validation.go index a90eab95126..295797a2fb5 100644 --- a/apps/dashboard/pkg/apis/dashboard/v0alpha1/validation.go +++ b/apps/dashboard/pkg/apis/dashboard/v0alpha1/validation.go @@ -12,7 +12,6 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" "cuelang.org/go/cue" - "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" ) @@ -83,11 +82,13 @@ var schemaSource string func getValidator() *cuevalidator.Validator { getSchemaOnce.Do(func() { - cueCtx := cuecontext.New() - compiledSchema := cueCtx.CompileString(schemaSource).LookupPath( + // The validator uses periodic context recreation to prevent memory leaks. + // The context is reused for up to 100 validations, then recreated to allow + // garbage collection of cached values while maintaining good performance. + validator = cuevalidator.NewValidatorFromSource( + schemaSource, cue.ParsePath("lineage.schemas[0].schema.spec"), ) - validator = cuevalidator.NewValidator(compiledSchema) }) return validator diff --git a/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_object_gen.go b/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_object_gen.go index be021b5f003..35bb8900ab0 100644 --- a/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_object_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_object_gen.go @@ -25,6 +25,13 @@ 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 } diff --git a/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_schema_gen.go b/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_schema_gen.go index e944e0afc33..006312837e0 100644 --- a/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_schema_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_schema_gen.go @@ -10,7 +10,7 @@ import ( // schema is unexported to prevent accidental overwrites var ( - schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v1beta1", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"), + schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v1beta1", NewDashboard(), &DashboardList{}, resource.WithKind("Dashboard"), resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope)) kindDashboard = resource.Kind{ Schema: schemaDashboard, diff --git a/apps/dashboard/pkg/apis/dashboard/v1beta1/validation.go b/apps/dashboard/pkg/apis/dashboard/v1beta1/validation.go index 248dc27111c..0b57f702409 100644 --- a/apps/dashboard/pkg/apis/dashboard/v1beta1/validation.go +++ b/apps/dashboard/pkg/apis/dashboard/v1beta1/validation.go @@ -10,7 +10,6 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" "cuelang.org/go/cue" - "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/cuevalidator" @@ -84,11 +83,13 @@ var schemaSource string func getValidator() *cuevalidator.Validator { getSchemaOnce.Do(func() { - cueCtx := cuecontext.New() - compiledSchema := cueCtx.CompileString(schemaSource).LookupPath( + // The validator uses periodic context recreation to prevent memory leaks. + // The context is reused for up to 100 validations, then recreated to allow + // garbage collection of cached values while maintaining good performance. + validator = cuevalidator.NewValidatorFromSource( + schemaSource, cue.ParsePath("lineage.schemas[0].schema.spec"), ) - validator = cuevalidator.NewValidator(compiledSchema) }) return validator diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_object_gen.go b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_object_gen.go index 99cf7df0da9..6a06594656e 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_object_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_object_gen.go @@ -25,6 +25,13 @@ 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 } diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_schema_gen.go b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_schema_gen.go index 136698cf70f..1a5f27d0fb5 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_schema_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_schema_gen.go @@ -10,7 +10,7 @@ import ( // schema is unexported to prevent accidental overwrites var ( - schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2alpha1", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"), + schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2alpha1", NewDashboard(), &DashboardList{}, resource.WithKind("Dashboard"), resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope)) kindDashboard = resource.Kind{ Schema: schemaDashboard, diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/validation.go b/apps/dashboard/pkg/apis/dashboard/v2alpha1/validation.go index ca9dcd3e514..71f2e6d08e1 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/validation.go +++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/validation.go @@ -10,7 +10,6 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" "cuelang.org/go/cue" - "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/cuevalidator" @@ -133,11 +132,13 @@ var schemaSource string func getValidator() *cuevalidator.Validator { getSchemaOnce.Do(func() { - cueCtx := cuecontext.New() - compiledSchema := cueCtx.CompileString(schemaSource).LookupPath( + // The validator uses periodic context recreation to prevent memory leaks. + // The context is reused for up to 100 validations, then recreated to allow + // garbage collection of cached values while maintaining good performance. + validator = cuevalidator.NewValidatorFromSource( + schemaSource, cue.ParsePath("DashboardSpec"), ) - validator = cuevalidator.NewValidator(compiledSchema) }) return validator diff --git a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_object_gen.go b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_object_gen.go index 5076b7d9b0c..bb64a321a1d 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_object_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_object_gen.go @@ -25,6 +25,13 @@ 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 } diff --git a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_schema_gen.go b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_schema_gen.go index 30c2237ca31..35d87fd07f7 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_schema_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_schema_gen.go @@ -10,7 +10,7 @@ import ( // schema is unexported to prevent accidental overwrites var ( - schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2beta1", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"), + schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2beta1", NewDashboard(), &DashboardList{}, resource.WithKind("Dashboard"), resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope)) kindDashboard = resource.Kind{ Schema: schemaDashboard, diff --git a/apps/dashboard/pkg/apis/dashboard/v2beta1/validation.go b/apps/dashboard/pkg/apis/dashboard/v2beta1/validation.go index 518c133bcd7..875be7b4beb 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2beta1/validation.go +++ b/apps/dashboard/pkg/apis/dashboard/v2beta1/validation.go @@ -10,7 +10,6 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" "cuelang.org/go/cue" - "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/errors" "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/cuevalidator" @@ -133,11 +132,13 @@ var schemaSource string func getValidator() *cuevalidator.Validator { getSchemaOnce.Do(func() { - cueCtx := cuecontext.New() - compiledSchema := cueCtx.CompileString(schemaSource).LookupPath( + // The validator uses periodic context recreation to prevent memory leaks. + // The context is reused for up to 100 validations, then recreated to allow + // garbage collection of cached values while maintaining good performance. + validator = cuevalidator.NewValidatorFromSource( + schemaSource, cue.ParsePath("DashboardSpec"), ) - validator = cuevalidator.NewValidator(compiledSchema) }) return validator diff --git a/apps/dashboard/pkg/apis/dashboard_manifest.go b/apps/dashboard/pkg/apis/dashboard_manifest.go index 974062efcec..c4e35bd8f40 100644 --- a/apps/dashboard/pkg/apis/dashboard_manifest.go +++ b/apps/dashboard/pkg/apis/dashboard_manifest.go @@ -6,6 +6,7 @@ package apis import ( + "encoding/json" "fmt" "strings" @@ -21,6 +22,24 @@ import ( v2beta1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1" ) +var ( + rawSchemaDashboardv0alpha1 = []byte(`{"ConversionStatus":{"additionalProperties":false,"description":"ConversionStatus is the status of the conversion of the dashboard.","properties":{"error":{"description":"The error message from the conversion.\nEmpty if the conversion has not failed.","type":"string"},"failed":{"description":"Whether from another version has failed.\nIf true, means that the dashboard is not valid,\nand the caller should instead fetch the stored version.","type":"boolean"},"source":{"additionalProperties":{},"description":"The original value map[string]any","type":"object"},"storedVersion":{"description":"The version which was stored when the dashboard was created / updated.\nFetching this version should always succeed.","type":"string"}},"required":["failed"],"type":"object"},"Dashboard":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"spec":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"status":{"additionalProperties":false,"properties":{"conversion":{"$ref":"#/components/schemas/ConversionStatus","description":"Optional conversion status."}},"type":"object"}}`) + versionSchemaDashboardv0alpha1 app.VersionSchema + _ = json.Unmarshal(rawSchemaDashboardv0alpha1, &versionSchemaDashboardv0alpha1) + rawSchemaSnapshotv0alpha1 = []byte(`{"Snapshot":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"dashboard":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"The raw dashboard (unstructured for now)","type":"object"},"expires":{"default":0,"description":"Optionally auto-remove the snapshot at a future date (Unix timestamp in seconds)","type":"integer"},"external":{"default":false,"description":"When set to true, the snapshot exists in a remote server","type":"boolean"},"externalUrl":{"description":"The external URL where the snapshot can be seen","type":"string"},"originalUrl":{"description":"The URL that created the dashboard originally","type":"string"},"timestamp":{"description":"Snapshot creation timestamp","type":"string"},"title":{"description":"Snapshot title","type":"string"}},"type":"object"}}`) + versionSchemaSnapshotv0alpha1 app.VersionSchema + _ = json.Unmarshal(rawSchemaSnapshotv0alpha1, &versionSchemaSnapshotv0alpha1) + rawSchemaDashboardv1beta1 = []byte(`{"ConversionStatus":{"additionalProperties":false,"description":"ConversionStatus is the status of the conversion of the dashboard.","properties":{"error":{"description":"The error message from the conversion.\nEmpty if the conversion has not failed.","type":"string"},"failed":{"description":"Whether from another version has failed.\nIf true, means that the dashboard is not valid,\nand the caller should instead fetch the stored version.","type":"boolean"},"source":{"additionalProperties":{},"description":"The original value map[string]any","type":"object"},"storedVersion":{"description":"The version which was stored when the dashboard was created / updated.\nFetching this version should always succeed.","type":"string"}},"required":["failed"],"type":"object"},"Dashboard":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"spec":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"status":{"additionalProperties":false,"properties":{"conversion":{"$ref":"#/components/schemas/ConversionStatus","description":"Optional conversion status."}},"type":"object"}}`) + versionSchemaDashboardv1beta1 app.VersionSchema + _ = json.Unmarshal(rawSchemaDashboardv1beta1, &versionSchemaDashboardv1beta1) + rawSchemaDashboardv2alpha1 = []byte(`{"Action":{"additionalProperties":false,"properties":{"confirmation":{"type":"string"},"fetch":{"$ref":"#/components/schemas/FetchOptions"},"infinity":{"$ref":"#/components/schemas/InfinityOptions"},"oneClick":{"type":"boolean"},"style":{"additionalProperties":false,"properties":{"backgroundColor":{"type":"string"}},"type":"object"},"title":{"type":"string"},"type":{"$ref":"#/components/schemas/ActionType"},"variables":{"items":{"$ref":"#/components/schemas/ActionVariable"},"type":"array"}},"required":["type","title"],"type":"object"},"ActionType":{"enum":["fetch","infinity"],"type":"string"},"ActionVariable":{"additionalProperties":false,"properties":{"key":{"type":"string"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/ActionVariableType"}},"required":["key","name","type"],"type":"object"},"ActionVariableType":{"const":"string","description":"Action variable type","type":"string"},"AdHocFilterWithLabels":{"additionalProperties":false,"description":"Define the AdHocFilterWithLabels type","properties":{"condition":{"description":"@deprecated","type":"string"},"forceEdit":{"type":"boolean"},"key":{"type":"string"},"keyLabel":{"type":"string"},"operator":{"type":"string"},"origin":{"$ref":"#/components/schemas/FilterOrigin"},"value":{"type":"string"},"valueLabels":{"items":{"type":"string"},"type":"array"},"values":{"items":{"type":"string"},"type":"array"}},"required":["key","operator","value"],"type":"object"},"AdhocVariableKind":{"additionalProperties":false,"description":"Adhoc variable kind","properties":{"kind":{"const":"AdhocVariable","type":"string"},"spec":{"$ref":"#/components/schemas/AdhocVariableSpec"}},"required":["kind","spec"],"type":"object"},"AdhocVariableSpec":{"additionalProperties":false,"description":"Adhoc variable specification","properties":{"allowCustomValue":{"default":true,"type":"boolean"},"baseFilters":{"items":{"$ref":"#/components/schemas/AdHocFilterWithLabels"},"type":"array"},"datasource":{"$ref":"#/components/schemas/DataSourceRef"},"defaultKeys":{"items":{"$ref":"#/components/schemas/MetricFindValue"},"type":"array"},"description":{"type":"string"},"filters":{"items":{"$ref":"#/components/schemas/AdHocFilterWithLabels"},"type":"array"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"label":{"type":"string"},"name":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","baseFilters","filters","defaultKeys","hide","skipUrlSync","allowCustomValue"],"type":"object"},"AnnotationEventFieldMapping":{"additionalProperties":false,"description":"Annotation event field mapping. Defines how to map a data frame field to an annotation event field.","properties":{"regex":{"description":"Regular expression to apply to the field value","type":"string"},"source":{"default":"field","description":"Source type for the field value","type":"string"},"value":{"description":"Constant value to use when source is \"text\"","type":"string"}},"type":"object"},"AnnotationPanelFilter":{"additionalProperties":false,"properties":{"exclude":{"default":false,"description":"Should the specified panels be included or excluded","type":"boolean"},"ids":{"description":"Panel IDs that should be included or excluded","items":{"type":"integer"},"type":"array"}},"required":["ids"],"type":"object"},"AnnotationQueryKind":{"additionalProperties":false,"properties":{"kind":{"const":"AnnotationQuery","type":"string"},"spec":{"$ref":"#/components/schemas/AnnotationQuerySpec"}},"required":["kind","spec"],"type":"object"},"AnnotationQuerySpec":{"additionalProperties":false,"properties":{"builtIn":{"default":false,"type":"boolean"},"datasource":{"$ref":"#/components/schemas/DataSourceRef"},"enable":{"type":"boolean"},"filter":{"$ref":"#/components/schemas/AnnotationPanelFilter"},"hide":{"type":"boolean"},"iconColor":{"type":"string"},"legacyOptions":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"Catch-all field for datasource-specific properties","type":"object"},"mappings":{"additionalProperties":{"$ref":"#/components/schemas/AnnotationEventFieldMapping"},"description":"Mappings define how to convert data frame fields to annotation event fields.","type":"object"},"name":{"type":"string"},"query":{"$ref":"#/components/schemas/DataQueryKind"}},"required":["enable","hide","iconColor","name"],"type":"object"},"AutoGridLayoutItemKind":{"additionalProperties":false,"properties":{"kind":{"const":"AutoGridLayoutItem","type":"string"},"spec":{"$ref":"#/components/schemas/AutoGridLayoutItemSpec"}},"required":["kind","spec"],"type":"object"},"AutoGridLayoutItemSpec":{"additionalProperties":false,"properties":{"conditionalRendering":{"$ref":"#/components/schemas/ConditionalRenderingGroupKind"},"element":{"$ref":"#/components/schemas/ElementReference"},"repeat":{"$ref":"#/components/schemas/AutoGridRepeatOptions"}},"required":["element"],"type":"object"},"AutoGridLayoutKind":{"additionalProperties":false,"properties":{"kind":{"const":"AutoGridLayout","type":"string"},"spec":{"$ref":"#/components/schemas/AutoGridLayoutSpec"}},"required":["kind","spec"],"type":"object"},"AutoGridLayoutSpec":{"additionalProperties":false,"properties":{"columnWidth":{"type":"number"},"columnWidthMode":{"default":"standard","enum":["narrow","standard","wide","custom"],"type":"string"},"fillScreen":{"default":false,"type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/AutoGridLayoutItemKind"},"type":"array"},"maxColumnCount":{"default":3,"type":"number"},"rowHeight":{"type":"number"},"rowHeightMode":{"default":"standard","enum":["short","standard","tall","custom"],"type":"string"}},"required":["columnWidthMode","rowHeightMode","items"],"type":"object"},"AutoGridRepeatOptions":{"additionalProperties":false,"properties":{"mode":{"$ref":"#/components/schemas/RepeatMode"},"value":{"type":"string"}},"required":["mode","value"],"type":"object"},"ConditionalRenderingDataKind":{"additionalProperties":false,"properties":{"kind":{"const":"ConditionalRenderingData","type":"string"},"spec":{"$ref":"#/components/schemas/ConditionalRenderingDataSpec"}},"required":["kind","spec"],"type":"object"},"ConditionalRenderingDataSpec":{"additionalProperties":false,"properties":{"value":{"type":"boolean"}},"required":["value"],"type":"object"},"ConditionalRenderingGroupKind":{"additionalProperties":false,"properties":{"kind":{"const":"ConditionalRenderingGroup","type":"string"},"spec":{"$ref":"#/components/schemas/ConditionalRenderingGroupSpec"}},"required":["kind","spec"],"type":"object"},"ConditionalRenderingGroupSpec":{"additionalProperties":false,"properties":{"condition":{"enum":["and","or"],"type":"string"},"items":{"items":{"oneOf":[{"$ref":"#/components/schemas/ConditionalRenderingVariableKind"},{"$ref":"#/components/schemas/ConditionalRenderingDataKind"},{"$ref":"#/components/schemas/ConditionalRenderingTimeRangeSizeKind"}]},"type":"array"},"visibility":{"enum":["show","hide"],"type":"string"}},"required":["visibility","condition","items"],"type":"object"},"ConditionalRenderingTimeRangeSizeKind":{"additionalProperties":false,"properties":{"kind":{"const":"ConditionalRenderingTimeRangeSize","type":"string"},"spec":{"$ref":"#/components/schemas/ConditionalRenderingTimeRangeSizeSpec"}},"required":["kind","spec"],"type":"object"},"ConditionalRenderingTimeRangeSizeSpec":{"additionalProperties":false,"properties":{"value":{"type":"string"}},"required":["value"],"type":"object"},"ConditionalRenderingVariableKind":{"additionalProperties":false,"properties":{"kind":{"const":"ConditionalRenderingVariable","type":"string"},"spec":{"$ref":"#/components/schemas/ConditionalRenderingVariableSpec"}},"required":["kind","spec"],"type":"object"},"ConditionalRenderingVariableSpec":{"additionalProperties":false,"properties":{"operator":{"enum":["equals","notEquals","matches","notMatches"],"type":"string"},"value":{"type":"string"},"variable":{"type":"string"}},"required":["variable","operator","value"],"type":"object"},"ConstantVariableKind":{"additionalProperties":false,"description":"Constant variable kind","properties":{"kind":{"const":"ConstantVariable","type":"string"},"spec":{"$ref":"#/components/schemas/ConstantVariableSpec"}},"required":["kind","spec"],"type":"object"},"ConstantVariableSpec":{"additionalProperties":false,"description":"Constant variable specification","properties":{"current":{"$ref":"#/components/schemas/VariableOption","default":{"text":"","value":""}},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"label":{"type":"string"},"name":{"default":"","type":"string"},"query":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","query","current","hide","skipUrlSync"],"type":"object"},"ConversionStatus":{"additionalProperties":false,"description":"ConversionStatus is the status of the conversion of the dashboard.","properties":{"error":{"description":"The error message from the conversion.\nEmpty if the conversion has not failed.","type":"string"},"failed":{"description":"Whether from another version has failed.\nIf true, means that the dashboard is not valid,\nand the caller should instead fetch the stored version.","type":"boolean"},"source":{"additionalProperties":{},"description":"The original value map[string]any","type":"object"},"storedVersion":{"description":"The version which was stored when the dashboard was created / updated.\nFetching this version should always succeed.","type":"string"}},"required":["failed"],"type":"object"},"CustomVariableKind":{"additionalProperties":false,"description":"Custom variable kind","properties":{"kind":{"const":"CustomVariable","type":"string"},"spec":{"$ref":"#/components/schemas/CustomVariableSpec"}},"required":["kind","spec"],"type":"object"},"CustomVariableSpec":{"additionalProperties":false,"description":"Custom variable specification","properties":{"allValue":{"type":"string"},"allowCustomValue":{"default":true,"type":"boolean"},"current":{"$ref":"#/components/schemas/VariableOption"},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"includeAll":{"default":false,"type":"boolean"},"label":{"type":"string"},"multi":{"default":false,"type":"boolean"},"name":{"default":"","type":"string"},"options":{"items":{"$ref":"#/components/schemas/VariableOption"},"type":"array"},"query":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","query","current","options","multi","includeAll","hide","skipUrlSync","allowCustomValue"],"type":"object"},"Dashboard":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"DashboardCursorSync":{"description":"\"Off\" for no shared crosshair or tooltip (default).\n\"Crosshair\" for shared crosshair.\n\"Tooltip\" for shared crosshair AND shared tooltip.","enum":["Crosshair","Tooltip","Off"],"type":"string"},"DashboardLink":{"additionalProperties":false,"description":"Links with references to other dashboards or external resources","properties":{"asDropdown":{"default":false,"description":"If true, all dashboards links will be displayed in a dropdown. If false, all dashboards links will be displayed side by side. Only valid if the type is dashboards","type":"boolean"},"icon":{"description":"Icon name to be displayed with the link","type":"string"},"includeVars":{"default":false,"description":"If true, includes current template variables values in the link as query params","type":"boolean"},"keepTime":{"default":false,"description":"If true, includes current time range in the link as query params","type":"boolean"},"placement":{"$ref":"#/components/schemas/DashboardLinkPlacement","description":"Placement can be used to display the link somewhere else on the dashboard other than above the visualisations."},"tags":{"description":"List of tags to limit the linked dashboards. If empty, all dashboards will be displayed. Only valid if the type is dashboards","items":{"type":"string"},"type":"array"},"targetBlank":{"default":false,"description":"If true, the link will be opened in a new tab","type":"boolean"},"title":{"description":"Title to display with the link","type":"string"},"tooltip":{"description":"Tooltip to display when the user hovers their mouse over it","type":"string"},"type":{"$ref":"#/components/schemas/DashboardLinkType","description":"Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource)\nFIXME: The type is generated as ` + "`" + `type: DashboardLinkType | dashboardLinkType.Link;` + "`" + ` but it should be ` + "`" + `type: DashboardLinkType` + "`" + `"},"url":{"description":"Link URL. Only required/valid if the type is link","type":"string"}},"required":["title","type","icon","tooltip","tags","asDropdown","targetBlank","includeVars","keepTime"],"type":"object"},"DashboardLinkPlacement":{"const":"inControlsMenu","description":"Dashboard Link placement. Defines where the link should be displayed.\n- \"inControlsMenu\" renders the link in bottom part of the dashboard controls dropdown menu","type":"string"},"DashboardLinkType":{"description":"Dashboard Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource)","enum":["link","dashboards"],"type":"string"},"DataLink":{"additionalProperties":false,"properties":{"targetBlank":{"type":"boolean"},"title":{"type":"string"},"url":{"type":"string"}},"required":["title","url"],"type":"object"},"DataQueryKind":{"additionalProperties":false,"properties":{"kind":{"description":"The kind of a DataQueryKind is the datasource type","type":"string"},"spec":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"}},"required":["kind","spec"],"type":"object"},"DataSourceRef":{"additionalProperties":false,"properties":{"type":{"description":"The plugin type-id","type":"string"},"uid":{"description":"Specific datasource instance","type":"string"}},"type":"object"},"DataTopic":{"description":"A topic is attached to DataFrame metadata in query results.\nThis specifies where the data should be used.","enum":["series","annotations","alertStates"],"type":"string"},"DataTransformerConfig":{"additionalProperties":false,"description":"Transformations allow to manipulate data returned by a query before the system applies a visualization.\nUsing transformations you can: rename fields, join time series data, perform mathematical operations across queries,\nuse the output of one transformation as the input to another transformation, etc.","properties":{"disabled":{"description":"Disabled transformations are skipped","type":"boolean"},"filter":{"$ref":"#/components/schemas/MatcherConfig","description":"Optional frame matcher. When missing it will be applied to all results"},"id":{"description":"Unique identifier of transformer","type":"string"},"options":{"additionalProperties":{},"description":"Options to be passed to the transformer\nValid options depend on the transformer id","type":"object"},"topic":{"$ref":"#/components/schemas/DataTopic","description":"Where to pull DataFrames from as input to transformation"}},"required":["id","options"],"type":"object"},"DatasourceVariableKind":{"additionalProperties":false,"description":"Datasource variable kind","properties":{"kind":{"const":"DatasourceVariable","type":"string"},"spec":{"$ref":"#/components/schemas/DatasourceVariableSpec"}},"required":["kind","spec"],"type":"object"},"DatasourceVariableSpec":{"additionalProperties":false,"description":"Datasource variable specification","properties":{"allValue":{"type":"string"},"allowCustomValue":{"default":true,"type":"boolean"},"current":{"$ref":"#/components/schemas/VariableOption","default":{"text":"","value":""}},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"includeAll":{"default":false,"type":"boolean"},"label":{"type":"string"},"multi":{"default":false,"type":"boolean"},"name":{"default":"","type":"string"},"options":{"items":{"$ref":"#/components/schemas/VariableOption"},"type":"array"},"pluginId":{"default":"","type":"string"},"refresh":{"$ref":"#/components/schemas/VariableRefresh","default":"never"},"regex":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","pluginId","refresh","regex","current","options","multi","includeAll","hide","skipUrlSync","allowCustomValue"],"type":"object"},"DynamicConfigValue":{"additionalProperties":false,"properties":{"id":{"default":"","type":"string"},"value":{"additionalProperties":{},"type":"object"}},"required":["id"],"type":"object"},"Element":{"description":"Supported dashboard elements\n|* more element types in the future","oneOf":[{"$ref":"#/components/schemas/PanelKind"},{"$ref":"#/components/schemas/LibraryPanelKind"}]},"ElementReference":{"additionalProperties":false,"properties":{"kind":{"const":"ElementReference","type":"string"},"name":{"type":"string"}},"required":["kind","name"],"type":"object"},"FetchOptions":{"additionalProperties":false,"properties":{"body":{"type":"string"},"headers":{"items":{"items":{"type":"string"},"type":"array"},"type":"array"},"method":{"$ref":"#/components/schemas/HttpRequestMethod"},"queryParams":{"description":"These are 2D arrays of strings, each representing a key-value pair\nWe are defining them this way because we can't generate a go struct that\nthat would have exactly two strings in each sub-array","items":{"items":{"type":"string"},"type":"array"},"type":"array"},"url":{"type":"string"}},"required":["method","url"],"type":"object"},"FieldColor":{"additionalProperties":false,"description":"Map a field to a color.","properties":{"fixedColor":{"description":"The fixed color value for fixed or shades color modes.","type":"string"},"mode":{"$ref":"#/components/schemas/FieldColorModeId","description":"The main color scheme mode."},"seriesBy":{"$ref":"#/components/schemas/FieldColorSeriesByMode","description":"Some visualizations need to know how to assign a series color from by value color schemes."}},"required":["mode"],"type":"object"},"FieldColorModeId":{"description":"Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value.\nContinuous color interpolates a color using the percentage of a value relative to min and max.\nAccepted values are:\n` + "`" + `thresholds` + "`" + `: From thresholds. Informs Grafana to take the color from the matching threshold\n` + "`" + `palette-classic` + "`" + `: Classic palette. Grafana will assign color by looking up a color in a palette by series index. Useful for Graphs and pie charts and other categorical data visualizations\n` + "`" + `palette-classic-by-name` + "`" + `: Classic palette (by name). Grafana will assign color by looking up a color in a palette by series name. Useful for Graphs and pie charts and other categorical data visualizations\n` + "`" + `continuous-viridis` + "`" + `: Continuous Viridis palette mode\n` + "`" + `continuous-magma` + "`" + `: Continuous Magma palette mode\n` + "`" + `continuous-plasma` + "`" + `: Continuous Plasma palette mode\n` + "`" + `continuous-inferno` + "`" + `: Continuous Inferno palette mode\n` + "`" + `continuous-cividis` + "`" + `: Continuous Cividis palette mode\n` + "`" + `continuous-GrYlRd` + "`" + `: Continuous Green-Yellow-Red palette mode\n` + "`" + `continuous-RdYlGr` + "`" + `: Continuous Red-Yellow-Green palette mode\n` + "`" + `continuous-BlYlRd` + "`" + `: Continuous Blue-Yellow-Red palette mode\n` + "`" + `continuous-YlRd` + "`" + `: Continuous Yellow-Red palette mode\n` + "`" + `continuous-BlPu` + "`" + `: Continuous Blue-Purple palette mode\n` + "`" + `continuous-YlBl` + "`" + `: Continuous Yellow-Blue palette mode\n` + "`" + `continuous-blues` + "`" + `: Continuous Blue palette mode\n` + "`" + `continuous-reds` + "`" + `: Continuous Red palette mode\n` + "`" + `continuous-greens` + "`" + `: Continuous Green palette mode\n` + "`" + `continuous-purples` + "`" + `: Continuous Purple palette mode\n` + "`" + `shades` + "`" + `: Shades of a single color. Specify a single color, useful in an override rule.\n` + "`" + `fixed` + "`" + `: Fixed color mode. Specify a single color, useful in an override rule.","enum":["thresholds","palette-classic","palette-classic-by-name","continuous-viridis","continuous-magma","continuous-plasma","continuous-inferno","continuous-cividis","continuous-GrYlRd","continuous-RdYlGr","continuous-BlYlRd","continuous-YlRd","continuous-BlPu","continuous-YlBl","continuous-blues","continuous-reds","continuous-greens","continuous-purples","fixed","shades"],"type":"string"},"FieldColorSeriesByMode":{"description":"Defines how to assign a series color from \"by value\" color schemes. For example for an aggregated data points like a timeseries, the color can be assigned by the min, max or last value.","enum":["min","max","last"],"type":"string"},"FieldConfig":{"additionalProperties":false,"description":"The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results.\nEach column within this structure is called a field. A field can represent a single time series or table column.\nField options allow you to change how the data is displayed in your visualizations.","properties":{"actions":{"description":"Define interactive HTTP requests that can be triggered from data visualizations.","items":{"$ref":"#/components/schemas/Action"},"type":"array"},"color":{"$ref":"#/components/schemas/FieldColor","description":"Panel color configuration"},"custom":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"custom is specified by the FieldConfig field\nin panel plugin schemas.","type":"object"},"decimals":{"description":"Specify the number of decimals Grafana includes in the rendered value.\nIf you leave this field blank, Grafana automatically truncates the number of decimals based on the value.\nFor example 1.1234 will display as 1.12 and 100.456 will display as 100.\nTo display all decimals, set the unit to ` + "`" + `String` + "`" + `.","type":"number"},"description":{"description":"Human readable field metadata","type":"string"},"displayName":{"description":"The display value for this field. This supports template variables blank is auto","type":"string"},"displayNameFromDS":{"description":"This can be used by data sources that return and explicit naming structure for values and labels\nWhen this property is configured, this value is used rather than the default naming strategy.","type":"string"},"filterable":{"description":"True if data source field supports ad-hoc filters","type":"boolean"},"links":{"description":"The behavior when clicking on a result","items":{"additionalProperties":{},"type":"object"},"type":"array"},"mappings":{"description":"Convert input values into a display string","items":{"$ref":"#/components/schemas/ValueMapping"},"type":"array"},"max":{"description":"The maximum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.","type":"number"},"min":{"description":"The minimum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.","type":"number"},"noValue":{"description":"Alternative to empty string","type":"string"},"path":{"description":"An explicit path to the field in the datasource. When the frame meta includes a path,\nThis will default to ` + "`" + `${frame.meta.path}/${field.name}\n\nWhen defined, this value can be used as an identifier within the datasource scope, and\nmay be used to update the results","type":"string"},"thresholds":{"$ref":"#/components/schemas/ThresholdsConfig","description":"Map numeric values to states"},"unit":{"description":"Unit a field should use. The unit you select is applied to all fields except time.\nYou can use the units ID availables in Grafana or a custom unit.\nAvailable units in Grafana: https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/valueFormats/categories.ts\nAs custom unit, you can use the following formats:\n` + "`" + `suffix:\u003csuffix\u003e` + "`" + ` for custom unit that should go after value.\n` + "`" + `prefix:\u003cprefix\u003e` + "`" + ` for custom unit that should go before value.\n` + "`" + `time:\u003cformat\u003e` + "`" + ` For custom date time formats type for example ` + "`" + `time:YYYY-MM-DD` + "`" + `.\n` + "`" + `si:\u003cbase scale\u003e\u003cunit characters\u003e` + "`" + ` for custom SI units. For example: ` + "`" + `si: mF` + "`" + `. This one is a bit more advanced as you can specify both a unit and the source data scale. So if your source data is represented as milli (thousands of) something prefix the unit with that SI scale character.\n` + "`" + `count:\u003cunit\u003e` + "`" + ` for a custom count unit.\n` + "`" + `currency:\u003cunit\u003e` + "`" + ` for custom a currency unit.","type":"string"},"writeable":{"description":"True if data source can write a value to the path. Auth/authz are supported separately","type":"boolean"}},"type":"object"},"FieldConfigSource":{"additionalProperties":false,"description":"The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results.\nEach column within this structure is called a field. A field can represent a single time series or table column.\nField options allow you to change how the data is displayed in your visualizations.","properties":{"defaults":{"$ref":"#/components/schemas/FieldConfig","description":"Defaults are the options applied to all fields."},"overrides":{"description":"Overrides are the options applied to specific fields overriding the defaults.","items":{"additionalProperties":false,"properties":{"__systemRef":{"description":"Describes config override rules created when interacting with Grafana.","type":"string"},"matcher":{"$ref":"#/components/schemas/MatcherConfig"},"properties":{"items":{"$ref":"#/components/schemas/DynamicConfigValue"},"type":"array"}},"required":["matcher","properties"],"type":"object"},"type":"array"}},"required":["defaults","overrides"],"type":"object"},"FilterOrigin":{"const":"dashboard","description":"Determine the origin of the adhoc variable filter","type":"string"},"GridLayoutItemKind":{"additionalProperties":false,"properties":{"kind":{"const":"GridLayoutItem","type":"string"},"spec":{"$ref":"#/components/schemas/GridLayoutItemSpec"}},"required":["kind","spec"],"type":"object"},"GridLayoutItemSpec":{"additionalProperties":false,"properties":{"element":{"$ref":"#/components/schemas/ElementReference","description":"reference to a PanelKind from dashboard.spec.elements Expressed as JSON Schema reference"},"height":{"type":"integer"},"repeat":{"$ref":"#/components/schemas/RepeatOptions"},"width":{"type":"integer"},"x":{"type":"integer"},"y":{"type":"integer"}},"required":["x","y","width","height","element"],"type":"object"},"GridLayoutKind":{"additionalProperties":false,"properties":{"kind":{"const":"GridLayout","type":"string"},"spec":{"$ref":"#/components/schemas/GridLayoutSpec"}},"required":["kind","spec"],"type":"object"},"GridLayoutSpec":{"additionalProperties":false,"properties":{"items":{"items":{"$ref":"#/components/schemas/GridLayoutItemKind"},"type":"array"}},"required":["items"],"type":"object"},"GroupByVariableKind":{"additionalProperties":false,"description":"Group variable kind","properties":{"kind":{"const":"GroupByVariable","type":"string"},"spec":{"$ref":"#/components/schemas/GroupByVariableSpec"}},"required":["kind","spec"],"type":"object"},"GroupByVariableSpec":{"additionalProperties":false,"description":"GroupBy variable specification","properties":{"current":{"$ref":"#/components/schemas/VariableOption","default":{"text":"","value":""}},"datasource":{"$ref":"#/components/schemas/DataSourceRef"},"defaultValue":{"$ref":"#/components/schemas/VariableOption"},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"label":{"type":"string"},"multi":{"default":false,"type":"boolean"},"name":{"default":"","type":"string"},"options":{"items":{"$ref":"#/components/schemas/VariableOption"},"type":"array"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","current","options","multi","hide","skipUrlSync"],"type":"object"},"HttpRequestMethod":{"enum":["GET","PUT","POST","DELETE","PATCH"],"type":"string"},"InfinityOptions":{"additionalProperties":false,"properties":{"body":{"type":"string"},"datasourceUid":{"type":"string"},"headers":{"items":{"items":{"type":"string"},"type":"array"},"type":"array"},"method":{"$ref":"#/components/schemas/HttpRequestMethod"},"queryParams":{"description":"These are 2D arrays of strings, each representing a key-value pair\nWe are defining them this way because we can't generate a go struct that\nthat would have exactly two strings in each sub-array","items":{"items":{"type":"string"},"type":"array"},"type":"array"},"url":{"type":"string"}},"required":["method","url","datasourceUid"],"type":"object"},"IntervalVariableKind":{"additionalProperties":false,"description":"Interval variable kind","properties":{"kind":{"const":"IntervalVariable","type":"string"},"spec":{"$ref":"#/components/schemas/IntervalVariableSpec"}},"required":["kind","spec"],"type":"object"},"IntervalVariableSpec":{"additionalProperties":false,"description":"Interval variable specification","properties":{"auto":{"default":false,"type":"boolean"},"auto_count":{"default":0,"type":"integer"},"auto_min":{"default":"","type":"string"},"current":{"$ref":"#/components/schemas/VariableOption","default":{"text":"","value":""}},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"label":{"type":"string"},"name":{"default":"","type":"string"},"options":{"items":{"$ref":"#/components/schemas/VariableOption"},"type":"array"},"query":{"default":"","type":"string"},"refresh":{"$ref":"#/components/schemas/VariableRefresh","default":"never"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","query","current","options","auto","auto_min","auto_count","refresh","hide","skipUrlSync"],"type":"object"},"LibraryPanelKind":{"additionalProperties":false,"properties":{"kind":{"const":"LibraryPanel","type":"string"},"spec":{"$ref":"#/components/schemas/LibraryPanelKindSpec"}},"required":["kind","spec"],"type":"object"},"LibraryPanelKindSpec":{"additionalProperties":false,"properties":{"id":{"description":"Panel ID for the library panel in the dashboard","type":"number"},"libraryPanel":{"$ref":"#/components/schemas/LibraryPanelRef"},"title":{"description":"Title for the library panel in the dashboard","type":"string"}},"required":["id","title","libraryPanel"],"type":"object"},"LibraryPanelRef":{"additionalProperties":false,"description":"A library panel is a reusable panel that you can use in any dashboard.\nWhen you make a change to a library panel, that change propagates to all instances of where the panel is used.\nLibrary panels streamline reuse of panels across multiple dashboards.","properties":{"name":{"description":"Library panel name","type":"string"},"uid":{"description":"Library panel uid","type":"string"}},"required":["name","uid"],"type":"object"},"MappingType":{"description":"Supported value mapping types\n` + "`" + `value` + "`" + `: Maps text values to a color or different display text and color. For example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.\n` + "`" + `range` + "`" + `: Maps numerical ranges to a display text and color. For example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.\n` + "`" + `regex` + "`" + `: Maps regular expressions to replacement text and a color. For example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.\n` + "`" + `special` + "`" + `: Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color. See SpecialValueMatch to see the list of special values. For example, you can configure a special value mapping so that null values appear as N/A.","enum":["value","range","regex","special"],"type":"string"},"MatcherConfig":{"additionalProperties":false,"description":"Matcher is a predicate configuration. Based on the config a set of field(s) or values is filtered in order to apply override / transformation.\nIt comes with in id ( to resolve implementation from registry) and a configuration that’s specific to a particular matcher type.","properties":{"id":{"default":"","description":"The matcher id. This is used to find the matcher implementation from registry.","type":"string"},"options":{"additionalProperties":{},"description":"The matcher options. This is specific to the matcher implementation.","type":"object"}},"required":["id"],"type":"object"},"MetricFindValue":{"additionalProperties":false,"description":"Define the MetricFindValue type","properties":{"expandable":{"type":"boolean"},"group":{"type":"string"},"text":{"type":"string"},"value":{"oneOf":[{"type":"string"},{"type":"number"}]}},"required":["text"],"type":"object"},"PanelKind":{"additionalProperties":false,"properties":{"kind":{"const":"Panel","type":"string"},"spec":{"$ref":"#/components/schemas/PanelSpec"}},"required":["kind","spec"],"type":"object"},"PanelQueryKind":{"additionalProperties":false,"properties":{"kind":{"const":"PanelQuery","type":"string"},"spec":{"$ref":"#/components/schemas/PanelQuerySpec"}},"required":["kind","spec"],"type":"object"},"PanelQuerySpec":{"additionalProperties":false,"properties":{"datasource":{"$ref":"#/components/schemas/DataSourceRef"},"hidden":{"type":"boolean"},"query":{"$ref":"#/components/schemas/DataQueryKind"},"refId":{"type":"string"}},"required":["query","refId","hidden"],"type":"object"},"PanelSpec":{"additionalProperties":false,"properties":{"data":{"$ref":"#/components/schemas/QueryGroupKind"},"description":{"type":"string"},"id":{"type":"number"},"links":{"items":{"$ref":"#/components/schemas/DataLink"},"type":"array"},"title":{"type":"string"},"transparent":{"type":"boolean"},"vizConfig":{"$ref":"#/components/schemas/VizConfigKind"}},"required":["id","title","description","links","data","vizConfig"],"type":"object"},"QueryGroupKind":{"additionalProperties":false,"properties":{"kind":{"const":"QueryGroup","type":"string"},"spec":{"$ref":"#/components/schemas/QueryGroupSpec"}},"required":["kind","spec"],"type":"object"},"QueryGroupSpec":{"additionalProperties":false,"properties":{"queries":{"items":{"$ref":"#/components/schemas/PanelQueryKind"},"type":"array"},"queryOptions":{"$ref":"#/components/schemas/QueryOptionsSpec"},"transformations":{"items":{"$ref":"#/components/schemas/TransformationKind"},"type":"array"}},"required":["queries","transformations","queryOptions"],"type":"object"},"QueryOptionsSpec":{"additionalProperties":false,"properties":{"cacheTimeout":{"type":"string"},"hideTimeOverride":{"type":"boolean"},"interval":{"type":"string"},"maxDataPoints":{"type":"integer"},"queryCachingTTL":{"type":"integer"},"timeFrom":{"type":"string"},"timeShift":{"type":"string"}},"type":"object"},"QueryVariableKind":{"additionalProperties":false,"description":"Query variable kind","properties":{"kind":{"const":"QueryVariable","type":"string"},"spec":{"$ref":"#/components/schemas/QueryVariableSpec"}},"required":["kind","spec"],"type":"object"},"QueryVariableSpec":{"additionalProperties":false,"description":"Query variable specification","properties":{"allValue":{"type":"string"},"allowCustomValue":{"default":true,"type":"boolean"},"current":{"$ref":"#/components/schemas/VariableOption","default":{"text":"","value":""}},"datasource":{"$ref":"#/components/schemas/DataSourceRef"},"definition":{"type":"string"},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"includeAll":{"default":false,"type":"boolean"},"label":{"type":"string"},"multi":{"default":false,"type":"boolean"},"name":{"default":"","type":"string"},"options":{"items":{"$ref":"#/components/schemas/VariableOption"},"type":"array"},"placeholder":{"type":"string"},"query":{"$ref":"#/components/schemas/DataQueryKind"},"refresh":{"$ref":"#/components/schemas/VariableRefresh","default":"never"},"regex":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"},"sort":{"$ref":"#/components/schemas/VariableSort"},"staticOptions":{"items":{"$ref":"#/components/schemas/VariableOption"},"type":"array"},"staticOptionsOrder":{"enum":["before","after","sorted"],"type":"string"}},"required":["name","current","hide","refresh","skipUrlSync","query","regex","sort","options","multi","includeAll","allowCustomValue"],"type":"object"},"RangeMap":{"additionalProperties":false,"description":"Maps numerical ranges to a display text and color.\nFor example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.","properties":{"options":{"additionalProperties":false,"description":"Range to match against and the result to apply when the value is within the range","properties":{"from":{"description":"Min value of the range. It can be null which means -Infinity","type":"number"},"result":{"$ref":"#/components/schemas/ValueMappingResult","description":"Config to apply when the value is within the range"},"to":{"description":"Max value of the range. It can be null which means +Infinity","type":"number"}},"required":["from","to","result"],"type":"object"},"type":{"$ref":"#/components/schemas/MappingType"}},"required":["type","options"],"type":"object"},"RegexMap":{"additionalProperties":false,"description":"Maps regular expressions to replacement text and a color.\nFor example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.","properties":{"options":{"additionalProperties":false,"description":"Regular expression to match against and the result to apply when the value matches the regex","properties":{"pattern":{"description":"Regular expression to match against","type":"string"},"result":{"$ref":"#/components/schemas/ValueMappingResult","description":"Config to apply when the value matches the regex"}},"required":["pattern","result"],"type":"object"},"type":{"$ref":"#/components/schemas/MappingType"}},"required":["type","options"],"type":"object"},"RepeatMode":{"const":"variable","description":"other repeat modes will be added in the future: label, frame","type":"string"},"RepeatOptions":{"additionalProperties":false,"properties":{"direction":{"enum":["h","v"],"type":"string"},"maxPerRow":{"type":"integer"},"mode":{"$ref":"#/components/schemas/RepeatMode"},"value":{"type":"string"}},"required":["mode","value"],"type":"object"},"RowRepeatOptions":{"additionalProperties":false,"properties":{"mode":{"$ref":"#/components/schemas/RepeatMode"},"value":{"type":"string"}},"required":["mode","value"],"type":"object"},"RowsLayoutKind":{"additionalProperties":false,"properties":{"kind":{"const":"RowsLayout","type":"string"},"spec":{"$ref":"#/components/schemas/RowsLayoutSpec"}},"required":["kind","spec"],"type":"object"},"RowsLayoutRowKind":{"additionalProperties":false,"properties":{"kind":{"const":"RowsLayoutRow","type":"string"},"spec":{"$ref":"#/components/schemas/RowsLayoutRowSpec"}},"required":["kind","spec"],"type":"object"},"RowsLayoutRowSpec":{"additionalProperties":false,"properties":{"collapse":{"type":"boolean"},"conditionalRendering":{"$ref":"#/components/schemas/ConditionalRenderingGroupKind"},"fillScreen":{"type":"boolean"},"hideHeader":{"type":"boolean"},"layout":{"oneOf":[{"$ref":"#/components/schemas/GridLayoutKind"},{"$ref":"#/components/schemas/AutoGridLayoutKind"},{"$ref":"#/components/schemas/TabsLayoutKind"},{"$ref":"#/components/schemas/RowsLayoutKind"}]},"repeat":{"$ref":"#/components/schemas/RowRepeatOptions"},"title":{"type":"string"}},"required":["layout"],"type":"object"},"RowsLayoutSpec":{"additionalProperties":false,"properties":{"rows":{"items":{"$ref":"#/components/schemas/RowsLayoutRowKind"},"type":"array"}},"required":["rows"],"type":"object"},"SpecialValueMap":{"additionalProperties":false,"description":"Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color.\nSee SpecialValueMatch to see the list of special values.\nFor example, you can configure a special value mapping so that null values appear as N/A.","properties":{"options":{"additionalProperties":false,"properties":{"match":{"$ref":"#/components/schemas/SpecialValueMatch","description":"Special value to match against"},"result":{"$ref":"#/components/schemas/ValueMappingResult","description":"Config to apply when the value matches the special value"}},"required":["match","result"],"type":"object"},"type":{"$ref":"#/components/schemas/MappingType"}},"required":["type","options"],"type":"object"},"SpecialValueMatch":{"description":"Special value types supported by the ` + "`" + `SpecialValueMap` + "`" + `","enum":["true","false","null","nan","null+nan","empty"],"type":"string"},"SwitchVariableKind":{"additionalProperties":false,"properties":{"kind":{"const":"SwitchVariable","type":"string"},"spec":{"$ref":"#/components/schemas/SwitchVariableSpec"}},"required":["kind","spec"],"type":"object"},"SwitchVariableSpec":{"additionalProperties":false,"description":"Switch variable specification","properties":{"current":{"default":"false","type":"string"},"description":{"type":"string"},"disabledValue":{"default":"false","type":"string"},"enabledValue":{"default":"true","type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"label":{"type":"string"},"name":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","current","enabledValue","disabledValue","hide","skipUrlSync"],"type":"object"},"TabRepeatOptions":{"additionalProperties":false,"properties":{"mode":{"$ref":"#/components/schemas/RepeatMode"},"value":{"type":"string"}},"required":["mode","value"],"type":"object"},"TabsLayoutKind":{"additionalProperties":false,"properties":{"kind":{"const":"TabsLayout","type":"string"},"spec":{"$ref":"#/components/schemas/TabsLayoutSpec"}},"required":["kind","spec"],"type":"object"},"TabsLayoutSpec":{"additionalProperties":false,"properties":{"tabs":{"items":{"$ref":"#/components/schemas/TabsLayoutTabKind"},"type":"array"}},"required":["tabs"],"type":"object"},"TabsLayoutTabKind":{"additionalProperties":false,"properties":{"kind":{"const":"TabsLayoutTab","type":"string"},"spec":{"$ref":"#/components/schemas/TabsLayoutTabSpec"}},"required":["kind","spec"],"type":"object"},"TabsLayoutTabSpec":{"additionalProperties":false,"properties":{"conditionalRendering":{"$ref":"#/components/schemas/ConditionalRenderingGroupKind"},"layout":{"oneOf":[{"$ref":"#/components/schemas/GridLayoutKind"},{"$ref":"#/components/schemas/RowsLayoutKind"},{"$ref":"#/components/schemas/AutoGridLayoutKind"},{"$ref":"#/components/schemas/TabsLayoutKind"}]},"repeat":{"$ref":"#/components/schemas/TabRepeatOptions"},"title":{"type":"string"}},"required":["layout"],"type":"object"},"TextVariableKind":{"additionalProperties":false,"description":"Text variable kind","properties":{"kind":{"const":"TextVariable","type":"string"},"spec":{"$ref":"#/components/schemas/TextVariableSpec"}},"required":["kind","spec"],"type":"object"},"TextVariableSpec":{"additionalProperties":false,"description":"Text variable specification","properties":{"current":{"$ref":"#/components/schemas/VariableOption","default":{"text":"","value":""}},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"label":{"type":"string"},"name":{"default":"","type":"string"},"query":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","current","query","hide","skipUrlSync"],"type":"object"},"Threshold":{"additionalProperties":false,"properties":{"color":{"type":"string"},"value":{"description":"Value null means -Infinity","type":"number"}},"required":["value","color"],"type":"object"},"ThresholdsConfig":{"additionalProperties":false,"properties":{"mode":{"$ref":"#/components/schemas/ThresholdsMode"},"steps":{"items":{"$ref":"#/components/schemas/Threshold"},"type":"array"}},"required":["mode","steps"],"type":"object"},"ThresholdsMode":{"enum":["absolute","percentage"],"type":"string"},"TimeRangeOption":{"additionalProperties":false,"properties":{"display":{"default":"Last 6 hours","type":"string"},"from":{"default":"now-6h","type":"string"},"to":{"default":"now","type":"string"}},"required":["display","from","to"],"type":"object"},"TimeSettingsSpec":{"additionalProperties":false,"description":"Time configuration\nIt defines the default time config for the time picker, the refresh picker for the specific dashboard.","properties":{"autoRefresh":{"default":"","description":"Refresh rate of dashboard. Represented via interval string, e.g. \"5s\", \"1m\", \"1h\", \"1d\".\nv1: refresh","type":"string"},"autoRefreshIntervals":{"default":["5s","10s","30s","1m","5m","15m","30m","1h","2h","1d"],"description":"Interval options available in the refresh picker dropdown.\nv1: timepicker.refresh_intervals","items":{"type":"string"},"type":"array"},"fiscalYearStartMonth":{"default":0,"description":"The month that the fiscal year starts on. 0 = January, 11 = December","type":"integer"},"from":{"default":"now-6h","description":"Start time range for dashboard.\nAccepted values are relative time strings like \"now-6h\" or absolute time strings like \"2020-07-10T08:00:00.000Z\".","type":"string"},"hideTimepicker":{"default":false,"description":"Whether timepicker is visible or not.\nv1: timepicker.hidden","type":"boolean"},"nowDelay":{"description":"Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.\nv1: timepicker.nowDelay","type":"string"},"quickRanges":{"description":"Selectable options available in the time picker dropdown. Has no effect on provisioned dashboard.\nv1: timepicker.quick_ranges , not exposed in the UI","items":{"$ref":"#/components/schemas/TimeRangeOption"},"type":"array"},"timezone":{"default":"browser","description":"Timezone of dashboard. Accepted values are IANA TZDB zone ID or \"browser\" or \"utc\".","type":"string"},"to":{"default":"now","description":"End time range for dashboard.\nAccepted values are relative time strings like \"now-6h\" or absolute time strings like \"2020-07-10T08:00:00.000Z\".","type":"string"},"weekStart":{"description":"Day when the week starts. Expressed by the name of the day in lowercase, e.g. \"monday\".","enum":["saturday","monday","sunday"],"type":"string"}},"required":["from","to","autoRefresh","autoRefreshIntervals","hideTimepicker","fiscalYearStartMonth"],"type":"object"},"TransformationKind":{"additionalProperties":false,"properties":{"kind":{"description":"The kind of a TransformationKind is the transformation ID","type":"string"},"spec":{"$ref":"#/components/schemas/DataTransformerConfig"}},"required":["kind","spec"],"type":"object"},"ValueMap":{"additionalProperties":false,"description":"Maps text values to a color or different display text and color.\nFor example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.","properties":{"options":{"additionalProperties":{"$ref":"#/components/schemas/ValueMappingResult"},"description":"Map with \u003cvalue_to_match\u003e: ValueMappingResult. For example: { \"10\": { text: \"Perfection!\", color: \"green\" } }","type":"object"},"type":{"$ref":"#/components/schemas/MappingType"}},"required":["type","options"],"type":"object"},"ValueMapping":{"oneOf":[{"$ref":"#/components/schemas/ValueMap"},{"$ref":"#/components/schemas/RangeMap"},{"$ref":"#/components/schemas/RegexMap"},{"$ref":"#/components/schemas/SpecialValueMap"}]},"ValueMappingResult":{"additionalProperties":false,"description":"Result used as replacement with text and color when the value matches","properties":{"color":{"description":"Text to use when the value matches","type":"string"},"icon":{"description":"Icon to display when the value matches. Only specific visualizations.","type":"string"},"index":{"description":"Position in the mapping array. Only used internally.","type":"integer"},"text":{"description":"Text to display when the value matches","type":"string"}},"type":"object"},"VariableHide":{"description":"Determine if the variable shows on dashboard\nAccepted values are ` + "`" + `dontHide` + "`" + ` (show label and value), ` + "`" + `hideLabel` + "`" + ` (show value only), ` + "`" + `hideVariable` + "`" + ` (show nothing).","enum":["dontHide","hideLabel","hideVariable"],"type":"string"},"VariableKind":{"oneOf":[{"$ref":"#/components/schemas/QueryVariableKind"},{"$ref":"#/components/schemas/TextVariableKind"},{"$ref":"#/components/schemas/ConstantVariableKind"},{"$ref":"#/components/schemas/DatasourceVariableKind"},{"$ref":"#/components/schemas/IntervalVariableKind"},{"$ref":"#/components/schemas/CustomVariableKind"},{"$ref":"#/components/schemas/GroupByVariableKind"},{"$ref":"#/components/schemas/AdhocVariableKind"},{"$ref":"#/components/schemas/SwitchVariableKind"}]},"VariableOption":{"additionalProperties":false,"description":"Variable option specification","properties":{"selected":{"description":"Whether the option is selected or not","type":"boolean"},"text":{"description":"Text to be displayed for the option","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"value":{"description":"Value of the option","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]}},"required":["text","value"],"type":"object"},"VariableRefresh":{"description":"Options to config when to refresh a variable\n` + "`" + `never` + "`" + `: Never refresh the variable\n` + "`" + `onDashboardLoad` + "`" + `: Queries the data source every time the dashboard loads.\n` + "`" + `onTimeRangeChanged` + "`" + `: Queries the data source when the dashboard time range changes.","enum":["never","onDashboardLoad","onTimeRangeChanged"],"type":"string"},"VariableSort":{"description":"Sort variable options\nAccepted values are:\n` + "`" + `disabled` + "`" + `: No sorting\n` + "`" + `alphabeticalAsc` + "`" + `: Alphabetical ASC\n` + "`" + `alphabeticalDesc` + "`" + `: Alphabetical DESC\n` + "`" + `numericalAsc` + "`" + `: Numerical ASC\n` + "`" + `numericalDesc` + "`" + `: Numerical DESC\n` + "`" + `alphabeticalCaseInsensitiveAsc` + "`" + `: Alphabetical Case Insensitive ASC\n` + "`" + `alphabeticalCaseInsensitiveDesc` + "`" + `: Alphabetical Case Insensitive DESC\n` + "`" + `naturalAsc` + "`" + `: Natural ASC\n` + "`" + `naturalDesc` + "`" + `: Natural DESC\nVariableSort enum with default value","enum":["disabled","alphabeticalAsc","alphabeticalDesc","numericalAsc","numericalDesc","alphabeticalCaseInsensitiveAsc","alphabeticalCaseInsensitiveDesc","naturalAsc","naturalDesc"],"type":"string"},"VizConfigKind":{"additionalProperties":false,"properties":{"kind":{"description":"The kind of a VizConfigKind is the plugin ID","type":"string"},"spec":{"$ref":"#/components/schemas/VizConfigSpec"}},"required":["kind","spec"],"type":"object"},"VizConfigSpec":{"additionalProperties":false,"description":"--- Kinds ---","properties":{"fieldConfig":{"$ref":"#/components/schemas/FieldConfigSource"},"options":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"pluginVersion":{"type":"string"}},"required":["pluginVersion","options","fieldConfig"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"annotations":{"items":{"$ref":"#/components/schemas/AnnotationQueryKind"},"type":"array"},"cursorSync":{"$ref":"#/components/schemas/DashboardCursorSync","default":"Off","description":"Configuration of dashboard cursor sync behavior.\n\"Off\" for no shared crosshair or tooltip (default).\n\"Crosshair\" for shared crosshair.\n\"Tooltip\" for shared crosshair AND shared tooltip."},"description":{"description":"Description of dashboard.","type":"string"},"editable":{"default":true,"description":"Whether a dashboard is editable or not.","type":"boolean"},"elements":{"additionalProperties":{"$ref":"#/components/schemas/Element"},"type":"object"},"layout":{"oneOf":[{"$ref":"#/components/schemas/GridLayoutKind"},{"$ref":"#/components/schemas/RowsLayoutKind"},{"$ref":"#/components/schemas/AutoGridLayoutKind"},{"$ref":"#/components/schemas/TabsLayoutKind"}]},"links":{"description":"Links with references to other dashboards or external websites.","items":{"$ref":"#/components/schemas/DashboardLink"},"type":"array"},"liveNow":{"description":"When set to true, the dashboard will redraw panels at an interval matching the pixel width.\nThis will keep data \"moving left\" regardless of the query refresh rate. This setting helps\navoid dashboards presenting stale live data.","type":"boolean"},"preload":{"default":false,"description":"When set to true, the dashboard will load all panels in the dashboard when it's loaded.","type":"boolean"},"revision":{"description":"Plugins only. The version of the dashboard installed together with the plugin.\nThis is used to determine if the dashboard should be updated when the plugin is updated.","type":"integer"},"tags":{"description":"Tags associated with dashboard.","items":{"type":"string"},"type":"array"},"timeSettings":{"$ref":"#/components/schemas/TimeSettingsSpec"},"title":{"description":"Title of dashboard.","type":"string"},"variables":{"description":"Configured template variables.","items":{"$ref":"#/components/schemas/VariableKind"},"type":"array"}},"required":["annotations","cursorSync","elements","layout","links","preload","tags","timeSettings","title","variables"],"type":"object"},"status":{"additionalProperties":false,"properties":{"conversion":{"$ref":"#/components/schemas/ConversionStatus","description":"Optional conversion status."}},"type":"object"}}`) + versionSchemaDashboardv2alpha1 app.VersionSchema + _ = json.Unmarshal(rawSchemaDashboardv2alpha1, &versionSchemaDashboardv2alpha1) + rawSchemaDashboardv2beta1 = []byte(`{"Action":{"additionalProperties":false,"properties":{"confirmation":{"type":"string"},"fetch":{"$ref":"#/components/schemas/FetchOptions"},"infinity":{"$ref":"#/components/schemas/InfinityOptions"},"oneClick":{"type":"boolean"},"style":{"additionalProperties":false,"properties":{"backgroundColor":{"type":"string"}},"type":"object"},"title":{"type":"string"},"type":{"$ref":"#/components/schemas/ActionType"},"variables":{"items":{"$ref":"#/components/schemas/ActionVariable"},"type":"array"}},"required":["type","title"],"type":"object"},"ActionType":{"enum":["fetch","infinity"],"type":"string"},"ActionVariable":{"additionalProperties":false,"properties":{"key":{"type":"string"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/ActionVariableType"}},"required":["key","name","type"],"type":"object"},"ActionVariableType":{"const":"string","description":"Action variable type","type":"string"},"AdHocFilterWithLabels":{"additionalProperties":false,"description":"Define the AdHocFilterWithLabels type","properties":{"condition":{"description":"@deprecated","type":"string"},"forceEdit":{"type":"boolean"},"key":{"type":"string"},"keyLabel":{"type":"string"},"operator":{"type":"string"},"origin":{"$ref":"#/components/schemas/FilterOrigin"},"value":{"type":"string"},"valueLabels":{"items":{"type":"string"},"type":"array"},"values":{"items":{"type":"string"},"type":"array"}},"required":["key","operator","value"],"type":"object"},"AdhocVariableKind":{"additionalProperties":false,"description":"Adhoc variable kind","properties":{"datasource":{"additionalProperties":false,"properties":{"name":{"type":"string"}},"type":"object"},"group":{"type":"string"},"kind":{"const":"AdhocVariable","type":"string"},"spec":{"$ref":"#/components/schemas/AdhocVariableSpec"}},"required":["kind","group","spec"],"type":"object"},"AdhocVariableSpec":{"additionalProperties":false,"description":"Adhoc variable specification","properties":{"allowCustomValue":{"default":true,"type":"boolean"},"baseFilters":{"items":{"$ref":"#/components/schemas/AdHocFilterWithLabels"},"type":"array"},"defaultKeys":{"items":{"$ref":"#/components/schemas/MetricFindValue"},"type":"array"},"description":{"type":"string"},"filters":{"items":{"$ref":"#/components/schemas/AdHocFilterWithLabels"},"type":"array"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"label":{"type":"string"},"name":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","baseFilters","filters","defaultKeys","hide","skipUrlSync","allowCustomValue"],"type":"object"},"AnnotationEventFieldMapping":{"additionalProperties":false,"description":"Annotation event field mapping. Defines how to map a data frame field to an annotation event field.","properties":{"regex":{"description":"Regular expression to apply to the field value","type":"string"},"source":{"default":"field","description":"Source type for the field value","type":"string"},"value":{"description":"Constant value to use when source is \"text\"","type":"string"}},"type":"object"},"AnnotationPanelFilter":{"additionalProperties":false,"properties":{"exclude":{"default":false,"description":"Should the specified panels be included or excluded","type":"boolean"},"ids":{"description":"Panel IDs that should be included or excluded","items":{"type":"integer"},"type":"array"}},"required":["ids"],"type":"object"},"AnnotationQueryKind":{"additionalProperties":false,"properties":{"kind":{"const":"AnnotationQuery","type":"string"},"spec":{"$ref":"#/components/schemas/AnnotationQuerySpec"}},"required":["kind","spec"],"type":"object"},"AnnotationQueryPlacement":{"const":"inControlsMenu","description":"Annotation Query placement. Defines where the annotation query should be displayed.\n- \"inControlsMenu\" renders the annotation query in the dashboard controls dropdown menu","type":"string"},"AnnotationQuerySpec":{"additionalProperties":false,"properties":{"builtIn":{"default":false,"type":"boolean"},"enable":{"type":"boolean"},"filter":{"$ref":"#/components/schemas/AnnotationPanelFilter"},"hide":{"type":"boolean"},"iconColor":{"type":"string"},"legacyOptions":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"Catch-all field for datasource-specific properties. Should not be available in as code tooling.","type":"object"},"mappings":{"additionalProperties":{"$ref":"#/components/schemas/AnnotationEventFieldMapping"},"description":"Mappings define how to convert data frame fields to annotation event fields.","type":"object"},"name":{"type":"string"},"placement":{"$ref":"#/components/schemas/AnnotationQueryPlacement","description":"Placement can be used to display the annotation query somewhere else on the dashboard other than the default location."},"query":{"$ref":"#/components/schemas/DataQueryKind"}},"required":["query","enable","hide","iconColor","name"],"type":"object"},"AutoGridLayoutItemKind":{"additionalProperties":false,"properties":{"kind":{"const":"AutoGridLayoutItem","type":"string"},"spec":{"$ref":"#/components/schemas/AutoGridLayoutItemSpec"}},"required":["kind","spec"],"type":"object"},"AutoGridLayoutItemSpec":{"additionalProperties":false,"properties":{"conditionalRendering":{"$ref":"#/components/schemas/ConditionalRenderingGroupKind"},"element":{"$ref":"#/components/schemas/ElementReference"},"repeat":{"$ref":"#/components/schemas/AutoGridRepeatOptions"}},"required":["element"],"type":"object"},"AutoGridLayoutKind":{"additionalProperties":false,"properties":{"kind":{"const":"AutoGridLayout","type":"string"},"spec":{"$ref":"#/components/schemas/AutoGridLayoutSpec"}},"required":["kind","spec"],"type":"object"},"AutoGridLayoutSpec":{"additionalProperties":false,"properties":{"columnWidth":{"type":"number"},"columnWidthMode":{"default":"standard","enum":["narrow","standard","wide","custom"],"type":"string"},"fillScreen":{"default":false,"type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/AutoGridLayoutItemKind"},"type":"array"},"maxColumnCount":{"default":3,"type":"number"},"rowHeight":{"type":"number"},"rowHeightMode":{"default":"standard","enum":["short","standard","tall","custom"],"type":"string"}},"required":["columnWidthMode","rowHeightMode","items"],"type":"object"},"AutoGridRepeatOptions":{"additionalProperties":false,"properties":{"mode":{"$ref":"#/components/schemas/RepeatMode"},"value":{"type":"string"}},"required":["mode","value"],"type":"object"},"ConditionalRenderingDataKind":{"additionalProperties":false,"properties":{"kind":{"const":"ConditionalRenderingData","type":"string"},"spec":{"$ref":"#/components/schemas/ConditionalRenderingDataSpec"}},"required":["kind","spec"],"type":"object"},"ConditionalRenderingDataSpec":{"additionalProperties":false,"properties":{"value":{"type":"boolean"}},"required":["value"],"type":"object"},"ConditionalRenderingGroupKind":{"additionalProperties":false,"properties":{"kind":{"const":"ConditionalRenderingGroup","type":"string"},"spec":{"$ref":"#/components/schemas/ConditionalRenderingGroupSpec"}},"required":["kind","spec"],"type":"object"},"ConditionalRenderingGroupSpec":{"additionalProperties":false,"properties":{"condition":{"enum":["and","or"],"type":"string"},"items":{"items":{"oneOf":[{"$ref":"#/components/schemas/ConditionalRenderingVariableKind"},{"$ref":"#/components/schemas/ConditionalRenderingDataKind"},{"$ref":"#/components/schemas/ConditionalRenderingTimeRangeSizeKind"}]},"type":"array"},"visibility":{"enum":["show","hide"],"type":"string"}},"required":["visibility","condition","items"],"type":"object"},"ConditionalRenderingTimeRangeSizeKind":{"additionalProperties":false,"properties":{"kind":{"const":"ConditionalRenderingTimeRangeSize","type":"string"},"spec":{"$ref":"#/components/schemas/ConditionalRenderingTimeRangeSizeSpec"}},"required":["kind","spec"],"type":"object"},"ConditionalRenderingTimeRangeSizeSpec":{"additionalProperties":false,"properties":{"value":{"type":"string"}},"required":["value"],"type":"object"},"ConditionalRenderingVariableKind":{"additionalProperties":false,"properties":{"kind":{"const":"ConditionalRenderingVariable","type":"string"},"spec":{"$ref":"#/components/schemas/ConditionalRenderingVariableSpec"}},"required":["kind","spec"],"type":"object"},"ConditionalRenderingVariableSpec":{"additionalProperties":false,"properties":{"operator":{"enum":["equals","notEquals","matches","notMatches"],"type":"string"},"value":{"type":"string"},"variable":{"type":"string"}},"required":["variable","operator","value"],"type":"object"},"ConstantVariableKind":{"additionalProperties":false,"description":"Constant variable kind","properties":{"kind":{"const":"ConstantVariable","type":"string"},"spec":{"$ref":"#/components/schemas/ConstantVariableSpec"}},"required":["kind","spec"],"type":"object"},"ConstantVariableSpec":{"additionalProperties":false,"description":"Constant variable specification","properties":{"current":{"$ref":"#/components/schemas/VariableOption","default":{"text":"","value":""}},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"label":{"type":"string"},"name":{"default":"","type":"string"},"query":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","query","current","hide","skipUrlSync"],"type":"object"},"ConversionStatus":{"additionalProperties":false,"description":"ConversionStatus is the status of the conversion of the dashboard.","properties":{"error":{"description":"The error message from the conversion.\nEmpty if the conversion has not failed.","type":"string"},"failed":{"description":"Whether from another version has failed.\nIf true, means that the dashboard is not valid,\nand the caller should instead fetch the stored version.","type":"boolean"},"source":{"additionalProperties":{},"description":"The original value map[string]any","type":"object"},"storedVersion":{"description":"The version which was stored when the dashboard was created / updated.\nFetching this version should always succeed.","type":"string"}},"required":["failed"],"type":"object"},"CustomVariableKind":{"additionalProperties":false,"description":"Custom variable kind","properties":{"kind":{"const":"CustomVariable","type":"string"},"spec":{"$ref":"#/components/schemas/CustomVariableSpec"}},"required":["kind","spec"],"type":"object"},"CustomVariableSpec":{"additionalProperties":false,"description":"Custom variable specification","properties":{"allValue":{"type":"string"},"allowCustomValue":{"default":true,"type":"boolean"},"current":{"$ref":"#/components/schemas/VariableOption"},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"includeAll":{"default":false,"type":"boolean"},"label":{"type":"string"},"multi":{"default":false,"type":"boolean"},"name":{"default":"","type":"string"},"options":{"items":{"$ref":"#/components/schemas/VariableOption"},"type":"array"},"query":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","query","current","options","multi","includeAll","hide","skipUrlSync","allowCustomValue"],"type":"object"},"Dashboard":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"DashboardCursorSync":{"description":"\"Off\" for no shared crosshair or tooltip (default).\n\"Crosshair\" for shared crosshair.\n\"Tooltip\" for shared crosshair AND shared tooltip.","enum":["Crosshair","Tooltip","Off"],"type":"string"},"DashboardLink":{"additionalProperties":false,"description":"Links with references to other dashboards or external resources","properties":{"asDropdown":{"default":false,"description":"If true, all dashboards links will be displayed in a dropdown. If false, all dashboards links will be displayed side by side. Only valid if the type is dashboards","type":"boolean"},"icon":{"description":"Icon name to be displayed with the link","type":"string"},"includeVars":{"default":false,"description":"If true, includes current template variables values in the link as query params","type":"boolean"},"keepTime":{"default":false,"description":"If true, includes current time range in the link as query params","type":"boolean"},"placement":{"$ref":"#/components/schemas/DashboardLinkPlacement","description":"Placement can be used to display the link somewhere else on the dashboard other than above the visualisations."},"tags":{"description":"List of tags to limit the linked dashboards. If empty, all dashboards will be displayed. Only valid if the type is dashboards","items":{"type":"string"},"type":"array"},"targetBlank":{"default":false,"description":"If true, the link will be opened in a new tab","type":"boolean"},"title":{"description":"Title to display with the link","type":"string"},"tooltip":{"description":"Tooltip to display when the user hovers their mouse over it","type":"string"},"type":{"$ref":"#/components/schemas/DashboardLinkType","description":"Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource)\nFIXME: The type is generated as ` + "`" + `type: DashboardLinkType | dashboardLinkType.Link;` + "`" + ` but it should be ` + "`" + `type: DashboardLinkType` + "`" + `"},"url":{"description":"Link URL. Only required/valid if the type is link","type":"string"}},"required":["title","type","icon","tooltip","tags","asDropdown","targetBlank","includeVars","keepTime"],"type":"object"},"DashboardLinkPlacement":{"const":"inControlsMenu","description":"Dashboard Link placement. Defines where the link should be displayed.\n- \"inControlsMenu\" renders the link in bottom part of the dashboard controls dropdown menu","type":"string"},"DashboardLinkType":{"description":"Dashboard Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource)","enum":["link","dashboards"],"type":"string"},"DataLink":{"additionalProperties":false,"properties":{"targetBlank":{"type":"boolean"},"title":{"type":"string"},"url":{"type":"string"}},"required":["title","url"],"type":"object"},"DataQueryKind":{"additionalProperties":false,"properties":{"datasource":{"additionalProperties":false,"description":"New type for datasource reference\nNot creating a new type until we figure out how to handle DS refs for group by, adhoc, and every place that uses DataSourceRef in TS.","properties":{"name":{"type":"string"}},"type":"object"},"group":{"type":"string"},"kind":{"const":"DataQuery","type":"string"},"spec":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"version":{"default":"v0","type":"string"}},"required":["kind","group","version","spec"],"type":"object"},"DataTopic":{"description":"A topic is attached to DataFrame metadata in query results.\nThis specifies where the data should be used.","enum":["series","annotations","alertStates"],"type":"string"},"DataTransformerConfig":{"additionalProperties":false,"description":"Transformations allow to manipulate data returned by a query before the system applies a visualization.\nUsing transformations you can: rename fields, join time series data, perform mathematical operations across queries,\nuse the output of one transformation as the input to another transformation, etc.","properties":{"disabled":{"description":"Disabled transformations are skipped","type":"boolean"},"filter":{"$ref":"#/components/schemas/MatcherConfig","description":"Optional frame matcher. When missing it will be applied to all results"},"id":{"description":"Unique identifier of transformer","type":"string"},"options":{"additionalProperties":{},"description":"Options to be passed to the transformer\nValid options depend on the transformer id","type":"object"},"topic":{"$ref":"#/components/schemas/DataTopic","description":"Where to pull DataFrames from as input to transformation"}},"required":["id","options"],"type":"object"},"DatasourceVariableKind":{"additionalProperties":false,"description":"Datasource variable kind","properties":{"kind":{"const":"DatasourceVariable","type":"string"},"spec":{"$ref":"#/components/schemas/DatasourceVariableSpec"}},"required":["kind","spec"],"type":"object"},"DatasourceVariableSpec":{"additionalProperties":false,"description":"Datasource variable specification","properties":{"allValue":{"type":"string"},"allowCustomValue":{"default":true,"type":"boolean"},"current":{"$ref":"#/components/schemas/VariableOption","default":{"text":"","value":""}},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"includeAll":{"default":false,"type":"boolean"},"label":{"type":"string"},"multi":{"default":false,"type":"boolean"},"name":{"default":"","type":"string"},"options":{"items":{"$ref":"#/components/schemas/VariableOption"},"type":"array"},"pluginId":{"default":"","type":"string"},"refresh":{"$ref":"#/components/schemas/VariableRefresh","default":"never"},"regex":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","pluginId","refresh","regex","current","options","multi","includeAll","hide","skipUrlSync","allowCustomValue"],"type":"object"},"DynamicConfigValue":{"additionalProperties":false,"properties":{"id":{"default":"","type":"string"},"value":{"additionalProperties":{},"type":"object"}},"required":["id"],"type":"object"},"Element":{"description":"Supported dashboard elements\n|* more element types in the future","oneOf":[{"$ref":"#/components/schemas/PanelKind"},{"$ref":"#/components/schemas/LibraryPanelKind"}]},"ElementReference":{"additionalProperties":false,"properties":{"kind":{"const":"ElementReference","type":"string"},"name":{"type":"string"}},"required":["kind","name"],"type":"object"},"FetchOptions":{"additionalProperties":false,"properties":{"body":{"type":"string"},"headers":{"items":{"items":{"type":"string"},"type":"array"},"type":"array"},"method":{"$ref":"#/components/schemas/HttpRequestMethod"},"queryParams":{"description":"These are 2D arrays of strings, each representing a key-value pair\nWe are defining them this way because we can't generate a go struct that\nthat would have exactly two strings in each sub-array","items":{"items":{"type":"string"},"type":"array"},"type":"array"},"url":{"type":"string"}},"required":["method","url"],"type":"object"},"FieldColor":{"additionalProperties":false,"description":"Map a field to a color.","properties":{"fixedColor":{"description":"The fixed color value for fixed or shades color modes.","type":"string"},"mode":{"$ref":"#/components/schemas/FieldColorModeId","description":"The main color scheme mode."},"seriesBy":{"$ref":"#/components/schemas/FieldColorSeriesByMode","description":"Some visualizations need to know how to assign a series color from by value color schemes."}},"required":["mode"],"type":"object"},"FieldColorModeId":{"description":"Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value.\nContinuous color interpolates a color using the percentage of a value relative to min and max.\nAccepted values are:\n` + "`" + `thresholds` + "`" + `: From thresholds. Informs Grafana to take the color from the matching threshold\n` + "`" + `palette-classic` + "`" + `: Classic palette. Grafana will assign color by looking up a color in a palette by series index. Useful for Graphs and pie charts and other categorical data visualizations\n` + "`" + `palette-classic-by-name` + "`" + `: Classic palette (by name). Grafana will assign color by looking up a color in a palette by series name. Useful for Graphs and pie charts and other categorical data visualizations\n` + "`" + `continuous-viridis` + "`" + `: Continuous Viridis palette mode\n` + "`" + `continuous-magma` + "`" + `: Continuous Magma palette mode\n` + "`" + `continuous-plasma` + "`" + `: Continuous Plasma palette mode\n` + "`" + `continuous-inferno` + "`" + `: Continuous Inferno palette mode\n` + "`" + `continuous-cividis` + "`" + `: Continuous Cividis palette mode\n` + "`" + `continuous-GrYlRd` + "`" + `: Continuous Green-Yellow-Red palette mode\n` + "`" + `continuous-RdYlGr` + "`" + `: Continuous Red-Yellow-Green palette mode\n` + "`" + `continuous-BlYlRd` + "`" + `: Continuous Blue-Yellow-Red palette mode\n` + "`" + `continuous-YlRd` + "`" + `: Continuous Yellow-Red palette mode\n` + "`" + `continuous-BlPu` + "`" + `: Continuous Blue-Purple palette mode\n` + "`" + `continuous-YlBl` + "`" + `: Continuous Yellow-Blue palette mode\n` + "`" + `continuous-blues` + "`" + `: Continuous Blue palette mode\n` + "`" + `continuous-reds` + "`" + `: Continuous Red palette mode\n` + "`" + `continuous-greens` + "`" + `: Continuous Green palette mode\n` + "`" + `continuous-purples` + "`" + `: Continuous Purple palette mode\n` + "`" + `shades` + "`" + `: Shades of a single color. Specify a single color, useful in an override rule.\n` + "`" + `fixed` + "`" + `: Fixed color mode. Specify a single color, useful in an override rule.","enum":["thresholds","palette-classic","palette-classic-by-name","continuous-viridis","continuous-magma","continuous-plasma","continuous-inferno","continuous-cividis","continuous-GrYlRd","continuous-RdYlGr","continuous-BlYlRd","continuous-YlRd","continuous-BlPu","continuous-YlBl","continuous-blues","continuous-reds","continuous-greens","continuous-purples","fixed","shades"],"type":"string"},"FieldColorSeriesByMode":{"description":"Defines how to assign a series color from \"by value\" color schemes. For example for an aggregated data points like a timeseries, the color can be assigned by the min, max or last value.","enum":["min","max","last"],"type":"string"},"FieldConfig":{"additionalProperties":false,"description":"The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results.\nEach column within this structure is called a field. A field can represent a single time series or table column.\nField options allow you to change how the data is displayed in your visualizations.","properties":{"actions":{"description":"Define interactive HTTP requests that can be triggered from data visualizations.","items":{"$ref":"#/components/schemas/Action"},"type":"array"},"color":{"$ref":"#/components/schemas/FieldColor","description":"Panel color configuration"},"custom":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"custom is specified by the FieldConfig field\nin panel plugin schemas.","type":"object"},"decimals":{"description":"Specify the number of decimals Grafana includes in the rendered value.\nIf you leave this field blank, Grafana automatically truncates the number of decimals based on the value.\nFor example 1.1234 will display as 1.12 and 100.456 will display as 100.\nTo display all decimals, set the unit to ` + "`" + `String` + "`" + `.","type":"number"},"description":{"description":"Human readable field metadata","type":"string"},"displayName":{"description":"The display value for this field. This supports template variables blank is auto","type":"string"},"displayNameFromDS":{"description":"This can be used by data sources that return and explicit naming structure for values and labels\nWhen this property is configured, this value is used rather than the default naming strategy.","type":"string"},"filterable":{"description":"True if data source field supports ad-hoc filters","type":"boolean"},"links":{"description":"The behavior when clicking on a result","items":{"additionalProperties":{},"type":"object"},"type":"array"},"mappings":{"description":"Convert input values into a display string","items":{"$ref":"#/components/schemas/ValueMapping"},"type":"array"},"max":{"description":"The maximum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.","type":"number"},"min":{"description":"The minimum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.","type":"number"},"noValue":{"description":"Alternative to empty string","type":"string"},"path":{"description":"An explicit path to the field in the datasource. When the frame meta includes a path,\nThis will default to ` + "`" + `${frame.meta.path}/${field.name}\n\nWhen defined, this value can be used as an identifier within the datasource scope, and\nmay be used to update the results","type":"string"},"thresholds":{"$ref":"#/components/schemas/ThresholdsConfig","description":"Map numeric values to states"},"unit":{"description":"Unit a field should use. The unit you select is applied to all fields except time.\nYou can use the units ID availables in Grafana or a custom unit.\nAvailable units in Grafana: https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/valueFormats/categories.ts\nAs custom unit, you can use the following formats:\n` + "`" + `suffix:\u003csuffix\u003e` + "`" + ` for custom unit that should go after value.\n` + "`" + `prefix:\u003cprefix\u003e` + "`" + ` for custom unit that should go before value.\n` + "`" + `time:\u003cformat\u003e` + "`" + ` For custom date time formats type for example ` + "`" + `time:YYYY-MM-DD` + "`" + `.\n` + "`" + `si:\u003cbase scale\u003e\u003cunit characters\u003e` + "`" + ` for custom SI units. For example: ` + "`" + `si: mF` + "`" + `. This one is a bit more advanced as you can specify both a unit and the source data scale. So if your source data is represented as milli (thousands of) something prefix the unit with that SI scale character.\n` + "`" + `count:\u003cunit\u003e` + "`" + ` for a custom count unit.\n` + "`" + `currency:\u003cunit\u003e` + "`" + ` for custom a currency unit.","type":"string"},"writeable":{"description":"True if data source can write a value to the path. Auth/authz are supported separately","type":"boolean"}},"type":"object"},"FieldConfigSource":{"additionalProperties":false,"description":"The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results.\nEach column within this structure is called a field. A field can represent a single time series or table column.\nField options allow you to change how the data is displayed in your visualizations.","properties":{"defaults":{"$ref":"#/components/schemas/FieldConfig","description":"Defaults are the options applied to all fields."},"overrides":{"description":"Overrides are the options applied to specific fields overriding the defaults.","items":{"additionalProperties":false,"properties":{"__systemRef":{"description":"Describes config override rules created when interacting with Grafana.","type":"string"},"matcher":{"$ref":"#/components/schemas/MatcherConfig"},"properties":{"items":{"$ref":"#/components/schemas/DynamicConfigValue"},"type":"array"}},"required":["matcher","properties"],"type":"object"},"type":"array"}},"required":["defaults","overrides"],"type":"object"},"FilterOrigin":{"const":"dashboard","description":"Determine the origin of the adhoc variable filter","type":"string"},"GridLayoutItemKind":{"additionalProperties":false,"properties":{"kind":{"const":"GridLayoutItem","type":"string"},"spec":{"$ref":"#/components/schemas/GridLayoutItemSpec"}},"required":["kind","spec"],"type":"object"},"GridLayoutItemSpec":{"additionalProperties":false,"properties":{"element":{"$ref":"#/components/schemas/ElementReference","description":"reference to a PanelKind from dashboard.spec.elements Expressed as JSON Schema reference"},"height":{"type":"integer"},"repeat":{"$ref":"#/components/schemas/RepeatOptions"},"width":{"type":"integer"},"x":{"type":"integer"},"y":{"type":"integer"}},"required":["x","y","width","height","element"],"type":"object"},"GridLayoutKind":{"additionalProperties":false,"properties":{"kind":{"const":"GridLayout","type":"string"},"spec":{"$ref":"#/components/schemas/GridLayoutSpec"}},"required":["kind","spec"],"type":"object"},"GridLayoutSpec":{"additionalProperties":false,"properties":{"items":{"items":{"$ref":"#/components/schemas/GridLayoutItemKind"},"type":"array"}},"required":["items"],"type":"object"},"GroupByVariableKind":{"additionalProperties":false,"description":"Group variable kind","properties":{"datasource":{"additionalProperties":false,"properties":{"name":{"type":"string"}},"type":"object"},"group":{"type":"string"},"kind":{"const":"GroupByVariable","type":"string"},"spec":{"$ref":"#/components/schemas/GroupByVariableSpec"}},"required":["kind","group","spec"],"type":"object"},"GroupByVariableSpec":{"additionalProperties":false,"description":"GroupBy variable specification","properties":{"current":{"$ref":"#/components/schemas/VariableOption","default":{"text":"","value":""}},"defaultValue":{"$ref":"#/components/schemas/VariableOption"},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"label":{"type":"string"},"multi":{"default":false,"type":"boolean"},"name":{"default":"","type":"string"},"options":{"items":{"$ref":"#/components/schemas/VariableOption"},"type":"array"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","current","options","multi","hide","skipUrlSync"],"type":"object"},"HttpRequestMethod":{"enum":["GET","PUT","POST","DELETE","PATCH"],"type":"string"},"InfinityOptions":{"additionalProperties":false,"properties":{"body":{"type":"string"},"datasourceUid":{"type":"string"},"headers":{"items":{"items":{"type":"string"},"type":"array"},"type":"array"},"method":{"$ref":"#/components/schemas/HttpRequestMethod"},"queryParams":{"description":"These are 2D arrays of strings, each representing a key-value pair\nWe are defining them this way because we can't generate a go struct that\nthat would have exactly two strings in each sub-array","items":{"items":{"type":"string"},"type":"array"},"type":"array"},"url":{"type":"string"}},"required":["method","url","datasourceUid"],"type":"object"},"IntervalVariableKind":{"additionalProperties":false,"description":"Interval variable kind","properties":{"kind":{"const":"IntervalVariable","type":"string"},"spec":{"$ref":"#/components/schemas/IntervalVariableSpec"}},"required":["kind","spec"],"type":"object"},"IntervalVariableSpec":{"additionalProperties":false,"description":"Interval variable specification","properties":{"auto":{"default":false,"type":"boolean"},"auto_count":{"default":0,"type":"integer"},"auto_min":{"default":"","type":"string"},"current":{"$ref":"#/components/schemas/VariableOption","default":{"text":"","value":""}},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"label":{"type":"string"},"name":{"default":"","type":"string"},"options":{"items":{"$ref":"#/components/schemas/VariableOption"},"type":"array"},"query":{"default":"","type":"string"},"refresh":{"const":"onTimeRangeChanged","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","query","current","options","auto","auto_min","auto_count","refresh","hide","skipUrlSync"],"type":"object"},"LibraryPanelKind":{"additionalProperties":false,"properties":{"kind":{"const":"LibraryPanel","type":"string"},"spec":{"$ref":"#/components/schemas/LibraryPanelKindSpec"}},"required":["kind","spec"],"type":"object"},"LibraryPanelKindSpec":{"additionalProperties":false,"properties":{"id":{"description":"Panel ID for the library panel in the dashboard","type":"number"},"libraryPanel":{"$ref":"#/components/schemas/LibraryPanelRef"},"title":{"description":"Title for the library panel in the dashboard","type":"string"}},"required":["id","title","libraryPanel"],"type":"object"},"LibraryPanelRef":{"additionalProperties":false,"description":"A library panel is a reusable panel that you can use in any dashboard.\nWhen you make a change to a library panel, that change propagates to all instances of where the panel is used.\nLibrary panels streamline reuse of panels across multiple dashboards.","properties":{"name":{"description":"Library panel name","type":"string"},"uid":{"description":"Library panel uid","type":"string"}},"required":["name","uid"],"type":"object"},"MappingType":{"description":"Supported value mapping types\n` + "`" + `value` + "`" + `: Maps text values to a color or different display text and color. For example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.\n` + "`" + `range` + "`" + `: Maps numerical ranges to a display text and color. For example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.\n` + "`" + `regex` + "`" + `: Maps regular expressions to replacement text and a color. For example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.\n` + "`" + `special` + "`" + `: Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color. See SpecialValueMatch to see the list of special values. For example, you can configure a special value mapping so that null values appear as N/A.","enum":["value","range","regex","special"],"type":"string"},"MatcherConfig":{"additionalProperties":false,"description":"Matcher is a predicate configuration. Based on the config a set of field(s) or values is filtered in order to apply override / transformation.\nIt comes with in id ( to resolve implementation from registry) and a configuration that’s specific to a particular matcher type.","properties":{"id":{"default":"","description":"The matcher id. This is used to find the matcher implementation from registry.","type":"string"},"options":{"additionalProperties":{},"description":"The matcher options. This is specific to the matcher implementation.","type":"object"}},"required":["id"],"type":"object"},"MetricFindValue":{"additionalProperties":false,"description":"Define the MetricFindValue type","properties":{"expandable":{"type":"boolean"},"group":{"type":"string"},"text":{"type":"string"},"value":{"oneOf":[{"type":"string"},{"type":"number"}]}},"required":["text"],"type":"object"},"PanelKind":{"additionalProperties":false,"properties":{"kind":{"const":"Panel","type":"string"},"spec":{"$ref":"#/components/schemas/PanelSpec"}},"required":["kind","spec"],"type":"object"},"PanelQueryKind":{"additionalProperties":false,"properties":{"kind":{"const":"PanelQuery","type":"string"},"spec":{"$ref":"#/components/schemas/PanelQuerySpec"}},"required":["kind","spec"],"type":"object"},"PanelQuerySpec":{"additionalProperties":false,"properties":{"hidden":{"type":"boolean"},"query":{"$ref":"#/components/schemas/DataQueryKind"},"refId":{"default":"A","type":"string"}},"required":["query","refId","hidden"],"type":"object"},"PanelSpec":{"additionalProperties":false,"properties":{"data":{"$ref":"#/components/schemas/QueryGroupKind"},"description":{"type":"string"},"id":{"type":"number"},"links":{"items":{"$ref":"#/components/schemas/DataLink"},"type":"array"},"title":{"type":"string"},"transparent":{"type":"boolean"},"vizConfig":{"$ref":"#/components/schemas/VizConfigKind"}},"required":["id","title","description","links","data","vizConfig"],"type":"object"},"QueryGroupKind":{"additionalProperties":false,"properties":{"kind":{"const":"QueryGroup","type":"string"},"spec":{"$ref":"#/components/schemas/QueryGroupSpec"}},"required":["kind","spec"],"type":"object"},"QueryGroupSpec":{"additionalProperties":false,"properties":{"queries":{"items":{"$ref":"#/components/schemas/PanelQueryKind"},"type":"array"},"queryOptions":{"$ref":"#/components/schemas/QueryOptionsSpec"},"transformations":{"items":{"$ref":"#/components/schemas/TransformationKind"},"type":"array"}},"required":["queries","transformations","queryOptions"],"type":"object"},"QueryOptionsSpec":{"additionalProperties":false,"properties":{"cacheTimeout":{"type":"string"},"hideTimeOverride":{"type":"boolean"},"interval":{"type":"string"},"maxDataPoints":{"type":"integer"},"queryCachingTTL":{"type":"integer"},"timeCompare":{"type":"string"},"timeFrom":{"type":"string"},"timeShift":{"type":"string"}},"type":"object"},"QueryVariableKind":{"additionalProperties":false,"description":"Query variable kind","properties":{"kind":{"const":"QueryVariable","type":"string"},"spec":{"$ref":"#/components/schemas/QueryVariableSpec"}},"required":["kind","spec"],"type":"object"},"QueryVariableSpec":{"additionalProperties":false,"description":"Query variable specification","properties":{"allValue":{"type":"string"},"allowCustomValue":{"default":true,"type":"boolean"},"current":{"$ref":"#/components/schemas/VariableOption","default":{"text":"","value":""}},"definition":{"type":"string"},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"includeAll":{"default":false,"type":"boolean"},"label":{"type":"string"},"multi":{"default":false,"type":"boolean"},"name":{"default":"","type":"string"},"options":{"items":{"$ref":"#/components/schemas/VariableOption"},"type":"array"},"placeholder":{"type":"string"},"query":{"$ref":"#/components/schemas/DataQueryKind"},"refresh":{"$ref":"#/components/schemas/VariableRefresh","default":"never"},"regex":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"},"sort":{"$ref":"#/components/schemas/VariableSort"},"staticOptions":{"items":{"$ref":"#/components/schemas/VariableOption"},"type":"array"},"staticOptionsOrder":{"enum":["before","after","sorted"],"type":"string"}},"required":["name","current","hide","refresh","skipUrlSync","query","regex","sort","options","multi","includeAll","allowCustomValue"],"type":"object"},"RangeMap":{"additionalProperties":false,"description":"Maps numerical ranges to a display text and color.\nFor example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.","properties":{"options":{"additionalProperties":false,"description":"Range to match against and the result to apply when the value is within the range","properties":{"from":{"description":"Min value of the range. It can be null which means -Infinity","type":"number"},"result":{"$ref":"#/components/schemas/ValueMappingResult","description":"Config to apply when the value is within the range"},"to":{"description":"Max value of the range. It can be null which means +Infinity","type":"number"}},"required":["from","to","result"],"type":"object"},"type":{"$ref":"#/components/schemas/MappingType"}},"required":["type","options"],"type":"object"},"RegexMap":{"additionalProperties":false,"description":"Maps regular expressions to replacement text and a color.\nFor example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.","properties":{"options":{"additionalProperties":false,"description":"Regular expression to match against and the result to apply when the value matches the regex","properties":{"pattern":{"description":"Regular expression to match against","type":"string"},"result":{"$ref":"#/components/schemas/ValueMappingResult","description":"Config to apply when the value matches the regex"}},"required":["pattern","result"],"type":"object"},"type":{"$ref":"#/components/schemas/MappingType"}},"required":["type","options"],"type":"object"},"RepeatMode":{"const":"variable","description":"other repeat modes will be added in the future: label, frame","type":"string"},"RepeatOptions":{"additionalProperties":false,"properties":{"direction":{"enum":["h","v"],"type":"string"},"maxPerRow":{"type":"integer"},"mode":{"$ref":"#/components/schemas/RepeatMode"},"value":{"type":"string"}},"required":["mode","value"],"type":"object"},"RowRepeatOptions":{"additionalProperties":false,"properties":{"mode":{"$ref":"#/components/schemas/RepeatMode"},"value":{"type":"string"}},"required":["mode","value"],"type":"object"},"RowsLayoutKind":{"additionalProperties":false,"properties":{"kind":{"const":"RowsLayout","type":"string"},"spec":{"$ref":"#/components/schemas/RowsLayoutSpec"}},"required":["kind","spec"],"type":"object"},"RowsLayoutRowKind":{"additionalProperties":false,"properties":{"kind":{"const":"RowsLayoutRow","type":"string"},"spec":{"$ref":"#/components/schemas/RowsLayoutRowSpec"}},"required":["kind","spec"],"type":"object"},"RowsLayoutRowSpec":{"additionalProperties":false,"properties":{"collapse":{"type":"boolean"},"conditionalRendering":{"$ref":"#/components/schemas/ConditionalRenderingGroupKind"},"fillScreen":{"type":"boolean"},"hideHeader":{"type":"boolean"},"layout":{"oneOf":[{"$ref":"#/components/schemas/GridLayoutKind"},{"$ref":"#/components/schemas/AutoGridLayoutKind"},{"$ref":"#/components/schemas/TabsLayoutKind"},{"$ref":"#/components/schemas/RowsLayoutKind"}]},"repeat":{"$ref":"#/components/schemas/RowRepeatOptions"},"title":{"type":"string"}},"required":["layout"],"type":"object"},"RowsLayoutSpec":{"additionalProperties":false,"properties":{"rows":{"items":{"$ref":"#/components/schemas/RowsLayoutRowKind"},"type":"array"}},"required":["rows"],"type":"object"},"SpecialValueMap":{"additionalProperties":false,"description":"Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color.\nSee SpecialValueMatch to see the list of special values.\nFor example, you can configure a special value mapping so that null values appear as N/A.","properties":{"options":{"additionalProperties":false,"properties":{"match":{"$ref":"#/components/schemas/SpecialValueMatch","description":"Special value to match against"},"result":{"$ref":"#/components/schemas/ValueMappingResult","description":"Config to apply when the value matches the special value"}},"required":["match","result"],"type":"object"},"type":{"$ref":"#/components/schemas/MappingType"}},"required":["type","options"],"type":"object"},"SpecialValueMatch":{"description":"Special value types supported by the ` + "`" + `SpecialValueMap` + "`" + `","enum":["true","false","null","nan","null+nan","empty"],"type":"string"},"SwitchVariableKind":{"additionalProperties":false,"properties":{"kind":{"const":"SwitchVariable","type":"string"},"spec":{"$ref":"#/components/schemas/SwitchVariableSpec"}},"required":["kind","spec"],"type":"object"},"SwitchVariableSpec":{"additionalProperties":false,"properties":{"current":{"default":"false","type":"string"},"description":{"type":"string"},"disabledValue":{"default":"false","type":"string"},"enabledValue":{"default":"true","type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"label":{"type":"string"},"name":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","current","enabledValue","disabledValue","hide","skipUrlSync"],"type":"object"},"TabRepeatOptions":{"additionalProperties":false,"properties":{"mode":{"$ref":"#/components/schemas/RepeatMode"},"value":{"type":"string"}},"required":["mode","value"],"type":"object"},"TabsLayoutKind":{"additionalProperties":false,"properties":{"kind":{"const":"TabsLayout","type":"string"},"spec":{"$ref":"#/components/schemas/TabsLayoutSpec"}},"required":["kind","spec"],"type":"object"},"TabsLayoutSpec":{"additionalProperties":false,"properties":{"tabs":{"items":{"$ref":"#/components/schemas/TabsLayoutTabKind"},"type":"array"}},"required":["tabs"],"type":"object"},"TabsLayoutTabKind":{"additionalProperties":false,"properties":{"kind":{"const":"TabsLayoutTab","type":"string"},"spec":{"$ref":"#/components/schemas/TabsLayoutTabSpec"}},"required":["kind","spec"],"type":"object"},"TabsLayoutTabSpec":{"additionalProperties":false,"properties":{"conditionalRendering":{"$ref":"#/components/schemas/ConditionalRenderingGroupKind"},"layout":{"oneOf":[{"$ref":"#/components/schemas/GridLayoutKind"},{"$ref":"#/components/schemas/RowsLayoutKind"},{"$ref":"#/components/schemas/AutoGridLayoutKind"},{"$ref":"#/components/schemas/TabsLayoutKind"}]},"repeat":{"$ref":"#/components/schemas/TabRepeatOptions"},"title":{"type":"string"}},"required":["layout"],"type":"object"},"TextVariableKind":{"additionalProperties":false,"description":"Text variable kind","properties":{"kind":{"const":"TextVariable","type":"string"},"spec":{"$ref":"#/components/schemas/TextVariableSpec"}},"required":["kind","spec"],"type":"object"},"TextVariableSpec":{"additionalProperties":false,"description":"Text variable specification","properties":{"current":{"$ref":"#/components/schemas/VariableOption","default":{"text":"","value":""}},"description":{"type":"string"},"hide":{"$ref":"#/components/schemas/VariableHide","default":"dontHide"},"label":{"type":"string"},"name":{"default":"","type":"string"},"query":{"default":"","type":"string"},"skipUrlSync":{"default":false,"type":"boolean"}},"required":["name","current","query","hide","skipUrlSync"],"type":"object"},"Threshold":{"additionalProperties":false,"properties":{"color":{"type":"string"},"value":{"description":"Value null means -Infinity","type":"number"}},"required":["value","color"],"type":"object"},"ThresholdsConfig":{"additionalProperties":false,"properties":{"mode":{"$ref":"#/components/schemas/ThresholdsMode"},"steps":{"items":{"$ref":"#/components/schemas/Threshold"},"type":"array"}},"required":["mode","steps"],"type":"object"},"ThresholdsMode":{"enum":["absolute","percentage"],"type":"string"},"TimeRangeOption":{"additionalProperties":false,"properties":{"display":{"default":"Last 6 hours","type":"string"},"from":{"default":"now-6h","type":"string"},"to":{"default":"now","type":"string"}},"required":["display","from","to"],"type":"object"},"TimeSettingsSpec":{"additionalProperties":false,"description":"Time configuration\nIt defines the default time config for the time picker, the refresh picker for the specific dashboard.","properties":{"autoRefresh":{"default":"","description":"Refresh rate of dashboard. Represented via interval string, e.g. \"5s\", \"1m\", \"1h\", \"1d\".\nv1: refresh","type":"string"},"autoRefreshIntervals":{"default":["5s","10s","30s","1m","5m","15m","30m","1h","2h","1d"],"description":"Interval options available in the refresh picker dropdown.\nv1: timepicker.refresh_intervals","items":{"type":"string"},"type":"array"},"fiscalYearStartMonth":{"default":0,"description":"The month that the fiscal year starts on. 0 = January, 11 = December","type":"integer"},"from":{"default":"now-6h","description":"Start time range for dashboard.\nAccepted values are relative time strings like \"now-6h\" or absolute time strings like \"2020-07-10T08:00:00.000Z\".","type":"string"},"hideTimepicker":{"default":false,"description":"Whether timepicker is visible or not.\nv1: timepicker.hidden","type":"boolean"},"nowDelay":{"description":"Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.\nv1: timepicker.nowDelay","type":"string"},"quickRanges":{"description":"Selectable options available in the time picker dropdown. Has no effect on provisioned dashboard.\nv1: timepicker.quick_ranges , not exposed in the UI","items":{"$ref":"#/components/schemas/TimeRangeOption"},"type":"array"},"timezone":{"default":"browser","description":"Timezone of dashboard. Accepted values are IANA TZDB zone ID or \"browser\" or \"utc\".","type":"string"},"to":{"default":"now","description":"End time range for dashboard.\nAccepted values are relative time strings like \"now-6h\" or absolute time strings like \"2020-07-10T08:00:00.000Z\".","type":"string"},"weekStart":{"description":"Day when the week starts. Expressed by the name of the day in lowercase, e.g. \"monday\".","enum":["saturday","monday","sunday"],"type":"string"}},"required":["from","to","autoRefresh","autoRefreshIntervals","hideTimepicker","fiscalYearStartMonth"],"type":"object"},"TransformationKind":{"additionalProperties":false,"properties":{"kind":{"description":"The kind of a TransformationKind is the transformation ID","type":"string"},"spec":{"$ref":"#/components/schemas/DataTransformerConfig"}},"required":["kind","spec"],"type":"object"},"ValueMap":{"additionalProperties":false,"description":"Maps text values to a color or different display text and color.\nFor example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.","properties":{"options":{"additionalProperties":{"$ref":"#/components/schemas/ValueMappingResult"},"description":"Map with \u003cvalue_to_match\u003e: ValueMappingResult. For example: { \"10\": { text: \"Perfection!\", color: \"green\" } }","type":"object"},"type":{"$ref":"#/components/schemas/MappingType"}},"required":["type","options"],"type":"object"},"ValueMapping":{"oneOf":[{"$ref":"#/components/schemas/ValueMap"},{"$ref":"#/components/schemas/RangeMap"},{"$ref":"#/components/schemas/RegexMap"},{"$ref":"#/components/schemas/SpecialValueMap"}]},"ValueMappingResult":{"additionalProperties":false,"description":"Result used as replacement with text and color when the value matches","properties":{"color":{"description":"Text to use when the value matches","type":"string"},"icon":{"description":"Icon to display when the value matches. Only specific visualizations.","type":"string"},"index":{"description":"Position in the mapping array. Only used internally.","type":"integer"},"text":{"description":"Text to display when the value matches","type":"string"}},"type":"object"},"VariableHide":{"description":"Determine if the variable shows on dashboard\nAccepted values are ` + "`" + `dontHide` + "`" + ` (show label and value), ` + "`" + `hideLabel` + "`" + ` (show value only), ` + "`" + `hideVariable` + "`" + ` (show nothing), ` + "`" + `inControlsMenu` + "`" + ` (show in a drop-down menu).","enum":["dontHide","hideLabel","hideVariable","inControlsMenu"],"type":"string"},"VariableKind":{"oneOf":[{"$ref":"#/components/schemas/QueryVariableKind"},{"$ref":"#/components/schemas/TextVariableKind"},{"$ref":"#/components/schemas/ConstantVariableKind"},{"$ref":"#/components/schemas/DatasourceVariableKind"},{"$ref":"#/components/schemas/IntervalVariableKind"},{"$ref":"#/components/schemas/CustomVariableKind"},{"$ref":"#/components/schemas/GroupByVariableKind"},{"$ref":"#/components/schemas/AdhocVariableKind"},{"$ref":"#/components/schemas/SwitchVariableKind"}]},"VariableOption":{"additionalProperties":false,"description":"Variable option specification","properties":{"selected":{"description":"Whether the option is selected or not","type":"boolean"},"text":{"description":"Text to be displayed for the option","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]},"value":{"description":"Value of the option","oneOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}]}},"required":["text","value"],"type":"object"},"VariableRefresh":{"description":"Options to config when to refresh a variable\n` + "`" + `never` + "`" + `: Never refresh the variable\n` + "`" + `onDashboardLoad` + "`" + `: Queries the data source every time the dashboard loads.\n` + "`" + `onTimeRangeChanged` + "`" + `: Queries the data source when the dashboard time range changes.","enum":["never","onDashboardLoad","onTimeRangeChanged"],"type":"string"},"VariableSort":{"description":"Sort variable options\nAccepted values are:\n` + "`" + `disabled` + "`" + `: No sorting\n` + "`" + `alphabeticalAsc` + "`" + `: Alphabetical ASC\n` + "`" + `alphabeticalDesc` + "`" + `: Alphabetical DESC\n` + "`" + `numericalAsc` + "`" + `: Numerical ASC\n` + "`" + `numericalDesc` + "`" + `: Numerical DESC\n` + "`" + `alphabeticalCaseInsensitiveAsc` + "`" + `: Alphabetical Case Insensitive ASC\n` + "`" + `alphabeticalCaseInsensitiveDesc` + "`" + `: Alphabetical Case Insensitive DESC\n` + "`" + `naturalAsc` + "`" + `: Natural ASC\n` + "`" + `naturalDesc` + "`" + `: Natural DESC\nVariableSort enum with default value","enum":["disabled","alphabeticalAsc","alphabeticalDesc","numericalAsc","numericalDesc","alphabeticalCaseInsensitiveAsc","alphabeticalCaseInsensitiveDesc","naturalAsc","naturalDesc"],"type":"string"},"VizConfigKind":{"additionalProperties":false,"properties":{"group":{"description":"The group is the plugin ID","type":"string"},"kind":{"const":"VizConfig","type":"string"},"spec":{"$ref":"#/components/schemas/VizConfigSpec"},"version":{"type":"string"}},"required":["kind","group","version","spec"],"type":"object"},"VizConfigSpec":{"additionalProperties":false,"description":"--- Kinds ---","properties":{"fieldConfig":{"$ref":"#/components/schemas/FieldConfigSource"},"options":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"}},"required":["options","fieldConfig"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"annotations":{"items":{"$ref":"#/components/schemas/AnnotationQueryKind"},"type":"array"},"cursorSync":{"$ref":"#/components/schemas/DashboardCursorSync","default":"Off","description":"Configuration of dashboard cursor sync behavior.\n\"Off\" for no shared crosshair or tooltip (default).\n\"Crosshair\" for shared crosshair.\n\"Tooltip\" for shared crosshair AND shared tooltip."},"description":{"description":"Description of dashboard.","type":"string"},"editable":{"default":true,"description":"Whether a dashboard is editable or not.","type":"boolean"},"elements":{"additionalProperties":{"$ref":"#/components/schemas/Element"},"type":"object"},"layout":{"oneOf":[{"$ref":"#/components/schemas/GridLayoutKind"},{"$ref":"#/components/schemas/RowsLayoutKind"},{"$ref":"#/components/schemas/AutoGridLayoutKind"},{"$ref":"#/components/schemas/TabsLayoutKind"}]},"links":{"description":"Links with references to other dashboards or external websites.","items":{"$ref":"#/components/schemas/DashboardLink"},"type":"array"},"liveNow":{"description":"When set to true, the dashboard will redraw panels at an interval matching the pixel width.\nThis will keep data \"moving left\" regardless of the query refresh rate. This setting helps\navoid dashboards presenting stale live data.","type":"boolean"},"preload":{"default":false,"description":"When set to true, the dashboard will load all panels in the dashboard when it's loaded.","type":"boolean"},"revision":{"description":"Plugins only. The version of the dashboard installed together with the plugin.\nThis is used to determine if the dashboard should be updated when the plugin is updated.","type":"integer"},"tags":{"description":"Tags associated with dashboard.","items":{"type":"string"},"type":"array"},"timeSettings":{"$ref":"#/components/schemas/TimeSettingsSpec"},"title":{"description":"Title of dashboard.","type":"string"},"variables":{"description":"Configured template variables.","items":{"$ref":"#/components/schemas/VariableKind"},"type":"array"}},"required":["annotations","cursorSync","elements","layout","links","preload","tags","timeSettings","title","variables"],"type":"object"},"status":{"additionalProperties":false,"properties":{"conversion":{"$ref":"#/components/schemas/ConversionStatus","description":"Optional conversion status."}},"type":"object"}}`) + versionSchemaDashboardv2beta1 app.VersionSchema + _ = json.Unmarshal(rawSchemaDashboardv2beta1, &versionSchemaDashboardv2beta1) +) + var appManifestData = app.ManifestData{ AppName: "dashboard", Group: "dashboard.grafana.app", @@ -35,6 +54,7 @@ var appManifestData = app.ManifestData{ Plural: "Dashboards", Scope: "Namespaced", Conversion: false, + Schema: &versionSchemaDashboardv0alpha1, }, { @@ -42,6 +62,7 @@ var appManifestData = app.ManifestData{ Plural: "Snapshots", Scope: "Namespaced", Conversion: false, + Schema: &versionSchemaSnapshotv0alpha1, }, }, Routes: app.ManifestVersionRoutes{ @@ -60,6 +81,7 @@ var appManifestData = app.ManifestData{ Plural: "Dashboards", Scope: "Namespaced", Conversion: false, + Schema: &versionSchemaDashboardv1beta1, }, }, Routes: app.ManifestVersionRoutes{ @@ -78,6 +100,7 @@ var appManifestData = app.ManifestData{ Plural: "Dashboards", Scope: "Namespaced", Conversion: false, + Schema: &versionSchemaDashboardv2alpha1, }, }, Routes: app.ManifestVersionRoutes{ @@ -96,6 +119,7 @@ var appManifestData = app.ManifestData{ Plural: "Dashboards", Scope: "Namespaced", Conversion: false, + Schema: &versionSchemaDashboardv2beta1, }, }, Routes: app.ManifestVersionRoutes{ diff --git a/apps/dashboard/pkg/migration/README.md b/apps/dashboard/pkg/migration/README.md index abca58c9087..ab938e31f66 100644 --- a/apps/dashboard/pkg/migration/README.md +++ b/apps/dashboard/pkg/migration/README.md @@ -8,12 +8,13 @@ This document describes the Grafana dashboard migration system, focusing on conv - [Conversion Flow](#conversion-flow-v0--v1--v2) - [v0 to v1 Conversion](#v0-to-v1-conversion) - [v1 to v2 Conversion](#v1-to-v2-conversion) + - [v2 to v0/v1 Conversion](#v2-to-v0v1-conversion) - [Conversion Matrix](#conversion-matrix) - [API Versions](#api-versions) - [Schema Versions](#schema-versions) - [Testing](#testing) - [Backend conversion tests](#backend-conversion-tests) - - [Frontend migration comparison tests](#frontend-migration-comparison-tests) + - [Backend and frontend conversion parity tests](#backend-and-frontend-conversion-parity-tests) - [Monitoring Migrations](#monitoring-migrations) - [Metrics](#metrics) - [Dashboard conversion success metric](#1-dashboard-conversion-success-metric) @@ -54,6 +55,12 @@ v0alpha1 (Legacy JSON) → v1beta1 (Migrated JSON) → v2alpha1/v2beta1 (Structu - Handles modern dashboard features and Kubernetes-native storage - See [V2 to V1 Layout Conversion](./conversion/v2_to_v1_layout_conversion.md) for details on how V2 layouts are converted back to V1 panel arrays +#### v2 to v0/v1 Conversion: +- Converts structured v2 dashboards back to JSON format (v0alpha1 or v1beta1) +- Chains through intermediate versions: v2 → v1beta1 → v0alpha1 +- v0alpha1 and v1beta1 share the same spec structure (only API version differs) +- Enables backward compatibility when storing v2 dashboards in legacy format + ## Conversion Matrix The system supports conversions between all dashboard API versions: @@ -113,25 +120,51 @@ go test ./apps/dashboard/pkg/migration/conversion/... -v go test ./apps/dashboard/pkg/migration/... -run TestSchemaMigrationMetrics ``` -### Frontend migration comparison tests +### Backend and frontend conversion parity tests -The frontend migration comparison tests validate that backend and frontend conversion logic produce consistent results: +These tests ensure that backend (Go) and frontend (TypeScript) conversions produce identical outputs. This is critical because: -- **Test methodology**: Compares backend vs frontend conversion outputs through DashboardModel integration -- **Dataset coverage**: Tests run against curated test files covering various conversion scenarios -- **Test location**: `public/app/features/dashboard/state/DashboardMigratorToBackend.test.ts` -- **Test data**: Located in `apps/dashboard/pkg/migration/testdata/input/` and `testdata/output/` +- **Dual implementation**: Both backend and frontend implement dashboard version conversions +- **Consistency requirement**: Users should see the same dashboard regardless of which path is used +- **API flexibility**: The API may return dashboards in different versions depending on context + +**Why normalize through Scene?** + +Both backend and frontend outputs are passed through the same Scene load/save cycle before comparison. This normalization: +- Eliminates differences from default values added by Scene +- Handles field ordering variations +- Simulates the real-world flow: dashboard loaded → edited → saved + +**Test locations:** + +| Test File | Purpose | +|-----------|---------| +| `public/app/features/dashboard-scene/serialization/transformSaveModelV1ToV2.test.ts` | v1beta1 → v2beta1 conversion parity | +| `public/app/features/dashboard-scene/serialization/transformSaveModelV2ToV1.test.ts` | v2beta1 → v1beta1/v0alpha1 conversion parity | +| `public/app/features/dashboard/state/DashboardMigratorToBackend.test.ts` | Schema version migration parity | **Test execution:** ```bash -# Frontend migration comparison tests +# V1 to V2 conversion parity tests +yarn test transformSaveModelV1ToV2.test.ts + +# V2 to V1 conversion parity tests +yarn test transformSaveModelV2ToV1.test.ts + +# Schema migration parity tests yarn test DashboardMigratorToBackend.test.ts ``` -**Test approach:** -- **Frontend path**: `jsonInput → DashboardModel → DashboardMigrator → getSaveModelClone()` -- **Backend path**: `jsonInput → Backend Conversion → backendOutput → DashboardModel → getSaveModelClone()` -- **Comparison**: Direct comparison of final converted states from both paths +**Test approach (v1 → v2):** +- **Backend path**: `v1beta1 → Go conversion → v2beta1 → Scene → normalized output` +- **Frontend path**: `v1beta1 → Scene → v2beta1 → Scene → normalized output` +- **Test data**: Uses files from `apps/dashboard/pkg/migration/conversion/testdata/` and migrated dashboards + +**Test approach (v2 → v1/v0):** +- **Backend path**: `v2beta1 → Go conversion → v1beta1/v0alpha1 → Scene → normalized output` +- **Frontend path**: `v2beta1 → Scene → v1beta1 → Scene → normalized output` +- **Target versions**: Tests both v0alpha1 and v1beta1 (they share the same spec structure) +- **Test data**: Uses files from `apps/dashboard/pkg/migration/conversion/testdata/` For schema version migration testing details, see the [SchemaVersion Migration Guide](./schemaversion/README.md). diff --git a/apps/dashboard/pkg/migration/conversion/conversion.go b/apps/dashboard/pkg/migration/conversion/conversion.go index cd014dd1466..d0f90e1ba98 100644 --- a/apps/dashboard/pkg/migration/conversion/conversion.go +++ b/apps/dashboard/pkg/migration/conversion/conversion.go @@ -62,7 +62,7 @@ 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 } @@ -82,7 +82,7 @@ func RegisterConversions(s *runtime.Scheme, dsIndexProvider schemaversion.DataSo // v2beta1 conversions if err := s.AddConversionFunc((*dashv2beta1.Dashboard)(nil), (*dashv0.Dashboard)(nil), withConversionMetrics(dashv2beta1.APIVERSION, dashv0.APIVERSION, func(a, b interface{}, scope conversion.Scope) error { - return Convert_V2beta1_to_V0(a.(*dashv2beta1.Dashboard), b.(*dashv0.Dashboard), scope) + return Convert_V2beta1_to_V0(a.(*dashv2beta1.Dashboard), b.(*dashv0.Dashboard), scope, dsIndexProvider) })); err != nil { return err } diff --git a/apps/dashboard/pkg/migration/conversion/conversion_test.go b/apps/dashboard/pkg/migration/conversion/conversion_test.go index 66647c6b453..88dfb683225 100644 --- a/apps/dashboard/pkg/migration/conversion/conversion_test.go +++ b/apps/dashboard/pkg/migration/conversion/conversion_test.go @@ -605,6 +605,44 @@ func TestConversionMetrics(t *testing.T) { expectedSourceSchema: "v2alpha1", expectedTargetSchema: "v2beta1", }, + { + name: "successful v2alpha1 to v0 conversion", + source: &dashv2alpha1.Dashboard{ + ObjectMeta: metav1.ObjectMeta{UID: "test-uid-4"}, + Spec: dashv2alpha1.DashboardSpec{ + Title: "test dashboard", + Elements: map[string]dashv2alpha1.DashboardElement{}, + Annotations: []dashv2alpha1.DashboardAnnotationQueryKind{}, + Links: []dashv2alpha1.DashboardDashboardLink{}, + }, + }, + target: &dashv0.Dashboard{}, + expectAPISuccess: true, + expectMetricsSuccess: true, + expectedSourceAPI: dashv2alpha1.APIVERSION, + expectedTargetAPI: dashv0.APIVERSION, + expectedSourceSchema: "v2alpha1", + expectedTargetSchema: "42", // V2→V0 results in latest schema version + }, + { + name: "successful v2beta1 to v0 conversion", + source: &dashv2beta1.Dashboard{ + ObjectMeta: metav1.ObjectMeta{UID: "test-uid-5"}, + Spec: dashv2beta1.DashboardSpec{ + Title: "test dashboard", + Elements: map[string]dashv2beta1.DashboardElement{}, + Annotations: []dashv2beta1.DashboardAnnotationQueryKind{}, + Links: []dashv2beta1.DashboardDashboardLink{}, + }, + }, + target: &dashv0.Dashboard{}, + expectAPISuccess: true, + expectMetricsSuccess: true, + expectedSourceAPI: dashv2beta1.APIVERSION, + expectedTargetAPI: dashv0.APIVERSION, + expectedSourceSchema: "v2beta1", + expectedTargetSchema: "42", // V2→V0 results in latest schema version + }, } for _, tt := range tests { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/input/v1beta1.panel-datasource-type-datasource.json b/apps/dashboard/pkg/migration/conversion/testdata/input/v1beta1.panel-datasource-type-datasource.json new file mode 100644 index 00000000000..6becb06c8f6 --- /dev/null +++ b/apps/dashboard/pkg/migration/conversion/testdata/input/v1beta1.panel-datasource-type-datasource.json @@ -0,0 +1,153 @@ +{ + "apiVersion": "dashboard.grafana.app/v1beta1", + "kind": "Dashboard", + "metadata": { + "name": "ad5vfcn", + "namespace": "default", + "uid": "dlMZZl6GndU8gJLUQSmgZxXBPCNXyXhNBeQJhHXl0r4X", + "resourceVersion": "2", + "generation": 2, + "creationTimestamp": "2025-11-28T10:14:21Z", + "labels": { + "grafana.app/deprecatedInternalID": "288" + }, + "annotations": { + "grafana.app/createdBy": "user:eex2ofwuj0agwd", + "grafana.app/updatedBy": "user:eex2ofwuj0agwd", + "grafana.app/updatedTimestamp": "2025-11-28T10:15:06Z" + } + }, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 288, + "links": [], + "panels": [ + { + "datasource": { + "type": "testdata", + "uid": "gdev-testdata" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-pre", + "targets": [ + { + "datasource": {}, + "queryType": "randomWalk", + "refId": "A" + } + ], + "title": "New panel", + "type": "timeseries" + } + ], + "preload": false, + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Panel ds inheritance ", + "uid": "ad5vfcn", + "version": 2 + }, + "status": {} +} diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v10.table_thresholds.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v10.table_thresholds.v0alpha1.json index 624425c41eb..5a6cebb8a91 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v10.table_thresholds.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v10.table_thresholds.v0alpha1.json @@ -4,260 +4,123 @@ "metadata": { "name": "v10.table_thresholds.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "table" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "table" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V10 Table Thresholds Test" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v10.table_thresholds.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V10 Table Thresholds Test", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v11.no-op-migration.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v11.no-op-migration.v0alpha1.json index abf1618c7f8..0442d15c222 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v11.no-op-migration.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v11.no-op-migration.v0alpha1.json @@ -4,229 +4,126 @@ "metadata": { "name": "v11.no-op-migration.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "CPU Usage", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Memory Usage", + "type": "stat" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "server", + "options": [], + "query": "label_values(server)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V11 No-Op Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v11.no-op-migration.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "CPU Usage", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Memory Usage", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V11 No-Op Migration Test Dashboard", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "server", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "__legacyStringValue": "label_values(server)" - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - } - ] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v12.template-variables.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v12.template-variables.v0alpha1.json index 5b7ff4cfca5..7cf9b83cc46 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v12.template-variables.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v12.template-variables.v0alpha1.json @@ -4,232 +4,185 @@ "metadata": { "name": "v12.template-variables.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "refresh_true_var", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "refresh_false_var", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 2, + "includeAll": false, + "multi": false, + "name": "hide_variable_var", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 1, + "includeAll": false, + "multi": false, + "name": "hide_label_var", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 2, + "includeAll": false, + "multi": false, + "name": "priority_var", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "no_properties_var", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V12 Template Variables Migration Test" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v12.template-variables.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": {}, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V12 Template Variables Migration Test", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "refresh_true_var", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "refresh_false_var", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "hide_variable_var", - "current": { - "text": "", - "value": "" - }, - "hide": "hideVariable", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "hide_label_var", - "current": { - "text": "", - "value": "" - }, - "hide": "hideLabel", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "priority_var", - "current": { - "text": "", - "value": "" - }, - "hide": "hideVariable", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "no_properties_var", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - } - ] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.graph_thresholds.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.graph_thresholds.v0alpha1.json index c767888f7a4..7aadfcf8535 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.graph_thresholds.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.graph_thresholds.v0alpha1.json @@ -4,378 +4,167 @@ "metadata": { "name": "v13.graph_thresholds.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Graph with Line Thresholds", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Graph with Fill Thresholds", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Graph with Single Threshold", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Graph with Existing Thresholds", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Non-Graph Panel", + "type": "stat" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V13 Graph Thresholds Migration Test" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v13.graph_thresholds.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Graph with Line Thresholds", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Graph with Fill Thresholds", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Graph with Single Threshold", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Graph with Existing Thresholds", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Non-Graph Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V13 Graph Thresholds Migration Test", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.minimal_graph_config.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.minimal_graph_config.v0alpha1.json index 0ba0e58612d..e768e617055 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.minimal_graph_config.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.minimal_graph_config.v0alpha1.json @@ -4,148 +4,84 @@ "metadata": { "name": "v13.minimal_graph_config.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "editorMode": "builder", + "expr": "{\"a.utf8.metric 🤘\", job=\"prometheus-utf8\"}", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "Dashboard with minimal graph panel settings" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v13.minimal_graph_config.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "gdev-prometheus" - }, - "spec": { - "editorMode": "builder", - "expr": "{\"a.utf8.metric 🤘\", job=\"prometheus-utf8\"}", - "instant": false, - "legendFormat": "__auto", - "range": true - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "browser", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Dashboard with minimal graph panel settings", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v14.shared_crosshair_to_graph_tooltip.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v14.shared_crosshair_to_graph_tooltip.v0alpha1.json index 9dfb93934b8..6f6b04077da 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v14.shared_crosshair_to_graph_tooltip.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v14.shared_crosshair_to_graph_tooltip.v0alpha1.json @@ -4,233 +4,128 @@ "metadata": { "name": "v14.shared_crosshair_to_graph_tooltip.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "cpu_usage", + "refId": "A" + } + ], + "title": "CPU Usage Over Time", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "memory_usage", + "refId": "B" + } + ], + "title": "Memory Usage", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "server", + "options": [], + "query": "label_values(server)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V14 Shared Crosshair Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v14.shared_crosshair_to_graph_tooltip.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Crosshair", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "CPU Usage Over Time", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "expr": "cpu_usage" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Memory Usage", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "expr": "memory_usage" - } - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-1h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V14 Shared Crosshair Migration Test Dashboard", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "server", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "__legacyStringValue": "label_values(server)" - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - } - ] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.mimir_rollout_debugging.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.mimir_rollout_debugging.v0alpha1.json index c16318c1bfd..cc366a688e3 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.mimir_rollout_debugging.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.mimir_rollout_debugging.v0alpha1.json @@ -4,1039 +4,773 @@ "metadata": { "name": "v15.mimir_rollout_debugging.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v15.mimir_rollout_debugging.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "rgba(255, 96, 96, 1)", - "name": "rollouts", - "legacyOptions": { - "expr": "up", - "showIn": 0, - "tags": [], - "titleFormat": "Rollout was underway in {{cluster}}/{{namespace}}", - "type": "tags" - } - } - } - ], - "cursorSync": "Crosshair", - "editable": false, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Versions running", - "description": "### Versions running\nShows the versions reported by each running pod.\n\nThe rollout will fail if any pod is not running the expected version.\n\nPods in green are running the expected version, while pods running other versions are shown in orange.\n\n", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "$datasource" - }, - "spec": { - "expr": "sum by (job, version) (up{job=~\".*\"})", - "format": "table", - "instant": true, - "legendFormat": "__auto" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "groupingToMatrix", - "spec": { - "id": "groupingToMatrix", - "options": { - "columnField": "version", - "rowField": "job", - "valueField": "Value" - } - } - }, - { - "kind": "sortBy", - "spec": { - "id": "sortBy", - "options": { - "sort": [ - { - "field": "job\\version" - } - ] - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "barchart", - "version": "", - "spec": { - "options": { - "barRadius": 0, - "barWidth": 0.97, - "fullHighlight": false, - "groupWidth": 0.7, - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "orientation": "horizontal", - "showValue": "auto", - "stacking": "percent", - "tooltip": { - "mode": "single", - "sort": "none" - }, - "xField": "job\\version", - "xTickLabelRotation": 0, - "xTickLabelSpacing": 0 - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "min": 0, - "max": 1, - "thresholds": { - "mode": "absolute", - "steps": [] - }, - "color": { - "mode": "shades", - "fixedColor": "orange" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "fillOpacity": 80, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineWidth": 1, - "scaleDistribution": { - "type": "linear" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*(target)/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "green", - "mode": "fixed" - } - } - ] - } - ] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Deployment rollout progress", - "description": "### Deployment rollout progress\nShows the number of pods for each `Deployment` that match the desired configuration, as a proportion of the desired number of pods.\n\nThe rollout will fail if insufficient pods match the desired configuration for any `Deployment`.\n\nPods in green match the desired configuration, while pods that do not match the desired configuration are shown in orange.\n\n", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "$datasource" - }, - "spec": { - "expr": "sum by (deployment) (up{job=\"kube-state-metrics\"})", - "format": "table", - "instant": true, - "legendFormat": "__auto" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "sortBy", - "spec": { - "id": "sortBy", - "options": { - "fields": {}, - "sort": [ - { - "field": "deployment" - } - ] - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "barchart", - "version": "", - "spec": { - "options": { - "barRadius": 0, - "barWidth": 0.97, - "fullHighlight": false, - "groupWidth": 0.7, - "legend": { - "displayMode": "list", - "showLegend": false - }, - "orientation": "horizontal", - "showValue": "auto", - "stacking": "none", - "tooltip": { - "mode": "single", - "sort": "none" - }, - "xTickLabelRotation": 0, - "xTickLabelSpacing": 0 - }, - "fieldConfig": { - "defaults": { - "unit": "percentunit", - "min": 0, - "max": 1, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "orange" - }, - { - "value": 1, - "color": "green" - } - ] - }, - "color": { - "mode": "thresholds" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "fillOpacity": 80, - "gradientMode": "scheme", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineWidth": 1, - "scaleDistribution": { - "type": "linear" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "StatefulSet rollout progress", - "description": "### StatefulSet rollout progress\nShows the number of pods for each `StatefulSet` that match the desired configuration, as a proportion of the desired number of pods.\n\nThe rollout will fail if insufficient pods match the desired configuration for any `StatefulSet`.\n\nPods in green match the desired configuration, while pods that do not match the desired configuration are shown in orange.\n\n", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "$datasource" - }, - "spec": { - "expr": "sum by (statefulset) (up{job=\"kube-state-metrics\"})", - "format": "table", - "instant": true, - "legendFormat": "__auto" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "sortBy", - "spec": { - "id": "sortBy", - "options": { - "fields": {}, - "sort": [ - { - "field": "statefulset" - } - ] - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "barchart", - "version": "", - "spec": { - "options": { - "barRadius": 0, - "barWidth": 0.97, - "fullHighlight": false, - "groupWidth": 0.7, - "legend": { - "displayMode": "list", - "showLegend": false - }, - "orientation": "horizontal", - "showValue": "auto", - "stacking": "none", - "tooltip": { - "mode": "single", - "sort": "none" - }, - "xTickLabelRotation": 0, - "xTickLabelSpacing": 0 - }, - "fieldConfig": { - "defaults": { - "unit": "percentunit", - "min": 0, - "max": 1, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "orange" - }, - { - "value": 1, - "color": "green" - } - ] - }, - "color": { - "mode": "thresholds" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "fillOpacity": 80, - "gradientMode": "scheme", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineWidth": 1, - "scaleDistribution": { - "type": "linear" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Aggregator lag", - "description": "### Aggregator lag\nShows the consumption lag of each aggregator pod.\n\nThis panel may show no data if aggregators are not deployed to this cell.\n\nThe rollout will fail if any pod's consumption lag is both:\n* greater than 30s (red area on graph), and\n* trending upwards compared to 1 minute earlier\n\n", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "$datasource" - }, - "spec": { - "expr": "max by (pod) (up{job=\"mimir-aggregator\"})", - "format": "time_series", - "legendFormat": "__auto" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "unit": "s", - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 30, - "color": "red" - } - ] - }, - "noValue": "No data (are aggregators deployed in this cell?)", - "custom": { - "drawStyle": "line", - "fillOpacity": 0, - "lineWidth": 1, - "pointSize": 5, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "area" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Unhealthy Deployment replicas", - "description": "### Unhealthy Deployment replicas\nShows the number of unavailable pods for each `Deployment`.\n\nThe rollout will fail if any `Deployment` has an unavailable pod.\n\nBoth this panel and the rollout check ignore any `Deployment`s that require spot nodes, as these are expected to be unavailable from time to time.\n\n`Deployment`s shown in green do not have any unavailable pods, while `Deployment`s shown in orange have one or more unavailable pods.\n\n", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "$datasource" - }, - "spec": { - "expr": "sum by (deployment) (up{job=\"kube-state-metrics\"})", - "format": "table", - "instant": true, - "legendFormat": "__auto" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "sortBy", - "spec": { - "id": "sortBy", - "options": { - "fields": {}, - "sort": [ - { - "field": "deployment" - } - ] - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "barchart", - "version": "", - "spec": { - "options": { - "barRadius": 0, - "barWidth": 0.97, - "fullHighlight": false, - "groupWidth": 0.7, - "legend": { - "displayMode": "list", - "showLegend": false - }, - "orientation": "horizontal", - "showValue": "auto", - "stacking": "none", - "tooltip": { - "mode": "single", - "sort": "none" - }, - "xTickLabelRotation": 0, - "xTickLabelSpacing": 0 - }, - "fieldConfig": { - "defaults": { - "unit": "", - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 1, - "color": "orange" - } - ] - }, - "color": { - "mode": "thresholds" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 10, - "fillOpacity": 80, - "gradientMode": "scheme", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineWidth": 1, - "scaleDistribution": { - "type": "linear" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Unhealthy StatefulSet replicas", - "description": "### Unhealthy StatefulSet replicas\nShows the number of pods for each `StatefulSet` that are not ready.\n\nThe rollout will fail if any `StatefulSet` has fewer ready pods than requested.\n\nBoth this panel and the rollout check ignore any `StatefulSets`s that require spot nodes, as these are expected to be unavailable from time to time.\n\n`StatefulSets`s shown in green do not have any pods that are not ready, while `StatefulSet`s shown in orange have one or more pods that are not ready.\n\n", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "$datasource" - }, - "spec": { - "expr": "sum by (statefulset) (up{job=\"kube-state-metrics\"})", - "format": "table", - "instant": true, - "legendFormat": "__auto" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "sortBy", - "spec": { - "id": "sortBy", - "options": { - "fields": {}, - "sort": [ - { - "field": "statefulset" - } - ] - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "barchart", - "version": "", - "spec": { - "options": { - "barRadius": 0, - "barWidth": 0.97, - "fullHighlight": false, - "groupWidth": 0.7, - "legend": { - "displayMode": "list", - "showLegend": false - }, - "orientation": "horizontal", - "showValue": "auto", - "stacking": "none", - "tooltip": { - "mode": "single", - "sort": "none" - }, - "xTickLabelRotation": 0, - "xTickLabelSpacing": 0 - }, - "fieldConfig": { - "defaults": { - "unit": "", - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 1, - "color": "orange" - } - ] - }, - "color": { - "mode": "thresholds" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMax": 10, - "fillOpacity": 80, - "gradientMode": "scheme", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineWidth": 1, - "scaleDistribution": { - "type": "linear" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + }, + { + "enable": true, + "expr": "up", + "hide": false, + "iconColor": "rgba(255, 96, 96, 1)", + "name": "rollouts", + "showIn": 0, + "tags": [], + "titleFormat": "Rollout was underway in {{cluster}}/{{namespace}}", + "type": "tags" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "show-in-mimir-links-dropdown" + ], + "targetBlank": false, + "title": "Mimir dashboards", + "tooltip": "", + "type": "dashboards" + } + ], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": -1, + "title": "Rollout progress", + "type": "row" + }, + { + "description": "### Versions running\nShows the versions reported by each running pod.\n\nThe rollout will fail if any pod is not running the expected version.\n\nPods in green are running the expected version, while pods running other versions are shown in orange.\n\n", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "orange", + "mode": "shades" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*(target)/" + }, + "properties": [ { - "kind": "RowsLayoutRow", - "spec": { - "title": "Rollout progress", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 8, - "height": 19, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 8, - "y": 0, - "width": 8, - "height": 19, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 0, - "width": 8, - "height": 19, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Rollout health", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 8, - "height": 19, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 8, - "y": 0, - "width": 8, - "height": 19, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 0, - "width": 8, - "height": 19, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - } - ] - } - } + "id": "color", + "value": { + "fixedColor": "green", + "mode": "fixed" } } ] } - }, - "links": [ - { - "title": "Mimir dashboards", - "type": "dashboards", - "icon": "external link", - "tooltip": "", - "tags": [ - "show-in-mimir-links-dropdown" - ], - "asDropdown": true, - "targetBlank": false, - "includeVars": true, - "keepTime": true - } - ], - "liveNow": false, - "preload": false, - "tags": [ - "mimir", - "betterops-mimir", - "show-in-mimir-links-dropdown", - "as-code" - ], - "timeSettings": { - "timezone": "utc", - "from": "now-1h", - "to": "now", - "autoRefresh": "5m", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Mimir / Rollout debugging", - "variables": [ - { - "kind": "DatasourceVariable", - "spec": { - "name": "datasource", - "pluginId": "prometheus", - "refresh": "onDashboardLoad", - "regex": "", - "current": { - "text": "", - "value": "grafanacloud-prom" - }, - "options": [], - "multi": false, - "includeAll": false, - "label": "Data source", - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "cluster", - "current": { - "text": "prod", - "value": "prod" - }, - "label": "cluster", - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "__legacyStringValue": "label_values(up, job)" - } - }, - "regex": "", - "sort": "alphabeticalAsc", - "options": [], - "multi": false, - "includeAll": true, - "allValue": ".*", - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "namespace", - "current": { - "text": "prod", - "value": "prod" - }, - "label": "namespace", - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "__legacyStringValue": "label_values(up{job=~\"$cluster\"}, instance)" - } - }, - "regex": "", - "sort": "alphabeticalAsc", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - } ] }, - "status": {} + "gridPos": { + "h": 19, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "horizontal", + "showValue": "auto", + "stacking": "percent", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xField": "job\\version", + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "$datasource" + }, + "expr": "sum by (job, version) (up{job=~\".*\"})", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "refId": "A" + } + ], + "title": "Versions running", + "transformations": [ + { + "id": "groupingToMatrix", + "options": { + "columnField": "version", + "rowField": "job", + "valueField": "Value" + } + }, + { + "id": "sortBy", + "options": { + "sort": [ + { + "field": "job\\version" + } + ] + } + } + ], + "type": "barchart" + }, + { + "description": "### Deployment rollout progress\nShows the number of pods for each `Deployment` that match the desired configuration, as a proportion of the desired number of pods.\n\nThe rollout will fail if insufficient pods match the desired configuration for any `Deployment`.\n\nPods in green match the desired configuration, while pods that do not match the desired configuration are shown in orange.\n\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "scheme", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "orange", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "percentunit" + } + }, + "gridPos": { + "h": 19, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 2, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "displayMode": "list", + "showLegend": false + }, + "orientation": "horizontal", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "$datasource" + }, + "expr": "sum by (deployment) (up{job=\"kube-state-metrics\"})", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "refId": "A" + } + ], + "title": "Deployment rollout progress", + "transformations": [ + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "field": "deployment" + } + ] + } + } + ], + "type": "barchart" + }, + { + "description": "### StatefulSet rollout progress\nShows the number of pods for each `StatefulSet` that match the desired configuration, as a proportion of the desired number of pods.\n\nThe rollout will fail if insufficient pods match the desired configuration for any `StatefulSet`.\n\nPods in green match the desired configuration, while pods that do not match the desired configuration are shown in orange.\n\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "scheme", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "orange", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "percentunit" + } + }, + "gridPos": { + "h": 19, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 3, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "displayMode": "list", + "showLegend": false + }, + "orientation": "horizontal", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "$datasource" + }, + "expr": "sum by (statefulset) (up{job=\"kube-state-metrics\"})", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "refId": "A" + } + ], + "title": "StatefulSet rollout progress", + "transformations": [ + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "field": "statefulset" + } + ] + } + } + ], + "type": "barchart" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 19 + }, + "id": -1, + "title": "Rollout health", + "type": "row" + }, + { + "description": "### Aggregator lag\nShows the consumption lag of each aggregator pod.\n\nThis panel may show no data if aggregators are not deployed to this cell.\n\nThe rollout will fail if any pod's consumption lag is both:\n* greater than 30s (red area on graph), and\n* trending upwards compared to 1 minute earlier\n\n", + "fieldConfig": { + "defaults": { + "custom": { + "drawStyle": "line", + "fillOpacity": 0, + "lineWidth": 1, + "pointSize": 5, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "area" + } + }, + "min": 0, + "noValue": "No data (are aggregators deployed in this cell?)", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 30 + } + ] + }, + "unit": "s" + } + }, + "gridPos": { + "h": 19, + "w": 8, + "x": 0, + "y": 19 + }, + "id": 4, + "options": { + "legend": { + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "$datasource" + }, + "expr": "max by (pod) (up{job=\"mimir-aggregator\"})", + "format": "time_series", + "legendFormat": "__auto", + "refId": "A" + } + ], + "title": "Aggregator lag", + "type": "timeseries" + }, + { + "description": "### Unhealthy Deployment replicas\nShows the number of unavailable pods for each `Deployment`.\n\nThe rollout will fail if any `Deployment` has an unavailable pod.\n\nBoth this panel and the rollout check ignore any `Deployment`s that require spot nodes, as these are expected to be unavailable from time to time.\n\n`Deployment`s shown in green do not have any unavailable pods, while `Deployment`s shown in orange have one or more unavailable pods.\n\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 10, + "fillOpacity": 80, + "gradientMode": "scheme", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 1 + } + ] + }, + "unit": "" + } + }, + "gridPos": { + "h": 19, + "w": 8, + "x": 8, + "y": 19 + }, + "id": 5, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "displayMode": "list", + "showLegend": false + }, + "orientation": "horizontal", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "$datasource" + }, + "expr": "sum by (deployment) (up{job=\"kube-state-metrics\"})", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "refId": "A" + } + ], + "title": "Unhealthy Deployment replicas", + "transformations": [ + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "field": "deployment" + } + ] + } + } + ], + "type": "barchart" + }, + { + "description": "### Unhealthy StatefulSet replicas\nShows the number of pods for each `StatefulSet` that are not ready.\n\nThe rollout will fail if any `StatefulSet` has fewer ready pods than requested.\n\nBoth this panel and the rollout check ignore any `StatefulSets`s that require spot nodes, as these are expected to be unavailable from time to time.\n\n`StatefulSets`s shown in green do not have any pods that are not ready, while `StatefulSet`s shown in orange have one or more pods that are not ready.\n\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 10, + "fillOpacity": 80, + "gradientMode": "scheme", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 1 + } + ] + }, + "unit": "" + } + }, + "gridPos": { + "h": 19, + "w": 8, + "x": 16, + "y": 19 + }, + "id": 6, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "displayMode": "list", + "showLegend": false + }, + "orientation": "horizontal", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "$datasource" + }, + "expr": "sum by (statefulset) (up{job=\"kube-state-metrics\"})", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "refId": "A" + } + ], + "title": "Unhealthy StatefulSet replicas", + "transformations": [ + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "field": "statefulset" + } + ] + } + } + ], + "type": "barchart" } + ], + "preload": false, + "refresh": "5m", + "schemaVersion": 42, + "tags": [ + "mimir", + "betterops-mimir", + "show-in-mimir-links-dropdown", + "as-code" + ], + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "grafanacloud-prom" + }, + "hide": 0, + "includeAll": false, + "label": "Data source", + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".*", + "allowCustomValue": true, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": true, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": "label_values(up, job)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "prod", + "value": "prod" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "label": "namespace", + "multi": false, + "name": "namespace", + "options": [], + "query": "label_values(up{job=~\"$cluster\"}, instance)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "utc", + "title": "Mimir / Rollout debugging" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.no-op-migration.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.no-op-migration.v0alpha1.json index df0cc0329de..dd68f978199 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.no-op-migration.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.no-op-migration.v0alpha1.json @@ -4,247 +4,136 @@ "metadata": { "name": "v15.no-op-migration.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + }, + { + "datasource": { + "type": "grafana", + "uid": "grafana" + }, + "enable": true, + "hide": false, + "iconColor": "", + "name": "Annotations \u0026 Alerts" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "CPU Usage", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Memory Usage", + "type": "stat" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "server", + "options": [], + "query": "label_values(server)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V15 No-Op Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v15.no-op-migration.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "grafana" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "", - "name": "Annotations \u0026 Alerts" - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "CPU Usage", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Memory Usage", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V15 No-Op Migration Test Dashboard", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "server", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "__legacyStringValue": "label_values(server)" - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - } - ] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.empty-rows-and-panels-array.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.empty-rows-and-panels-array.v0alpha1.json index e54e0a347d7..3d8d1b11ad3 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.empty-rows-and-panels-array.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.empty-rows-and-panels-array.v0alpha1.json @@ -4,1497 +4,1075 @@ "metadata": { "name": "v16.empty-rows-and-panels-array.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v16.empty-rows-and-panels-array.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "description": "Sample monitoring dashboard for testing purposes.", - "editable": false, - "elements": { - "panel-10": { - "kind": "Panel", - "spec": { - "id": 10, - "title": "Iota primary latency", - "description": "Sample latency metric for primary operations.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "expr": "increase(demo_latency_iota{env=~\"$env\", region=~\"$region\", node=~\"$node\", service=~\"$service\", type=\"primary\"}[$__rate_interval])", - "format": "time_series", - "interval": "1m", - "intervalFactor": 2, - "legendFormat": "{{node}} - {{service}}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "unit": "s", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-11": { - "kind": "Panel", - "spec": { - "id": 11, - "title": "Iota secondary latency", - "description": "Sample latency metric for secondary operations.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "expr": "increase(demo_latency_iota{env=~\"$env\", region=~\"$region\", node=~\"$node\", service=~\"$service\", type=\"secondary\"}[$__rate_interval])", - "format": "time_series", - "interval": "1m", - "intervalFactor": 2, - "legendFormat": "{{node}} - {{service}}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "unit": "s", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-12": { - "kind": "Panel", - "spec": { - "id": 12, - "title": "Kappa expansions", - "description": "Sample expansion events metric.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "expr": "increase(example_events_kappa{env=~\"$env\", region=~\"$region\", node=~\"$node\", service=~\"$service\"}[$__rate_interval])", - "format": "time_series", - "interval": "1m", - "intervalFactor": 2, - "legendFormat": "{{node}} - {{service}}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Alpha metric", - "description": "Sample metric showing connection count.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "expr": "random_metric_alpha{env=~\"$env\", region=~\"$region\", node=~\"$node\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{node}} - {{service}}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 54, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Beta counter", - "description": "Sample counter metric.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "expr": "rate(sample_counter_beta{env=~\"$env\", region=~\"$region\", node=~\"$node\"}[$__rate_interval])", - "format": "time_series", - "interval": "1m", - "intervalFactor": 2, - "legendFormat": "{{node}}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "unit": "ops", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Gamma errors", - "description": "Sample error metric.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "expr": "increase(test_errors_gamma{env=~\"$env\", region=~\"$region\", node=~\"$node\"}[$__rate_interval])", - "format": "time_series", - "interval": "1m", - "intervalFactor": 2, - "legendFormat": "{{node}}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Delta events", - "description": "Sample event rate metric.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "expr": "rate(demo_events_delta{env=~\"$env\", region=~\"$region\", node=~\"$node\"}[$__rate_interval])", - "format": "time_series", - "interval": "1m", - "intervalFactor": 2, - "legendFormat": "{{node}}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Epsilon usage", - "description": "Sample resource utilization metric.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "expr": "example_usage_epsilon{env=~\"$env\", region=~\"$region\", node=~\"$node\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{node}} - {{status}}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "unit": "bytes", - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 51, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineStyle": { - "fill": "solid" - }, - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Zeta and Eta", - "description": "Sample memory allocation metrics.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "expr": "random_total_zeta{env=~\"$env\", region=~\"$region\", node=~\"$node\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{node}} - total" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "expr": "sample_target_eta{env=~\"$env\", region=~\"$region\", node=~\"$node\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{node}} - target" - } - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "unit": "bytes", - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 51, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineStyle": { - "fill": "solid" - }, - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Theta utilization", - "description": "Sample utilization percentage.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "expr": "100 * random_total_zeta{env=~\"$env\", region=~\"$region\", node=~\"$node\"} / clamp_min(test_available_theta{env=~\"$env\", region=~\"$region\", node=~\"$node\"},1)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{node}}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "gauge", - "version": "9.1.7", - "spec": { - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - }, - "color": { - "mode": "thresholds" - } - }, - "overrides": [] - } - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "description": "Sample monitoring dashboard for testing purposes.", + "editable": false, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "sample-monitoring" + ], + "targetBlank": false, + "title": "Related dashboards", + "tooltip": "", + "type": "dashboards", + "url": "" + } + ], + "liveNow": false, + "panels": [ + { + "description": "Sample metric showing connection count.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 54, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 12, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 8, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 12, - "y": 8, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 16, - "width": 24, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 24, - "width": 16, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 24, - "width": 8, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - } - ] - } - } - } + "color": "green", + "value": null }, { - "kind": "RowsLayoutRow", - "spec": { - "title": "Sample section", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-10" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 12, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-11" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 8, - "width": 24, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-12" - } - } - } - ] - } - } - } + "color": "red", + "value": 80 } ] - } - }, - "links": [ - { - "title": "Related dashboards", - "type": "dashboards", - "icon": "external link", - "tooltip": "", - "url": "", - "tags": [ - "sample-monitoring" - ], - "asDropdown": false, - "targetBlank": false, - "includeVars": true, - "keepTime": true - } - ], - "liveNow": false, - "preload": false, - "tags": [ - "sample-monitoring" - ], - "timeSettings": { - "timezone": "default", - "from": "now-30m", - "to": "now", - "autoRefresh": "30s", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Sample dashboard", - "variables": [ - { - "kind": "DatasourceVariable", - "spec": { - "name": "example_datasource", - "pluginId": "sample_source", - "refresh": "onDashboardLoad", - "regex": "", - "current": { - "text": "", - "value": "" - }, - "options": [], - "multi": false, - "includeAll": false, - "label": "Data Source", - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } }, - { - "kind": "QueryVariable", - "spec": { - "name": "env", - "current": { - "text": "", - "value": "" - }, - "label": "Environment", - "hide": "dontHide", - "refresh": "onTimeRangeChanged", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "__legacyStringValue": "label_values(system_info_lambda{}, env)" - } - }, - "regex": "", - "sort": "alphabeticalDesc", - "options": [], - "multi": true, - "includeAll": true, - "allValue": ".+", - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "region", - "current": { - "text": "", - "value": "" - }, - "label": "Region", - "hide": "dontHide", - "refresh": "onTimeRangeChanged", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "__legacyStringValue": "label_values(system_info_lambda{env=~\"$env\"}, region)" - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": true, - "includeAll": true, - "allValue": ".*", - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "node", - "current": { - "text": "", - "value": "" - }, - "label": "Node", - "hide": "dontHide", - "refresh": "onTimeRangeChanged", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "__legacyStringValue": "label_values(system_info_lambda{env=~\"$env\", region=~\"$region\"}, node)" - } - }, - "regex": "", - "sort": "alphabeticalDesc", - "options": [], - "multi": true, - "includeAll": true, - "allValue": ".+", - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "service", - "current": { - "text": "", - "value": "" - }, - "label": "Service", - "hide": "dontHide", - "refresh": "onTimeRangeChanged", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "datasource": { - "name": "${example_datasource}" - }, - "spec": { - "__legacyStringValue": "label_values(example_events_kappa{env=~\"$env\", region=~\"$region\", node=~\"$node\"}, service)" - } - }, - "regex": "", - "sort": "alphabeticalDesc", - "options": [], - "multi": true, - "includeAll": true, - "allValue": ".+", - "allowCustomValue": true - } - } - ] + "unit": "short" + } }, - "status": {} + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "expr": "random_metric_alpha{env=~\"$env\", region=~\"$region\", node=~\"$node\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{node}} - {{service}}", + "refId": "A" + } + ], + "title": "Alpha metric", + "type": "timeseries" + }, + { + "description": "Sample counter metric.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ops" + } + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "expr": "rate(sample_counter_beta{env=~\"$env\", region=~\"$region\", node=~\"$node\"}[$__rate_interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 2, + "legendFormat": "{{node}}", + "refId": "A" + } + ], + "title": "Beta counter", + "type": "timeseries" + }, + { + "description": "Sample error metric.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + } + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "expr": "increase(test_errors_gamma{env=~\"$env\", region=~\"$region\", node=~\"$node\"}[$__rate_interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 2, + "legendFormat": "{{node}}", + "refId": "A" + } + ], + "title": "Gamma errors", + "type": "timeseries" + }, + { + "description": "Sample event rate metric.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + } + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "expr": "rate(demo_events_delta{env=~\"$env\", region=~\"$region\", node=~\"$node\"}[$__rate_interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 2, + "legendFormat": "{{node}}", + "refId": "A" + } + ], + "title": "Delta events", + "type": "timeseries" + }, + { + "description": "Sample resource utilization metric.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 51, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + } + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "expr": "example_usage_epsilon{env=~\"$env\", region=~\"$region\", node=~\"$node\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{node}} - {{status}}", + "refId": "A" + } + ], + "title": "Epsilon usage", + "type": "timeseries" + }, + { + "description": "Sample memory allocation metrics.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 51, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + } + }, + "gridPos": { + "h": 8, + "w": 16, + "x": 0, + "y": 24 + }, + "id": 7, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "expr": "random_total_zeta{env=~\"$env\", region=~\"$region\", node=~\"$node\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{node}} - total", + "refId": "A" + }, + { + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "expr": "sample_target_eta{env=~\"$env\", region=~\"$region\", node=~\"$node\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{node}} - target", + "refId": "B" + } + ], + "title": "Zeta and Eta", + "type": "timeseries" + }, + { + "description": "Sample utilization percentage.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "percent" + } + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 24 + }, + "id": 8, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.1.7", + "targets": [ + { + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "expr": "100 * random_total_zeta{env=~\"$env\", region=~\"$region\", node=~\"$node\"} / clamp_min(test_available_theta{env=~\"$env\", region=~\"$region\", node=~\"$node\"},1)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{node}}", + "refId": "A" + } + ], + "title": "Theta utilization", + "type": "gauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 32 + }, + "id": -1, + "title": "Sample section", + "type": "row" + }, + { + "description": "Sample latency metric for primary operations.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "s" + } + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "expr": "increase(demo_latency_iota{env=~\"$env\", region=~\"$region\", node=~\"$node\", service=~\"$service\", type=\"primary\"}[$__rate_interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 2, + "legendFormat": "{{node}} - {{service}}", + "refId": "A" + } + ], + "title": "Iota primary latency", + "type": "timeseries" + }, + { + "description": "Sample latency metric for secondary operations.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "s" + } + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "expr": "increase(demo_latency_iota{env=~\"$env\", region=~\"$region\", node=~\"$node\", service=~\"$service\", type=\"secondary\"}[$__rate_interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 2, + "legendFormat": "{{node}} - {{service}}", + "refId": "A" + } + ], + "title": "Iota secondary latency", + "type": "timeseries" + }, + { + "description": "Sample expansion events metric.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + } + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "expr": "increase(example_events_kappa{env=~\"$env\", region=~\"$region\", node=~\"$node\", service=~\"$service\"}[$__rate_interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 2, + "legendFormat": "{{node}} - {{service}}", + "refId": "A" + } + ], + "title": "Kappa expansions", + "type": "timeseries" } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 42, + "tags": [ + "sample-monitoring" + ], + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "hide": 0, + "includeAll": false, + "label": "Data Source", + "multi": false, + "name": "example_datasource", + "options": [], + "query": "sample_source", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".+", + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "hide": 0, + "includeAll": true, + "label": "Environment", + "multi": true, + "name": "env", + "options": [], + "query": "label_values(system_info_lambda{}, env)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 2, + "type": "query" + }, + { + "allValue": ".*", + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "hide": 0, + "includeAll": true, + "label": "Region", + "multi": true, + "name": "region", + "options": [], + "query": "label_values(system_info_lambda{env=~\"$env\"}, region)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allValue": ".+", + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "hide": 0, + "includeAll": true, + "label": "Node", + "multi": true, + "name": "node", + "options": [], + "query": "label_values(system_info_lambda{env=~\"$env\", region=~\"$region\"}, node)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 2, + "type": "query" + }, + { + "allValue": ".+", + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "", + "uid": "${example_datasource}" + }, + "hide": 0, + "includeAll": true, + "label": "Service", + "multi": true, + "name": "service", + "options": [], + "query": "label_values(example_events_kappa{env=~\"$env\", region=~\"$region\", node=~\"$node\"}, service)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 2, + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "default", + "title": "Sample dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.grid_layout_upgrade.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.grid_layout_upgrade.v0alpha1.json index cdeac70de04..286cc75e2c0 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.grid_layout_upgrade.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.grid_layout_upgrade.v0alpha1.json @@ -4,755 +4,338 @@ "metadata": { "name": "v16.grid_layout_upgrade.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": -1, + "title": "", + "type": "row" + }, + { + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "CPU Usage", + "type": "timeseries" + }, + { + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Memory Usage", + "type": "stat" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": -1, + "panels": [ + { + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Process List", + "type": "table" + }, + { + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Network I/O", + "type": "timeseries" + }, + { + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Disk I/O", + "type": "timeseries" + } + ], + "title": "Collapsed Row", + "type": "row" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 8 + }, + "id": -1, + "title": "Visible Row Title", + "type": "row" + }, + { + "gridPos": { + "h": 6, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Temperature", + "type": "gauge" + }, + { + "gridPos": { + "h": 6, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 7, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Uptime", + "type": "stat" + }, + { + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Load Average", + "type": "bargauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 14 + }, + "id": -1, + "title": "", + "type": "row" + }, + { + "gridPos": { + "h": 4, + "w": 16, + "x": 0, + "y": 14 + }, + "id": 9, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Description Panel", + "type": "text" + }, + { + "gridPos": { + "h": 3, + "w": 8, + "x": 16, + "y": 14 + }, + "id": 10, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "System Logs", + "type": "logs" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 18 + }, + "id": -1, + "repeat": "server", + "title": "", + "type": "row" + }, + { + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 11, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Server Metrics", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V16 Grid Layout Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v16.grid_layout_upgrade.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "CPU Usage", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-10": { - "kind": "Panel", - "spec": { - "id": 10, - "title": "System Logs", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "logs", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-11": { - "kind": "Panel", - "spec": { - "id": 11, - "title": "Server Metrics", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Memory Usage", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Process List", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Network I/O", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Disk I/O", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Temperature", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "gauge", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Uptime", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Load Average", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "bargauge", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-9": { - "kind": "Panel", - "spec": { - "id": 9, - "title": "Description Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 12, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 12, - "y": 0, - "width": 12, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Collapsed Row", - "collapse": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 24, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 8, - "width": 12, - "height": 6, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 12, - "y": 8, - "width": 12, - "height": 6, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Visible Row Title", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 8, - "height": 6, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 8, - "y": 0, - "width": 8, - "height": 6, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 0, - "width": 8, - "height": 6, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 16, - "height": 4, - "element": { - "kind": "ElementReference", - "name": "panel-9" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 0, - "width": 8, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-10" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "repeat": { - "mode": "variable", - "value": "server" - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 24, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-11" - } - } - } - ] - } - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V16 Grid Layout Migration Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.span_zero_demo.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.span_zero_demo.v0alpha1.json index d4bd349e923..a57a713ba61 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.span_zero_demo.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.span_zero_demo.v0alpha1.json @@ -4,1723 +4,854 @@ "metadata": { "name": "v16.span_zero_demo.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v16.span_zero_demo.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": false, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Application Monitoring", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "", - "spec": { - "options": { - "content": "This dashboard demonstrates various monitoring components for application observability and performance metrics.\n", - "mode": "markdown" - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-10": { - "kind": "Panel", - "spec": { - "id": 10, - "title": "All", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "loki", - "version": "v0", - "datasource": { - "name": "${loki}" - }, - "spec": { - "expr": "{namespace=\"default\", cluster=\"$cluster\", job=\"app-service\"} | logfmt" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "logs", - "version": "", - "spec": { - "options": { - "enableLogDetails": true, - "showTime": false, - "sortOrder": "Descending", - "wrapLogMessage": true - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-11": { - "kind": "Panel", - "spec": { - "id": 11, - "title": "Performance Analysis", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "", - "spec": { - "options": { - "content": "Performance monitoring examines factors that affect system response times, including operation duration, queue lengths, and processing delays. This section provides metrics and traces for performance analysis.\n", - "mode": "markdown" - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-12": { - "kind": "Panel", - "spec": { - "id": 12, - "title": "Concurrent Job Drivers", - "description": "Number of concurrent processing threads available for handling operations", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "max(app_worker_threads_active{cluster=\"$cluster\", namespace=\"default\"})", - "instant": true - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-13": { - "kind": "Panel", - "spec": { - "id": 13, - "title": "Recent Operation Traces", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "tempo", - "version": "v0", - "datasource": { - "name": "${tempo}" - }, - "spec": { - "filters": [ - { - "id": "span-name", - "operator": "=", - "scope": "span", - "tag": "name", - "value": [ - "provisioning.sync.process" - ] - }, - { - "id": "k8s-cluster-name", - "operator": "=", - "scope": "resource", - "tag": "k8s.cluster.name", - "value": [ - "$cluster" - ] - } - ], - "query": "{name=\"app.operation.process\"}", - "queryType": "traceqlSearch" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-14": { - "kind": "Panel", - "spec": { - "id": 14, - "title": "7d avg of job durations", - "description": "Histogram showing p99, p95, p50, and p10 percentiles for job processing duration based on number of resources changed", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "histogram_quantile(0.99, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (le, resources_changed_bucket, action)) and on(resources_changed_bucket, action) sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (resources_changed_bucket, action) \u003e 0", - "legendFormat": "{{action}} q0.99 - size {{resources_changed_bucket}}" - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "histogram_quantile(0.9, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (le, resources_changed_bucket, action)) and on(resources_changed_bucket, action) sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (resources_changed_bucket, action) \u003e 0", - "legendFormat": "{{action}} q0.95 - size {{resources_changed_bucket}}" - } - }, - "refId": "C", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "histogram_quantile(0.5, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (le, resources_changed_bucket, action)) and on(resources_changed_bucket, action) sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (resources_changed_bucket, action) \u003e 0", - "legendFormat": "{{action}} q0.5 - size {{resources_changed_bucket}}" - } - }, - "refId": "D", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "histogram_quantile(0.1, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (le, resources_changed_bucket, action)) and on(resources_changed_bucket, action) sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (resources_changed_bucket, action) \u003e 0", - "legendFormat": "{{action}} q0.1 - size {{resources_changed_bucket}}" - } - }, - "refId": "E", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "reduce", - "spec": { - "id": "reduce", - "options": { - "mode": "seriesToRows", - "reducers": [ - "mean" - ] - } - } - }, - { - "kind": "seriesToRows", - "spec": { - "id": "seriesToRows", - "options": null - } - }, - { - "kind": "organize", - "spec": { - "id": "organize", - "options": { - "renameByName": { - "Field": "Type", - "Mean": "Avg Duration", - "Metric": "Legend", - "Value": "Duration" - } - } - } - } - ], - "queryOptions": { - "timeFrom": "7d" - } - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "unit": "s", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 2, - "color": "yellow" - }, - { - "value": 5, - "color": "red" - } - ] - } - }, - "overrides": [] - } - } - } - } - }, - "panel-15": { - "kind": "Panel", - "spec": { - "id": 15, - "title": "Job Duration", - "description": "Histogram showing p99, p95, p50, and p10 percentiles for job processing duration based on number of resources changed", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "histogram_quantile(0.99, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[5m])) by (le, resources_changed_bucket, action))", - "legendFormat": "{{action}} q0.99 - size {{resources_changed_bucket}}" - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "histogram_quantile(0.95, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[5m])) by (le, resources_changed_bucket, action))", - "legendFormat": "{{action}} q0.95 - size {{resources_changed_bucket}}" - } - }, - "refId": "C", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "histogram_quantile(0.5, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[5m])) by (le, resources_changed_bucket, action))", - "legendFormat": "{{action}} q0.5 - size {{resources_changed_bucket}}" - } - }, - "refId": "D", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "histogram_quantile(0.1, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[5m])) by (le, resources_changed_bucket, action))", - "legendFormat": "{{action}} q0.1 - size {{resources_changed_bucket}}" - } - }, - "refId": "E", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-16": { - "kind": "Panel", - "spec": { - "id": 16, - "title": "Queue Size", - "description": "Total number of jobs waiting to be processed", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "clamp_min(sum(app_operation_queue_size{cluster=\"$cluster\", namespace=\"default\"}), 0)", - "legendFormat": "Queue size" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-17": { - "kind": "Panel", - "spec": { - "id": 17, - "title": "7d avg Queue Wait Time", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "avg(histogram_quantile(0.5, sum(rate(app_operation_queue_wait_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (le)))", - "legendFormat": "Queue size" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": { - "timeFrom": "7d" - } - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "unit": "s" - }, - "overrides": [] - } - } - } - } - }, - "panel-18": { - "kind": "Panel", - "spec": { - "id": 18, - "title": "Queue Wait Time", - "description": "How long a job is in the queue before being picked up", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "histogram_quantile(0.99, sum(rate(app_operation_queue_wait_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[$__rate_interval])) by (le))", - "legendFormat": "q0.99" - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "histogram_quantile(0.95, sum(rate(app_operation_queue_wait_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[$__rate_interval])) by (le))", - "legendFormat": "q0.95" - } - }, - "refId": "C", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "histogram_quantile(0.5, sum(rate(app_operation_queue_wait_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[$__rate_interval])) by (le))", - "legendFormat": "q0.5" - } - }, - "refId": "D", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "histogram_quantile(0.1, sum(rate(app_operation_queue_wait_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[$__rate_interval])) by (le))", - "legendFormat": "q0.1" - } - }, - "refId": "E", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-19": { - "kind": "Panel", - "spec": { - "id": 19, - "title": "Resource Monitoring", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "", - "spec": { - "options": { - "content": "Resource utilization monitoring for application containers", - "mode": "markdown" - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-20": { - "kind": "Panel", - "spec": { - "id": 20, - "title": "Running Pod(s)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "count by (cluster, channel)(label_replace(label_replace(kube_pod_container_info{namespace=\"default\", container=\"app-worker\", pod=~\"app-worker.*\", cluster=~\"$cluster\"}, \"version\", \"$1\", \"image\", \".+:(.+)\"), \"channel\", \"$1\", \"container\", \".+-(.+)\"))", - "legendFormat": "{{cluster}}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-21": { - "kind": "Panel", - "spec": { - "id": 21, - "title": "Memory Utilization", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "max(kube_pod_container_resource_requests{namespace=\"default\", resource=\"memory\", cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker.*\"})", - "legendFormat": "Memory Request" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "max(kube_pod_container_resource_limits{namespace=\"default\", resource=\"memory\", cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker.*\"})", - "legendFormat": "Memory Limit" - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "max(container_memory_usage_bytes{namespace=\"default\",cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker.*\"}) by (pod)", - "legendFormat": "Container usage {{pod}}" - } - }, - "refId": "C", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-22": { - "kind": "Panel", - "spec": { - "id": 22, - "title": "CPU Utilization", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "sum(irate(container_cpu_usage_seconds_total{namespace=\"default\", cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker-.*\"}[$__rate_interval])) by (pod, container, cpu)", - "legendFormat": "Usage {{pod}}" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "sum(irate(container_cpu_cfs_throttled_seconds_total{namespace=\"default\", cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker-.*\"}[$__rate_interval])) by (pod, container)", - "legendFormat": "Throttling {{pod}}" - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "max(kube_pod_container_resource_limits{namespace=\"default\", cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker-.*\", resource=\"cpu\"})", - "legendFormat": "CPU limit" - } - }, - "refId": "C", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "max(kube_pod_container_resource_requests{namespace=\"default\", cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker-.*\", resource=\"cpu\"})", - "legendFormat": "CPU request" - } - }, - "refId": "D", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Service Overview", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "", - "spec": { - "options": { - "content": "This service handles background processing tasks for the application system. It manages various types of operations including data synchronization, resource management, and batch processing.\n\nSupported operation types:\n1. Sync: Synchronizes data between different systems\n2. Process: Handles batch data processing tasks\n3. Cleanup: Removes outdated or temporary resources\n4. Update: Applies configuration changes across services\n\nService dependencies:\n- Data API: For reading and writing application data\n- Configuration Service: For managing system settings\n- Queue Service: For handling task scheduling\n- Storage Service: For persistent data management\n- Auth Service: For authentication and authorization\n- Metrics Service: For collecting operational statistics\n", - "mode": "markdown" - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Error Monitoring", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "", - "spec": { - "options": { - "content": "Error monitoring helps identify issues in the system. This section displays error logs and success rates for operations.", - "mode": "markdown" - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Job Success Rate", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "expr": "sum by (action) (app_jobs_processed_total{outcome=\"success\", cluster=\"$cluster\", namespace=\"default\"})\n/\nsum by (action) (app_jobs_processed_total{cluster=\"$cluster\", namespace=\"default\"})\n", - "legendFormat": "{{action}}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "unit": "percentunit", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "red" - }, - { - "value": 0.95, - "color": "yellow" - }, - { - "value": 1, - "color": "green" - } - ] - } - }, - "overrides": [] - } - } - } - } - }, - "panel-9": { - "kind": "Panel", - "spec": { - "id": 9, - "title": "Errors", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "loki", - "version": "v0", - "datasource": { - "name": "${loki}" - }, - "spec": { - "expr": "{namespace=\"default\", cluster=\"$cluster\", job=\"app-service\"} | logfmt | level=\"error\"" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "logs", - "version": "", - "spec": { - "options": { - "enableLogDetails": true, - "showTime": false, - "sortOrder": "Descending", - "wrapLogMessage": true - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": false, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": true, + "title": "External Documentation", + "tooltip": "", + "type": "link", + "url": "https://example.com/docs" + } + ], + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "content": "This dashboard demonstrates various monitoring components for application observability and performance metrics.\n", + "mode": "markdown" + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Application Monitoring", + "type": "text" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": -1, + "title": "Application Service", + "type": "row" + }, + { + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 3 + }, + "id": 6, + "options": { + "content": "This service handles background processing tasks for the application system. It manages various types of operations including data synchronization, resource management, and batch processing.\n\nSupported operation types:\n1. Sync: Synchronizes data between different systems\n2. Process: Handles batch data processing tasks\n3. Cleanup: Removes outdated or temporary resources\n4. Update: Applies configuration changes across services\n\nService dependencies:\n- Data API: For reading and writing application data\n- Configuration Service: For managing system settings\n- Queue Service: For handling task scheduling\n- Storage Service: For persistent data management\n- Auth Service: For authentication and authorization\n- Metrics Service: For collecting operational statistics\n", + "mode": "markdown" + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Service Overview", + "type": "text" + }, + { + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 3 + }, + "id": 7, + "options": { + "content": "Error monitoring helps identify issues in the system. This section displays error logs and success rates for operations.", + "mode": "markdown" + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Error Monitoring", + "type": "text" + }, + { + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 24, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - } - ] - } - } - } + "color": "red", + "value": 0 }, { - "kind": "RowsLayoutRow", - "spec": { - "title": "Application Service", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 8, - "y": 0, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 0, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 7, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-9" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 8, - "y": 7, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-10" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 7, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-11" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 14, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-12" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 8, - "y": 14, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-13" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 14, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-14" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 21, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-15" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 8, - "y": 21, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-16" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 21, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-17" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 28, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-18" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 8, - "y": 28, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-19" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 28, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-20" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 35, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-21" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 8, - "y": 35, - "width": 8, - "height": 7, - "element": { - "kind": "ElementReference", - "name": "panel-22" - } - } - } - ] - } - } - } + "color": "yellow", + "value": 0.95 + }, + { + "color": "green", + "value": 1 } ] + }, + "unit": "percentunit" + } + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 3 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "sum by (action) (app_jobs_processed_total{outcome=\"success\", cluster=\"$cluster\", namespace=\"default\"})\n/\nsum by (action) (app_jobs_processed_total{cluster=\"$cluster\", namespace=\"default\"})\n", + "legendFormat": "{{action}}", + "refId": "A" + } + ], + "title": "Job Success Rate", + "type": "stat" + }, + { + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 10 + }, + "id": 9, + "options": { + "enableLogDetails": true, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": true + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "${loki}" + }, + "expr": "{namespace=\"default\", cluster=\"$cluster\", job=\"app-service\"} | logfmt | level=\"error\"", + "refId": "A" + } + ], + "title": "Errors", + "type": "logs" + }, + { + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 10 + }, + "id": 10, + "options": { + "enableLogDetails": true, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": true + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "${loki}" + }, + "expr": "{namespace=\"default\", cluster=\"$cluster\", job=\"app-service\"} | logfmt", + "refId": "A" + } + ], + "title": "All", + "type": "logs" + }, + { + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 10 + }, + "id": 11, + "options": { + "content": "Performance monitoring examines factors that affect system response times, including operation duration, queue lengths, and processing delays. This section provides metrics and traces for performance analysis.\n", + "mode": "markdown" + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Performance Analysis", + "type": "text" + }, + { + "description": "Number of concurrent processing threads available for handling operations", + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 17 + }, + "id": 12, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "max(app_worker_threads_active{cluster=\"$cluster\", namespace=\"default\"})", + "instant": true, + "refId": "A" + } + ], + "title": "Concurrent Job Drivers", + "type": "stat" + }, + { + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 17 + }, + "id": 13, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "tempo", + "uid": "${tempo}" + }, + "filters": [ + { + "id": "span-name", + "operator": "=", + "scope": "span", + "tag": "name", + "value": [ + "provisioning.sync.process" + ] + }, + { + "id": "k8s-cluster-name", + "operator": "=", + "scope": "resource", + "tag": "k8s.cluster.name", + "value": [ + "$cluster" + ] + } + ], + "query": "{name=\"app.operation.process\"}", + "queryType": "traceqlSearch", + "refId": "A" + } + ], + "title": "Recent Operation Traces", + "type": "table" + }, + { + "description": "Histogram showing p99, p95, p50, and p10 percentiles for job processing duration based on number of resources changed", + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "yellow", + "value": 2 + }, + { + "color": "red", + "value": 5 + } + ] + }, + "unit": "s" + } + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 17 + }, + "id": 14, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "histogram_quantile(0.99, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (le, resources_changed_bucket, action)) and on(resources_changed_bucket, action) sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (resources_changed_bucket, action) \u003e 0", + "legendFormat": "{{action}} q0.99 - size {{resources_changed_bucket}}", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "histogram_quantile(0.9, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (le, resources_changed_bucket, action)) and on(resources_changed_bucket, action) sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (resources_changed_bucket, action) \u003e 0", + "legendFormat": "{{action}} q0.95 - size {{resources_changed_bucket}}", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "histogram_quantile(0.5, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (le, resources_changed_bucket, action)) and on(resources_changed_bucket, action) sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (resources_changed_bucket, action) \u003e 0", + "legendFormat": "{{action}} q0.5 - size {{resources_changed_bucket}}", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "histogram_quantile(0.1, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (le, resources_changed_bucket, action)) and on(resources_changed_bucket, action) sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (resources_changed_bucket, action) \u003e 0", + "legendFormat": "{{action}} q0.1 - size {{resources_changed_bucket}}", + "refId": "E" + } + ], + "timeFrom": "7d", + "title": "7d avg of job durations", + "transformations": [ + { + "id": "reduce", + "options": { + "mode": "seriesToRows", + "reducers": [ + "mean" + ] } }, - "links": [ - { - "title": "External Documentation", - "type": "link", - "icon": "external link", - "tooltip": "", - "url": "https://example.com/docs", - "tags": [], - "asDropdown": false, - "targetBlank": true, - "includeVars": false, - "keepTime": false - } - ], - "liveNow": false, - "preload": false, - "tags": [ - "as-code" - ], - "timeSettings": { - "timezone": "utc", - "from": "now-6h", - "to": "now", - "autoRefresh": "10s", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 + { + "id": "seriesToRows", + "options": null }, - "title": "Span Zero Demo Dashboard", - "variables": [ - { - "kind": "DatasourceVariable", - "spec": { - "name": "datasource", - "pluginId": "prometheus", - "refresh": "onDashboardLoad", - "regex": "", - "current": { - "text": "", - "value": "prometheus-datasource" - }, - "options": [], - "multi": false, - "includeAll": false, - "label": "Data source", - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "DatasourceVariable", - "spec": { - "name": "prom", - "pluginId": "prometheus", - "refresh": "onDashboardLoad", - "regex": "", - "current": { - "text": "", - "value": "prometheus-datasource" - }, - "options": [], - "multi": false, - "includeAll": false, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "DatasourceVariable", - "spec": { - "name": "loki", - "pluginId": "loki", - "refresh": "onDashboardLoad", - "regex": "", - "current": { - "text": "", - "value": "loki-datasource" - }, - "options": [], - "multi": false, - "includeAll": false, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "DatasourceVariable", - "spec": { - "name": "tempo", - "pluginId": "tempo", - "refresh": "onDashboardLoad", - "regex": ".*tempo.*", - "current": { - "text": "tempo-datasource", - "value": "tempo-datasource" - }, - "options": [], - "multi": false, - "includeAll": false, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "cluster", - "current": { - "text": "demo-cluster", - "value": "demo-cluster" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "${prom}" - }, - "spec": { - "__legacyStringValue": "label_values(app_worker_threads_active,cluster)" - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true + { + "id": "organize", + "options": { + "renameByName": { + "Field": "Type", + "Mean": "Avg Duration", + "Metric": "Legend", + "Value": "Duration" } } - ] + } + ], + "type": "table" + }, + { + "description": "Histogram showing p99, p95, p50, and p10 percentiles for job processing duration based on number of resources changed", + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 24 }, - "status": {} + "id": 15, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "histogram_quantile(0.99, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[5m])) by (le, resources_changed_bucket, action))", + "legendFormat": "{{action}} q0.99 - size {{resources_changed_bucket}}", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "histogram_quantile(0.95, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[5m])) by (le, resources_changed_bucket, action))", + "legendFormat": "{{action}} q0.95 - size {{resources_changed_bucket}}", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "histogram_quantile(0.5, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[5m])) by (le, resources_changed_bucket, action))", + "legendFormat": "{{action}} q0.5 - size {{resources_changed_bucket}}", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "histogram_quantile(0.1, sum(rate(app_operation_duration_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[5m])) by (le, resources_changed_bucket, action))", + "legendFormat": "{{action}} q0.1 - size {{resources_changed_bucket}}", + "refId": "E" + } + ], + "title": "Job Duration", + "type": "timeseries" + }, + { + "description": "Total number of jobs waiting to be processed", + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 24 + }, + "id": 16, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "clamp_min(sum(app_operation_queue_size{cluster=\"$cluster\", namespace=\"default\"}), 0)", + "legendFormat": "Queue size", + "refId": "A" + } + ], + "title": "Queue Size", + "type": "stat" + }, + { + "fieldConfig": { + "defaults": { + "unit": "s" + } + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 24 + }, + "id": 17, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "avg(histogram_quantile(0.5, sum(rate(app_operation_queue_wait_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[7d])) by (le)))", + "legendFormat": "Queue size", + "refId": "A" + } + ], + "timeFrom": "7d", + "title": "7d avg Queue Wait Time", + "type": "stat" + }, + { + "description": "How long a job is in the queue before being picked up", + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 31 + }, + "id": 18, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "histogram_quantile(0.99, sum(rate(app_operation_queue_wait_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[$__rate_interval])) by (le))", + "legendFormat": "q0.99", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "histogram_quantile(0.95, sum(rate(app_operation_queue_wait_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[$__rate_interval])) by (le))", + "legendFormat": "q0.95", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "histogram_quantile(0.5, sum(rate(app_operation_queue_wait_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[$__rate_interval])) by (le))", + "legendFormat": "q0.5", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "histogram_quantile(0.1, sum(rate(app_operation_queue_wait_seconds_bucket{cluster=\"$cluster\", namespace=\"default\"}[$__rate_interval])) by (le))", + "legendFormat": "q0.1", + "refId": "E" + } + ], + "title": "Queue Wait Time", + "type": "timeseries" + }, + { + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 31 + }, + "id": 19, + "options": { + "content": "Resource utilization monitoring for application containers", + "mode": "markdown" + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Resource Monitoring", + "type": "text" + }, + { + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 31 + }, + "id": 20, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "count by (cluster, channel)(label_replace(label_replace(kube_pod_container_info{namespace=\"default\", container=\"app-worker\", pod=~\"app-worker.*\", cluster=~\"$cluster\"}, \"version\", \"$1\", \"image\", \".+:(.+)\"), \"channel\", \"$1\", \"container\", \".+-(.+)\"))", + "legendFormat": "{{cluster}}", + "refId": "A" + } + ], + "title": "Running Pod(s)", + "type": "timeseries" + }, + { + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 38 + }, + "id": 21, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "max(kube_pod_container_resource_requests{namespace=\"default\", resource=\"memory\", cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker.*\"})", + "legendFormat": "Memory Request", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "max(kube_pod_container_resource_limits{namespace=\"default\", resource=\"memory\", cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker.*\"})", + "legendFormat": "Memory Limit", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "max(container_memory_usage_bytes{namespace=\"default\",cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker.*\"}) by (pod)", + "legendFormat": "Container usage {{pod}}", + "refId": "C" + } + ], + "title": "Memory Utilization", + "type": "timeseries" + }, + { + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 38 + }, + "id": 22, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "sum(irate(container_cpu_usage_seconds_total{namespace=\"default\", cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker-.*\"}[$__rate_interval])) by (pod, container, cpu)", + "legendFormat": "Usage {{pod}}", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "sum(irate(container_cpu_cfs_throttled_seconds_total{namespace=\"default\", cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker-.*\"}[$__rate_interval])) by (pod, container)", + "legendFormat": "Throttling {{pod}}", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "max(kube_pod_container_resource_limits{namespace=\"default\", cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker-.*\", resource=\"cpu\"})", + "legendFormat": "CPU limit", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "expr": "max(kube_pod_container_resource_requests{namespace=\"default\", cluster=~\"$cluster\", container=\"app-worker\", pod=~\"app-worker-.*\", resource=\"cpu\"})", + "legendFormat": "CPU request", + "refId": "D" + } + ], + "title": "CPU Utilization", + "type": "timeseries" } + ], + "preload": false, + "refresh": "10s", + "schemaVersion": 42, + "tags": [ + "as-code" + ], + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "prometheus-datasource" + }, + "hide": 0, + "includeAll": false, + "label": "Data source", + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "prometheus-datasource" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "prom", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "loki-datasource" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "loki", + "options": [], + "query": "loki", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allowCustomValue": true, + "current": { + "text": "tempo-datasource", + "value": "tempo-datasource" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "tempo", + "options": [], + "query": "tempo", + "refresh": 1, + "regex": ".*tempo.*", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allowCustomValue": true, + "current": { + "text": "demo-cluster", + "value": "demo-cluster" + }, + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "cluster", + "options": [], + "query": "label_values(app_worker_threads_active,cluster)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "utc", + "title": "Span Zero Demo Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v17.minspan_to_maxperrow.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v17.minspan_to_maxperrow.v0alpha1.json index 1eb62dfe79b..e169d2bfa64 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v17.minspan_to_maxperrow.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v17.minspan_to_maxperrow.v0alpha1.json @@ -4,673 +4,277 @@ "metadata": { "name": "v17.minspan_to_maxperrow.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with minSpan 8", + "type": "timeseries" + }, + { + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with minSpan 12", + "type": "timeseries" + }, + { + "gridPos": { + "h": 4, + "w": 6, + "x": 0, + "y": 8 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with minSpan 4", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 4, + "x": 6, + "y": 8 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with minSpan 1", + "type": "stat" + }, + { + "gridPos": { + "h": 6, + "w": 8, + "x": 12, + "y": 8 + }, + "id": 7, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel without minSpan", + "type": "timeseries" + }, + { + "gridPos": { + "h": 4, + "w": 6, + "x": 18, + "y": 8 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with invalid minSpan", + "type": "text" + }, + { + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with minSpan 2", + "type": "table" + }, + { + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with minSpan 24", + "type": "gauge" + }, + { + "gridPos": { + "h": 4, + "w": 6, + "x": 0, + "y": 22 + }, + "id": 9, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with zero minSpan", + "type": "timeseries" + }, + { + "gridPos": { + "h": 4, + "w": 6, + "x": 6, + "y": 22 + }, + "id": 10, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with negative minSpan", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V17 MinSpan to MaxPerRow Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v17.minspan_to_maxperrow.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with minSpan 8", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-10": { - "kind": "Panel", - "spec": { - "id": 10, - "title": "Panel with negative minSpan", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Panel with minSpan 4", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel with minSpan 2", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel with minSpan 12", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Panel with minSpan 24", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "gauge", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Panel with minSpan 1", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Panel without minSpan", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Panel with invalid minSpan", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-9": { - "kind": "Panel", - "spec": { - "id": 9, - "title": "Panel with zero minSpan", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 12, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 8, - "width": 6, - "height": 4, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 6, - "y": 8, - "width": 4, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 12, - "y": 8, - "width": 8, - "height": 6, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 18, - "y": 8, - "width": 6, - "height": 4, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 12, - "width": 24, - "height": 6, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 18, - "width": 24, - "height": 4, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 22, - "width": 6, - "height": 4, - "element": { - "kind": "ElementReference", - "name": "panel-9" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 6, - "y": 22, - "width": 6, - "height": 4, - "element": { - "kind": "ElementReference", - "name": "panel-10" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V17 MinSpan to MaxPerRow Migration Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v18.gauge_options.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v18.gauge_options.v0alpha1.json index a6f8caf4297..cc57f1b1914 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v18.gauge_options.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v18.gauge_options.v0alpha1.json @@ -4,428 +4,217 @@ "metadata": { "name": "v18.gauge_options.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v18.gauge_options.v42" + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 }, - "spec": { - "annotations": [ + "id": 1, + "options": { + "thresholds": [ { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } + "color": "red", + "value": 100 + }, + { + "color": "yellow", + "value": 50 + }, + { + "color": "green", + "value": 0 } ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Complete Gauge Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "gauge", - "version": "", - "spec": { - "options": { - "thresholds": [ - { - "color": "red", - "value": 100 - }, - { - "color": "yellow", - "value": 50 - }, - { - "color": "green", - "value": 0 - } - ], - "valueOptions": { - "decimals": 2, - "prefix": "Value: ", - "stat": "last", - "suffix": " ms", - "unit": "ms" - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Partial Gauge Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "gauge", - "version": "", - "spec": { - "options": { - "valueOptions": { - "decimals": 1, - "unit": "percent" - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Buggy Gauge Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "gauge", - "version": "", - "spec": { - "options": { - "valueOptions": { - "decimals": 0, - "stat": "avg", - "unit": "bytes" - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Custom Properties Gauge Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "gauge", - "version": "", - "spec": { - "options": { - "anotherProp": 42, - "customProperty": "customValue", - "thresholds": [ - { - "color": "blue", - "value": 10 - } - ], - "valueOptions": { - "unit": "short" - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Non-Gauge Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "show": true, - "showLegend": true - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V18 Gauge Options Migration Test Dashboard", - "variables": [] + "valueOptions": { + "decimals": 2, + "prefix": "Value: ", + "stat": "last", + "suffix": " ms", + "unit": "ms" + } }, - "status": {} + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Complete Gauge Panel", + "type": "gauge" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "valueOptions": { + "decimals": 1, + "unit": "percent" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Partial Gauge Panel", + "type": "gauge" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": { + "valueOptions": { + "decimals": 0, + "stat": "avg", + "unit": "bytes" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Buggy Gauge Panel", + "type": "gauge" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": { + "anotherProp": 42, + "customProperty": "customValue", + "thresholds": [ + { + "color": "blue", + "value": 10 + } + ], + "valueOptions": { + "unit": "short" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Custom Properties Gauge Panel", + "type": "gauge" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": { + "legend": { + "show": true, + "showLegend": true + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Non-Gauge Panel", + "type": "timeseries" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V18 Gauge Options Migration Test Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v19.panel_links.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v19.panel_links.v0alpha1.json index d48ee42151f..44bdfd7c1a0 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v19.panel_links.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v19.panel_links.v0alpha1.json @@ -4,463 +4,220 @@ "metadata": { "name": "v19.panel_links.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "links": [ + { + "title": "Dashboard Link", + "url": "dashboard/db/my-dashboard?$__url_time_range" + } + ], + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with legacy dashboard link", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "links": [ + { + "title": "DashUri Link", + "url": "dashboard/my-dashboard-uid?$__all_variables" + } + ], + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with dashUri link", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "links": [ + { + "title": "Custom Params Link", + "url": "http://example.com?customParam=value" + } + ], + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with custom params", + "type": "table" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "links": [ + { + "targetBlank": true, + "title": "Complex Link", + "url": "dashboard/db/complex-dashboard?$__url_time_range\u0026$__all_variables\u0026param1=value1\u0026param2=value2" + } + ], + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with complex link", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "links": [ + { + "title": "Existing URL Link", + "url": "http://existing-url.com" + } + ], + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with existing URL", + "type": "gauge" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with no links", + "type": "stat" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V19 Panel Links Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v19.panel_links.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with legacy dashboard link", - "description": "", - "links": [ - { - "title": "Dashboard Link", - "url": "dashboard/db/my-dashboard?$__url_time_range" - } - ], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Panel with dashUri link", - "description": "", - "links": [ - { - "title": "DashUri Link", - "url": "dashboard/my-dashboard-uid?$__all_variables" - } - ], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel with custom params", - "description": "", - "links": [ - { - "title": "Custom Params Link", - "url": "http://example.com?customParam=value" - } - ], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel with complex link", - "description": "", - "links": [ - { - "title": "Complex Link", - "url": "dashboard/db/complex-dashboard?$__url_time_range\u0026$__all_variables\u0026param1=value1\u0026param2=value2", - "targetBlank": true - } - ], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Panel with existing URL", - "description": "", - "links": [ - { - "title": "Existing URL Link", - "url": "http://existing-url.com" - } - ], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "gauge", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Panel with no links", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V19 Panel Links Migration Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v2.panels-and-services.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v2.panels-and-services.v0alpha1.json index 6099960b9ee..ec7aab7bc7a 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v2.panels-and-services.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v2.panels-and-services.v0alpha1.json @@ -4,381 +4,199 @@ "metadata": { "name": "v2.panels-and-services.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v2.panels-and-services.v42" + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 }, - "spec": { - "annotations": [ + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A", + "target": "cpu.usage" + } + ], + "title": "CPU Usage", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A", + "target": "memory.usage" + } + ], + "title": "Memory Usage", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Server Stats", + "type": "table" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A", + "target": "disk.io" + } + ], + "title": "Disk I/O", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "server", + "options": [], + "query": "label_values(server)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "env", + "options": [ { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } + "selected": false, + "text": "Production", + "value": "prod" + }, + { + "selected": false, + "text": "Staging", + "value": "stage" } ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "CPU Usage", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "target": "cpu.usage" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Memory Usage", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "target": "memory.usage" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Server Stats", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Disk I/O", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "target": "disk.io" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V2 Comprehensive Migration Test Dashboard", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "server", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "__legacyStringValue": "label_values(server)" - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "CustomVariable", - "spec": { - "name": "env", - "query": "", - "current": { - "text": "", - "value": "" - }, - "options": [ - { - "selected": false, - "text": "Production", - "value": "prod" - }, - { - "selected": false, - "text": "Staging", - "value": "stage" - } - ], - "multi": false, - "includeAll": false, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - } - ] - }, - "status": {} - } + "query": "", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V2 Comprehensive Migration Test Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v20.variable_syntax_links.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v20.variable_syntax_links.v0alpha1.json index 2c36d89c3c9..40a06e400a4 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v20.variable_syntax_links.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v20.variable_syntax_links.v0alpha1.json @@ -4,453 +4,243 @@ "metadata": { "name": "v20.variable_syntax_links.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "dataLinks": [ + { + "targetBlank": true, + "title": "Link with series name", + "url": "http://example.com?series=${__series.name}\u0026timestamp=__value.time" + }, + { + "targetBlank": false, + "title": "Link with field name", + "url": "http://grafana.com/dashboard?field=__field.name\u0026series=${__series.name}" + } + ] + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with data links using legacy variable syntax", + "type": "timeseries" + }, + { + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 2, + "options": { + "fieldOptions": { + "defaults": { + "links": [ + { + "targetBlank": true, + "title": "Field link", + "url": "http://monitoring.com?field=${__field.name}\u0026series=__series.name" + }, + { + "targetBlank": false, + "title": "Time-based link", + "url": "http://logs.com?time=__value.time\u0026field=__field.name" + } + ], + "title": "Series: __series.name, Field: ${__field.name}, Time: __value.time" + } + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with field options using legacy variable syntax", + "type": "stat" + }, + { + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 3, + "options": { + "dataLinks": [ + { + "targetBlank": true, + "title": "Combined link", + "url": "http://combined.com?series=${__series.name}\u0026field=${__field.name}\u0026time=__value.time" + } + ], + "fieldOptions": { + "defaults": { + "links": [ + { + "targetBlank": false, + "title": "Comprehensive link", + "url": "http://comprehensive.com?s=${__series.name}\u0026f=__field.name\u0026t=__value.time" + } + ], + "title": "Complete: __series.name / __field.name / __value.time" + } + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with both data links and field options", + "type": "gauge" + }, + { + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 4, + "options": { + "dataLinks": [ + { + "targetBlank": true, + "title": "Modern link", + "url": "http://modern.com?series=${__series.name}\u0026field=${__field.name}\u0026time=${__value.time}" + } + ], + "fieldOptions": { + "defaults": { + "links": [ + { + "targetBlank": false, + "title": "Modern field link", + "url": "http://modern-field.com?s=${__series.name}\u0026f=${__field.name}" + } + ], + "title": "Modern: ${__series.name} / ${__field.name} / ${__value.time}" + } + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with no legacy variables (should remain unchanged)", + "type": "table" + }, + { + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 5, + "options": { + "content": "This panel has no data links or field options to migrate." + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with no data links or field options", + "type": "text" + } + ], + "preload": false, + "refresh": "5s", + "schemaVersion": 42, + "tags": [ + "migration-test" + ], + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V20 Variable Syntax Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v20.variable_syntax_links.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with data links using legacy variable syntax", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "dataLinks": [ - { - "targetBlank": true, - "title": "Link with series name", - "url": "http://example.com?series=${__series.name}\u0026timestamp=__value.time" - }, - { - "targetBlank": false, - "title": "Link with field name", - "url": "http://grafana.com/dashboard?field=__field.name\u0026series=${__series.name}" - } - ] - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Panel with field options using legacy variable syntax", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": { - "fieldOptions": { - "defaults": { - "links": [ - { - "targetBlank": true, - "title": "Field link", - "url": "http://monitoring.com?field=${__field.name}\u0026series=__series.name" - }, - { - "targetBlank": false, - "title": "Time-based link", - "url": "http://logs.com?time=__value.time\u0026field=__field.name" - } - ], - "title": "Series: __series.name, Field: ${__field.name}, Time: __value.time" - } - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel with both data links and field options", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "gauge", - "version": "", - "spec": { - "options": { - "dataLinks": [ - { - "targetBlank": true, - "title": "Combined link", - "url": "http://combined.com?series=${__series.name}\u0026field=${__field.name}\u0026time=__value.time" - } - ], - "fieldOptions": { - "defaults": { - "links": [ - { - "targetBlank": false, - "title": "Comprehensive link", - "url": "http://comprehensive.com?s=${__series.name}\u0026f=__field.name\u0026t=__value.time" - } - ], - "title": "Complete: __series.name / __field.name / __value.time" - } - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel with no legacy variables (should remain unchanged)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": { - "dataLinks": [ - { - "targetBlank": true, - "title": "Modern link", - "url": "http://modern.com?series=${__series.name}\u0026field=${__field.name}\u0026time=${__value.time}" - } - ], - "fieldOptions": { - "defaults": { - "links": [ - { - "targetBlank": false, - "title": "Modern field link", - "url": "http://modern-field.com?s=${__series.name}\u0026f=${__field.name}" - } - ], - "title": "Modern: ${__series.name} / ${__field.name} / ${__value.time}" - } - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Panel with no data links or field options", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "", - "spec": { - "options": { - "content": "This panel has no data links or field options to migrate." - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 12, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 8, - "width": 24, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 16, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 12, - "y": 16, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [ - "migration-test" - ], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "5s", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V20 Variable Syntax Migration Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v21.data_links_series_to_field.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v21.data_links_series_to_field.v0alpha1.json index 81d695680a8..25823b0fd99 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v21.data_links_series_to_field.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v21.data_links_series_to_field.v0alpha1.json @@ -4,428 +4,217 @@ "metadata": { "name": "v21.data_links_series_to_field.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v21.data_links_series_to_field.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with data links", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "dataLinks": [ - { - "title": "Data Link 1", - "url": "http://mylink.com?series=${__field.labels}\u0026${__field.labels.a}" - }, - { - "title": "Data Link 2", - "url": "http://anotherlink.com?param=${__field.labels}" - } - ] - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Panel with field options links", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": { - "fieldOptions": { - "defaults": { - "links": [ - { - "title": "Field Link 1", - "url": "http://mylink.com?series=${__field.labels}\u0026${__field.labels.x}" - }, - { - "title": "Field Link 2", - "url": "http://fieldlink.com?field=${__field.labels}" - } - ] - } - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel with both link types", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "dataLinks": [ - { - "title": "Graph Data Link", - "url": "http://mylink.com?series=${__field.labels}" - } - ], - "fieldOptions": { - "defaults": { - "links": [ - { - "title": "Graph Field Link", - "url": "http://mylink.com?field=${__field.labels}" - } - ] - } - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel without series labels", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "dataLinks": [ - { - "title": "No Series Labels Link", - "url": "http://mylink.com?other=${__field.labels}" - } - ] - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Panel without options", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "dataLinks": [ + { + "title": "Data Link 1", + "url": "http://mylink.com?series=${__field.labels}\u0026${__field.labels.a}" + }, + { + "title": "Data Link 2", + "url": "http://anotherlink.com?param=${__field.labels}" + } + ] + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with data links", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "fieldOptions": { + "defaults": { + "links": [ { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } + "title": "Field Link 1", + "url": "http://mylink.com?series=${__field.labels}\u0026${__field.labels.x}" }, { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } + "title": "Field Link 2", + "url": "http://fieldlink.com?field=${__field.labels}" } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V21 Data Links Series to Field Migration Test Dashboard", - "variables": [] + } }, - "status": {} + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with field options links", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": { + "dataLinks": [ + { + "title": "Graph Data Link", + "url": "http://mylink.com?series=${__field.labels}" + } + ], + "fieldOptions": { + "defaults": { + "links": [ + { + "title": "Graph Field Link", + "url": "http://mylink.com?field=${__field.labels}" + } + ] + } + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with both link types", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": { + "dataLinks": [ + { + "title": "No Series Labels Link", + "url": "http://mylink.com?other=${__field.labels}" + } + ] + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel without series labels", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel without options", + "type": "timeseries" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V21 Data Links Series to Field Migration Test Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v22.table_panel_align.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v22.table_panel_align.v0alpha1.json index 22db42a1f9b..ab9f271d900 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v22.table_panel_align.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v22.table_panel_align.v0alpha1.json @@ -4,142 +4,79 @@ "metadata": { "name": "v22.table_panel_align.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "table" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V22 Table Panel Styles Test" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v22.table_panel_align.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V22 Table Panel Styles Test", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v23.multi_variable_alignment.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v23.multi_variable_alignment.v0alpha1.json index fbc2d99ff02..6bf600c5014 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v23.multi_variable_alignment.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v23.multi_variable_alignment.v0alpha1.json @@ -4,407 +4,309 @@ "metadata": { "name": "v23.multi_variable_alignment.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "up", + "refId": "A" + } + ], + "title": "Test Panel", + "type": "stat" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": [ + "A" + ], + "value": [ + "A" + ] + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": true, + "name": "multi_single_value", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": [ + "B", + "C" + ], + "value": [ + "B", + "C" + ] + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": true, + "name": "multi_array_value", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "D", + "value": "D" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "non_multi_array_value", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "E", + "value": "E" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "non_multi_single_value", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "F", + "value": "F" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "no_multi_property", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": true, + "name": "empty_current", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": true, + "name": "nil_current", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": [ + "G" + ], + "value": [ + "G" + ] + }, + "hide": 0, + "includeAll": false, + "multi": true, + "name": "custom_variable", + "options": [], + "query": "", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "text": "H", + "value": "H" + }, + "hide": 0, + "name": "textbox_variable", + "query": "", + "skipUrlSync": false, + "type": "textbox" + }, + { + "allowCustomValue": true, + "current": { + "text": [ + "Prometheus", + "InfluxDB" + ], + "value": [ + "prometheus", + "influxdb" + ] + }, + "hide": 0, + "includeAll": false, + "multi": true, + "name": "datasource_variable", + "options": [], + "query": "prometheus", + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "auto": false, + "auto_count": 0, + "auto_min": "", + "current": { + "text": "1m", + "value": "1m" + }, + "hide": 0, + "name": "interval_variable", + "options": [], + "query": "", + "skipUrlSync": false, + "type": "interval" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V23 Multi Variables Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v23.multi_variable_alignment.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Test Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "expr": "up" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V23 Multi Variables Migration Test Dashboard", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "multi_single_value", - "current": { - "text": [ - "A" - ], - "value": [ - "A" - ] - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": true, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "multi_array_value", - "current": { - "text": [ - "B", - "C" - ], - "value": [ - "B", - "C" - ] - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": true, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "non_multi_array_value", - "current": { - "text": "D", - "value": "D" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "non_multi_single_value", - "current": { - "text": "E", - "value": "E" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "no_multi_property", - "current": { - "text": "F", - "value": "F" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "empty_current", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": true, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "nil_current", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": true, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "CustomVariable", - "spec": { - "name": "custom_variable", - "query": "", - "current": { - "text": [ - "G" - ], - "value": [ - "G" - ] - }, - "options": [], - "multi": true, - "includeAll": false, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "TextVariable", - "spec": { - "name": "textbox_variable", - "current": { - "text": "H", - "value": "H" - }, - "query": "", - "hide": "dontHide", - "skipUrlSync": false - } - }, - { - "kind": "DatasourceVariable", - "spec": { - "name": "datasource_variable", - "pluginId": "prometheus", - "refresh": "never", - "regex": "", - "current": { - "text": [ - "Prometheus", - "InfluxDB" - ], - "value": [ - "prometheus", - "influxdb" - ] - }, - "options": [], - "multi": true, - "includeAll": false, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "IntervalVariable", - "spec": { - "name": "interval_variable", - "query": "", - "current": { - "text": "1m", - "value": "1m" - }, - "options": [], - "auto": false, - "auto_min": "", - "auto_count": 0, - "refresh": "onTimeRangeChanged", - "hide": "dontHide", - "skipUrlSync": false - } - } - ] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v24.table-angular.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v24.table-angular.v0alpha1.json index 660bd5c00fb..876be802767 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v24.table-angular.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v24.table-angular.v0alpha1.json @@ -4,1117 +4,468 @@ "metadata": { "name": "v24.table-angular.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "description": "Tests basic migration with default style pattern (/.*/) containing thresholds and colors. Should convert styles to fieldConfig.defaults with threshold steps.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "B" + } + ], + "title": "Basic Angular Table with Defaults", + "type": "table" + }, + { + "description": "Tests comprehensive migration including: default style with thresholds/colors/unit/decimals/align/colorMode, column overrides with exact name and regex patterns, date formatting, hidden columns, and links with tooltips.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Complex Table with All Style Features", + "type": "table" + }, + { + "description": "Tests migration of timeseries_aggregations transform to reduce transformation with column mappings (avg-\u003emean, max-\u003emax, min-\u003emin, total-\u003esum, current-\u003elastNotNull, count-\u003ecount).", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Table with Timeseries Aggregations Transform", + "type": "table" + }, + { + "description": "Tests migration of timeseries_to_rows transform to seriesToRows transformation.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Table with Timeseries to Rows Transform", + "type": "table" + }, + { + "description": "Tests migration of timeseries_to_columns transform to seriesToColumns transformation.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Table with Timeseries to Columns Transform", + "type": "table" + }, + { + "description": "Tests migration of table transform to merge transformation. Also tests auto alignment conversion to empty string.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Table with Merge Transform", + "type": "table" + }, + { + "description": "Tests that existing transformations are preserved and new transformation from old format is appended to the list.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 7, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Table with Existing Transformations", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "field1", + "field2" + ] + } + } + } + ], + "type": "table" + }, + { + "description": "Tests handling of mixed numeric and string threshold values (int, string, float) with proper type conversion.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Mixed Threshold Types", + "type": "table" + }, + { + "description": "Tests all color mode mappings: cell-\u003ecolor-background, row-\u003ecolor-background, value-\u003ecolor-text.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 9, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "All Color Modes Test", + "type": "table" + }, + { + "description": "Tests all alignment options: left, center, right, and auto (should convert to empty string).", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 10, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "All Alignment Options", + "type": "table" + }, + { + "description": "Tests both field matcher types: byName for exact matches and byRegexp for regex patterns.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 11, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Field Matcher Types Test", + "type": "table" + }, + { + "description": "Tests various link configurations: with and without tooltip, with and without target blank.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 12, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Link Configuration Test", + "type": "table" + }, + { + "description": "Tests various date format patterns and aliases.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 13, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Date Format Variations", + "type": "table" + }, + { + "description": "React table (table2) should not be migrated. Properties should remain unchanged.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 14, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "React Table - Should NOT Migrate", + "type": "table" + }, + { + "description": "Angular table without styles property should not be migrated.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 15, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Angular Table without Styles - Should NOT Migrate", + "type": "table" + }, + { + "description": "Non-table panels should remain completely unchanged.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 16, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Non-Table Panel - Should NOT Migrate", + "type": "timeseries" + }, + { + "description": "Other panel types should not be affected by table migration.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 17, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Singlestat Panel - Should NOT Migrate", + "type": "stat" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "No Title" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v24.table-angular.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Basic Angular Table with Defaults", - "description": "Tests basic migration with default style pattern (/.*/) containing thresholds and colors. Should convert styles to fieldConfig.defaults with threshold steps.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-10": { - "kind": "Panel", - "spec": { - "id": 10, - "title": "All Alignment Options", - "description": "Tests all alignment options: left, center, right, and auto (should convert to empty string).", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-11": { - "kind": "Panel", - "spec": { - "id": 11, - "title": "Field Matcher Types Test", - "description": "Tests both field matcher types: byName for exact matches and byRegexp for regex patterns.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-12": { - "kind": "Panel", - "spec": { - "id": 12, - "title": "Link Configuration Test", - "description": "Tests various link configurations: with and without tooltip, with and without target blank.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-13": { - "kind": "Panel", - "spec": { - "id": 13, - "title": "Date Format Variations", - "description": "Tests various date format patterns and aliases.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-14": { - "kind": "Panel", - "spec": { - "id": 14, - "title": "React Table - Should NOT Migrate", - "description": "React table (table2) should not be migrated. Properties should remain unchanged.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-15": { - "kind": "Panel", - "spec": { - "id": 15, - "title": "Angular Table without Styles - Should NOT Migrate", - "description": "Angular table without styles property should not be migrated.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-16": { - "kind": "Panel", - "spec": { - "id": 16, - "title": "Non-Table Panel - Should NOT Migrate", - "description": "Non-table panels should remain completely unchanged.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-17": { - "kind": "Panel", - "spec": { - "id": 17, - "title": "Singlestat Panel - Should NOT Migrate", - "description": "Other panel types should not be affected by table migration.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Complex Table with All Style Features", - "description": "Tests comprehensive migration including: default style with thresholds/colors/unit/decimals/align/colorMode, column overrides with exact name and regex patterns, date formatting, hidden columns, and links with tooltips.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Table with Timeseries Aggregations Transform", - "description": "Tests migration of timeseries_aggregations transform to reduce transformation with column mappings (avg-\u003emean, max-\u003emax, min-\u003emin, total-\u003esum, current-\u003elastNotNull, count-\u003ecount).", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Table with Timeseries to Rows Transform", - "description": "Tests migration of timeseries_to_rows transform to seriesToRows transformation.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Table with Timeseries to Columns Transform", - "description": "Tests migration of timeseries_to_columns transform to seriesToColumns transformation.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Table with Merge Transform", - "description": "Tests migration of table transform to merge transformation. Also tests auto alignment conversion to empty string.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Table with Existing Transformations", - "description": "Tests that existing transformations are preserved and new transformation from old format is appended to the list.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "filterFieldsByName", - "spec": { - "id": "filterFieldsByName", - "options": { - "include": { - "names": [ - "field1", - "field2" - ] - } - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Mixed Threshold Types", - "description": "Tests handling of mixed numeric and string threshold values (int, string, float) with proper type conversion.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-9": { - "kind": "Panel", - "spec": { - "id": 9, - "title": "All Color Modes Test", - "description": "Tests all color mode mappings: cell-\u003ecolor-background, row-\u003ecolor-background, value-\u003ecolor-text.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-9" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-10" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-11" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-12" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-13" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-14" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-15" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-16" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-17" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "No Title", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v25.no-op-migration.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v25.no-op-migration.v0alpha1.json index c05a05ae948..704035dffdf 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v25.no-op-migration.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v25.no-op-migration.v0alpha1.json @@ -4,242 +4,132 @@ "metadata": { "name": "v25.no-op-migration.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + }, + { + "enable": true, + "hide": false, + "iconColor": "", + "name": "Deployments" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with transformations remains unchanged", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Graph", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "tags should not be removed", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V25 No-Op Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v25.no-op-migration.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "", - "name": "Deployments" - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with transformations remains unchanged", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Graph", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V25 No-Op Migration Test Dashboard", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "tags should not be removed", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - } - ] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v26.text2_to_text.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v26.text2_to_text.v0alpha1.json index 3b79b30aed1..4ddc375e3d0 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v26.text2_to_text.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v26.text2_to_text.v0alpha1.json @@ -4,263 +4,126 @@ "metadata": { "name": "v26.text2_to_text.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Text2 Panel", + "type": "text" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Angular Text Panel", + "type": "text" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": { + "content": "# React Text Panel from Angular Panel\n# $constant\n\nFor markdown syntax help: [commonmark.org/help](https://commonmark.org/help/)\n\n## $text\n\n", + "mode": "markdown" + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "React Text Panel from Angular Panel", + "type": "text" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "No Title" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v26.text2_to_text.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Text2 Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Angular Text Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "React Text Panel from Angular Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "", - "spec": { - "options": { - "content": "# React Text Panel from Angular Panel\n# $constant\n\nFor markdown syntax help: [commonmark.org/help](https://commonmark.org/help/)\n\n## $text\n\n", - "mode": "markdown" - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "No Title", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v27.repeated_panels_and_constant_variable.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v27.repeated_panels_and_constant_variable.v0alpha1.json index cd7befbf4e7..99bdb079082 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v27.repeated_panels_and_constant_variable.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v27.repeated_panels_and_constant_variable.v0alpha1.json @@ -4,227 +4,120 @@ "metadata": { "name": "v27.repeated_panels_and_constant_variable.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Normal Panel", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": -1, + "title": "Row with repeated panels", + "type": "row" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Normal nested panel", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "current": { + "text": "default_value", + "value": "default_value" + }, + "hide": 0, + "name": "constant_var", + "query": "default_value", + "skipUrlSync": false, + "type": "textbox" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V27 Repeated Panels and Constant Variable Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v27.repeated_panels_and_constant_variable.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Normal Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Normal nested panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row with repeated panels", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - } - ] - } - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V27 Repeated Panels and Constant Variable Migration Test Dashboard", - "variables": [ - { - "kind": "TextVariable", - "spec": { - "name": "constant_var", - "current": { - "text": "default_value", - "value": "default_value" - }, - "query": "default_value", - "hide": "dontHide", - "skipUrlSync": false - } - } - ] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.remove_variable_properties.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.remove_variable_properties.v0alpha1.json index 6c987fc8588..77f44169ab6 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.remove_variable_properties.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.remove_variable_properties.v0alpha1.json @@ -4,150 +4,117 @@ "metadata": { "name": "v28.remove_variable_properties.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v28.remove_variable_properties.v42" + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "query_variable_with_tags", + "options": [], + "query": "label_values(up, instance)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" }, - "spec": { - "annotations": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "custom_variable_with_tags", + "options": [ { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } + "selected": false, + "text": "Option 1", + "value": "opt1" + }, + { + "selected": false, + "text": "Option 2", + "value": "opt2" } ], - "cursorSync": "Off", - "editable": true, - "elements": {}, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V28 Singlestat and Variable Properties Migration Test Dashboard", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "query_variable_with_tags", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "__legacyStringValue": "label_values(up, instance)" - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "CustomVariable", - "spec": { - "name": "custom_variable_with_tags", - "query": "", - "current": { - "text": "", - "value": "" - }, - "options": [ - { - "selected": false, - "text": "Option 1", - "value": "opt1" - }, - { - "selected": false, - "text": "Option 2", - "value": "opt2" - } - ], - "multi": false, - "includeAll": false, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "TextVariable", - "spec": { - "name": "clean_variable", - "current": { - "text": "", - "value": "" - }, - "query": "", - "hide": "dontHide", - "skipUrlSync": false - } - } - ] + "query": "", + "skipUrlSync": false, + "type": "custom" }, - "status": {} - } + { + "current": { + "text": "", + "value": "" + }, + "hide": 0, + "name": "clean_variable", + "query": "", + "skipUrlSync": false, + "type": "textbox" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V28 Singlestat and Variable Properties Migration Test Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_and_variable_properties.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_and_variable_properties.v0alpha1.json index 71e112bda5f..549d23f389c 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_and_variable_properties.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_and_variable_properties.v0alpha1.json @@ -4,422 +4,222 @@ "metadata": { "name": "v28.singlestat_and_variable_properties.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v28.singlestat_and_variable_properties.v42" + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 }, - "spec": { - "annotations": [ + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "B" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "B" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "rate(http_requests_total[5m])", + "refId": "A" + } + ], + "title": "", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "query_variable_with_tags", + "options": [], + "query": "label_values(up, instance)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "custom_variable_with_tags", + "options": [ { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } + "selected": false, + "text": "Option 1", + "value": "opt1" + }, + { + "selected": false, + "text": "Option 2", + "value": "opt2" } ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "expr": "rate(http_requests_total[5m])" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V28 Singlestat and Variable Properties Migration Test Dashboard", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "query_variable_with_tags", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "__legacyStringValue": "label_values(up, instance)" - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "CustomVariable", - "spec": { - "name": "custom_variable_with_tags", - "query": "", - "current": { - "text": "", - "value": "" - }, - "options": [ - { - "selected": false, - "text": "Option 1", - "value": "opt1" - }, - { - "selected": false, - "text": "Option 2", - "value": "opt2" - } - ], - "multi": false, - "includeAll": false, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "TextVariable", - "spec": { - "name": "clean_variable", - "current": { - "text": "", - "value": "" - }, - "query": "", - "hide": "dontHide", - "skipUrlSync": false - } - } - ] + "query": "", + "skipUrlSync": false, + "type": "custom" }, - "status": {} - } + { + "current": { + "text": "", + "value": "" + }, + "hide": 0, + "name": "clean_variable", + "query": "", + "skipUrlSync": false, + "type": "textbox" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V28 Singlestat and Variable Properties Migration Test Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_migration.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_migration.v0alpha1.json index cda275b5015..f47146292f4 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_migration.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_migration.v0alpha1.json @@ -4,658 +4,309 @@ "metadata": { "name": "v28.singlestat_migration.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v28.singlestat_migration.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "grafana-singlestat-panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "PD8C576611E62080A" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": { - "maxDataPoints": 100 - } - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "singlestat (old, internal. Migrated if schema \u003c 28)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "PD8C576611E62080A" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": { - "maxDataPoints": 100 - } - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "1.0.0", - "spec": { - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "fieldConfig": { - "defaults": { - "unit": "ms", - "mappings": [ - { - "type": "special", - "options": { - "match": "null", - "result": { - "text": "N/A" - } - } - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - } - }, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Status + Notes", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "PD8C576611E62080A" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "1.0.0", - "spec": { - "options": { - "code": { - "language": "plaintext", - "showLineNumbers": false, - "showMiniMap": false - }, - "content": "# Singlestat \u003e\u003e Stat\n\nKnown issues:\n* limited options", - "mode": "markdown" - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "expr": "rate(http_requests_total[5m])" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "B" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "B" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "B" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "rate(http_requests_total[5m])", + "refId": "A" + } + ], + "title": "", + "type": "timeseries" + }, + { + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 43 + }, + "id": 5, + "maxDataPoints": 100, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PD8C576611E62080A" + }, + "refId": "A" + } + ], + "title": "grafana-singlestat-panel", + "type": "stat" + }, + { + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" } }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } + "color": "green", + "value": null }, { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 43, - "width": 8, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 8, - "y": 43, - "width": 8, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 43, - "width": 8, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } + "color": "red", + "value": 80 } ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V28 Singlestat and Variable Properties Migration Test Dashboard", - "variables": [] + }, + "unit": "ms" + } }, - "status": {} + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 43 + }, + "id": 6, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "1.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PD8C576611E62080A" + }, + "refId": "A" + } + ], + "title": "singlestat (old, internal. Migrated if schema \u003c 28)", + "type": "stat" + }, + { + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 43 + }, + "id": 7, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "# Singlestat \u003e\u003e Stat\n\nKnown issues:\n* limited options", + "mode": "markdown" + }, + "pluginVersion": "1.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PD8C576611E62080A" + }, + "refId": "A" + } + ], + "title": "Status + Notes", + "type": "text" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V28 Singlestat and Variable Properties Migration Test Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v29.query_variables_refresh_and_options.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v29.query_variables_refresh_and_options.v0alpha1.json index 71b0544d532..46a5be539cf 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v29.query_variables_refresh_and_options.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v29.query_variables_refresh_and_options.v0alpha1.json @@ -4,474 +4,364 @@ "metadata": { "name": "v29.query_variables_refresh_and_options.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v29.query_variables_refresh_and_options.v42" + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 }, - "spec": { - "annotations": [ + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "expr": "up", + "refId": "A" + } + ], + "title": "Test Panel", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "never_refresh_with_options", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "never_refresh_without_options", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "dashboard_refresh_with_options", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "dashboard_refresh_without_options", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "timerange_refresh_with_options", + "options": [], + "query": {}, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "timerange_refresh_without_options", + "options": [], + "query": {}, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "no_refresh_with_options", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "no_refresh_without_options", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "unknown_refresh_with_options", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "unknown_refresh_without_options", + "options": [], + "query": {}, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "custom_variable", + "options": [ { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } + "selected": false, + "text": "custom", + "value": "custom" } ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Test Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "prometheus" - }, - "spec": { - "expr": "up" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V29 Query Variables Refresh and Options Migration Test Dashboard", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "never_refresh_with_options", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "never_refresh_without_options", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "dashboard_refresh_with_options", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "dashboard_refresh_without_options", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "timerange_refresh_with_options", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onTimeRangeChanged", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "timerange_refresh_without_options", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onTimeRangeChanged", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "no_refresh_with_options", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "no_refresh_without_options", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "unknown_refresh_with_options", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "unknown_refresh_without_options", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "CustomVariable", - "spec": { - "name": "custom_variable", - "query": "", - "current": { - "text": "", - "value": "" - }, - "options": [ - { - "selected": false, - "text": "custom", - "value": "custom" - } - ], - "multi": false, - "includeAll": false, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "TextVariable", - "spec": { - "name": "textbox_variable", - "current": { - "text": "", - "value": "" - }, - "query": "", - "hide": "dontHide", - "skipUrlSync": false - } - }, - { - "kind": "DatasourceVariable", - "spec": { - "name": "datasource_variable", - "pluginId": "prometheus", - "refresh": "never", - "regex": "", - "current": { - "text": "", - "value": "" - }, - "options": [], - "multi": false, - "includeAll": false, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "IntervalVariable", - "spec": { - "name": "interval_variable", - "query": "1m", - "current": { - "text": "", - "value": "" - }, - "options": [ - { - "selected": false, - "text": "1m", - "value": "1m" - } - ], - "auto": false, - "auto_min": "", - "auto_count": 0, - "refresh": "onTimeRangeChanged", - "hide": "dontHide", - "skipUrlSync": false - } - } - ] + "query": "", + "skipUrlSync": false, + "type": "custom" }, - "status": {} - } + { + "current": { + "text": "", + "value": "" + }, + "hide": 0, + "name": "textbox_variable", + "query": "", + "skipUrlSync": false, + "type": "textbox" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource_variable", + "options": [], + "query": "prometheus", + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "auto": false, + "auto_count": 0, + "auto_min": "", + "current": { + "text": "", + "value": "" + }, + "hide": 0, + "name": "interval_variable", + "options": [ + { + "selected": false, + "text": "1m", + "value": "1m" + } + ], + "query": "1m", + "skipUrlSync": false, + "type": "interval" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V29 Query Variables Refresh and Options Migration Test Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v3.no-op.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v3.no-op.v0alpha1.json index 0c6fd287427..811f9a00d89 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v3.no-op.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v3.no-op.v0alpha1.json @@ -4,319 +4,145 @@ "metadata": { "name": "v3.no-op.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "barchart" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "barchart" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V3 No-Op Migration - but tests ensuring panel IDs are unique" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v3.no-op.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "barchart", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "barchart", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V3 No-Op Migration - but tests ensuring panel IDs are unique", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v30.value_mappings_and_tooltip_options.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v30.value_mappings_and_tooltip_options.v0alpha1.json index f4c9878142d..e6ec721a7f3 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v30.value_mappings_and_tooltip_options.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v30.value_mappings_and_tooltip_options.v0alpha1.json @@ -4,721 +4,409 @@ "metadata": { "name": "v30.value_mappings_and_tooltip_options.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v30.value_mappings_and_tooltip_options.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with legacy value mappings and tooltip options", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "tooltip": { - "mode": "multi" - } - }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "type": "value", - "options": { - "0": { - "text": "Down" - }, - "1": { - "text": "Up" - } - } - }, - { - "type": "range", - "options": { - "from": 10, - "to": 20, - "result": { - "text": "Medium" - } - } - }, - { - "type": "special", - "options": { - "match": "null", - "result": { - "text": "Null Value" - } - } - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "test-field" - }, - "properties": [ - { - "id": "mappings", - "value": [ - { - "options": { - "1": { - "text": "Override Up" - } - }, - "type": "value" - } - ] - } - ] - } - ] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "XY Chart with tooltip options only", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "xychart", - "version": "", - "spec": { - "options": { - "tooltip": { - "mode": "single" - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "XY Chart2 with tooltip options", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "xychart2", - "version": "", - "spec": { - "options": { - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Graph panel gets migrated to timeseries and tooltip", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "tooltip": { - "mode": "single" - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Panel with complex value mappings", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "type": "value", - "options": { - "100": { - "text": "Critical" - } - } - }, - { - "type": "range", - "options": { - "from": 50, - "to": 99, - "result": { - "text": "Warning" - } - } - }, - { - "type": "range", - "options": { - "from": 0, - "to": 49, - "result": { - "text": "OK" - } - } - } - ] - }, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Nested panel with both migrations", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "tooltip": { - "mode": "multi" - } - }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "type": "value", - "options": { - "0": { - "text": "Off" - }, - "1": { - "text": "On" - } - } - } - ] - }, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Panel with no relevant configurations", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "displayMode": "list", - "showLegend": true - } - }, - "fieldConfig": { - "defaults": { - "unit": "bytes" - }, - "overrides": [] - } - } - } - } - }, - "panel-9": { - "kind": "Panel", - "spec": { - "id": 9, - "title": "Panel with empty mappings array - should return null", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "empty-field" - }, - "properties": [ - { - "id": "mappings", - "value": [] - } - ] - } - ] - } - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": true, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - } - ] - } - } + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "0": { + "text": "Down" + }, + "1": { + "text": "Up" } }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Collapsed Row with nested panels", - "collapse": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-9" - } - } - } - ] - } - } + "type": "value" + }, + { + "options": { + "from": 10, + "result": { + "text": "Medium" + }, + "to": 20 + }, + "type": "range" + }, + { + "options": { + "match": "null", + "result": { + "text": "Null Value" } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 } ] } }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V30 Value Mappings and Tooltip Options Migration Test Dashboard", - "variables": [] + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "test-field" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "1": { + "text": "Override Up" + } + }, + "type": "value" + } + ] + } + ] + } + ] }, - "status": {} + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with legacy value mappings and tooltip options", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "tooltip": { + "mode": "single" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "XY Chart with tooltip options only", + "type": "xychart" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": { + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "XY Chart2 with tooltip options", + "type": "xychart2" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": { + "tooltip": { + "mode": "single" + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Graph panel gets migrated to timeseries and tooltip", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "100": { + "text": "Critical" + } + }, + "type": "value" + }, + { + "options": { + "from": 50, + "result": { + "text": "Warning" + }, + "to": 99 + }, + "type": "range" + }, + { + "options": { + "from": 0, + "result": { + "text": "OK" + }, + "to": 49 + }, + "type": "range" + } + ] + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with complex value mappings", + "type": "stat" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": -1, + "panels": [ + { + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "0": { + "text": "Off" + }, + "1": { + "text": "On" + } + }, + "type": "value" + } + ] + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 7, + "options": { + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "", + "targets": [], + "title": "Nested panel with both migrations", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "unit": "bytes" + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 8, + "options": { + "legend": { + "displayMode": "list", + "showLegend": true + } + }, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with no relevant configurations", + "type": "timeseries" + }, + { + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "empty-field" + }, + "properties": [ + { + "id": "mappings", + "value": [] + } + ] + } + ] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 9, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with empty mappings array - should return null", + "type": "stat" + } + ], + "title": "Collapsed Row with nested panels", + "type": "row" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V30 Value Mappings and Tooltip Options Migration Test Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v31.labels_to_fields_merge.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v31.labels_to_fields_merge.v0alpha1.json index faba0b459ca..b3261291c34 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v31.labels_to_fields_merge.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v31.labels_to_fields_merge.v0alpha1.json @@ -4,700 +4,329 @@ "metadata": { "name": "v31.labels_to_fields_merge.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with basic labelsToFields transformation", + "transformations": [ + { + "id": "labelsToFields", + "options": {} + }, + { + "id": "merge", + "options": {} + } + ], + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 9, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with labelsToFields options preserved", + "transformations": [ + { + "id": "labelsToFields", + "options": { + "keepLabels": [ + "job", + "instance", + "region" + ], + "mode": "rows", + "valueLabel": "value" + } + }, + { + "id": "merge", + "options": {} + } + ], + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with multiple labelsToFields transformations", + "transformations": [ + { + "id": "organize", + "options": {} + }, + { + "id": "labelsToFields", + "options": {} + }, + { + "id": "merge", + "options": {} + }, + { + "id": "calculateField", + "options": {} + }, + { + "id": "labelsToFields", + "options": { + "mode": "rows" + } + }, + { + "id": "merge", + "options": {} + } + ], + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with no transformations", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with other transformations only", + "transformations": [ + { + "id": "organize", + "options": {} + }, + { + "id": "reduce", + "options": {} + } + ], + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": -1, + "title": "Row with nested panels", + "type": "row" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Nested panel with labelsToFields", + "transformations": [ + { + "id": "labelsToFields", + "options": {} + }, + { + "id": "merge", + "options": {} + } + ], + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 7, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Nested panel without labelsToFields", + "transformations": [ + { + "id": "organize", + "options": {} + } + ], + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with labelsToFields and existing merge", + "transformations": [ + { + "id": "labelsToFields", + "options": {} + }, + { + "id": "merge", + "options": {} + }, + { + "id": "merge", + "options": {} + }, + { + "id": "reduce", + "options": {} + } + ], + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V31 LabelsToFields Merge Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v31.labels_to_fields_merge.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with basic labelsToFields transformation", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "labelsToFields", - "spec": { - "id": "labelsToFields", - "options": {} - } - }, - { - "kind": "merge", - "spec": { - "id": "merge", - "options": {} - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Panel with multiple labelsToFields transformations", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "organize", - "spec": { - "id": "organize", - "options": {} - } - }, - { - "kind": "labelsToFields", - "spec": { - "id": "labelsToFields", - "options": {} - } - }, - { - "kind": "merge", - "spec": { - "id": "merge", - "options": {} - } - }, - { - "kind": "calculateField", - "spec": { - "id": "calculateField", - "options": {} - } - }, - { - "kind": "labelsToFields", - "spec": { - "id": "labelsToFields", - "options": { - "mode": "rows" - } - } - }, - { - "kind": "merge", - "spec": { - "id": "merge", - "options": {} - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel with no transformations", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel with other transformations only", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "organize", - "spec": { - "id": "organize", - "options": {} - } - }, - { - "kind": "reduce", - "spec": { - "id": "reduce", - "options": {} - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Nested panel with labelsToFields", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [ - { - "kind": "labelsToFields", - "spec": { - "id": "labelsToFields", - "options": {} - } - }, - { - "kind": "merge", - "spec": { - "id": "merge", - "options": {} - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Nested panel without labelsToFields", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [ - { - "kind": "organize", - "spec": { - "id": "organize", - "options": {} - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Panel with labelsToFields and existing merge", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "labelsToFields", - "spec": { - "id": "labelsToFields", - "options": {} - } - }, - { - "kind": "merge", - "spec": { - "id": "merge", - "options": {} - } - }, - { - "kind": "merge", - "spec": { - "id": "merge", - "options": {} - } - }, - { - "kind": "reduce", - "spec": { - "id": "reduce", - "options": {} - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-9": { - "kind": "Panel", - "spec": { - "id": 9, - "title": "Panel with labelsToFields options preserved", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "labelsToFields", - "spec": { - "id": "labelsToFields", - "options": { - "keepLabels": [ - "job", - "instance", - "region" - ], - "mode": "rows", - "valueLabel": "value" - } - } - }, - { - "kind": "merge", - "spec": { - "id": "merge", - "options": {} - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-9" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row with nested panels", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - } - ] - } - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V31 LabelsToFields Merge Migration Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v32.no_op_migration.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v32.no_op_migration.v0alpha1.json index 97a04da908a..bde81f8e5b9 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v32.no_op_migration.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v32.no_op_migration.v0alpha1.json @@ -4,336 +4,179 @@ "metadata": { "name": "v32.no_op_migration.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + }, + { + "enable": true, + "hide": false, + "iconColor": "", + "name": "Deployments" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with transformations remains unchanged", + "transformations": [ + { + "id": "labelsToFields", + "options": { + "keepLabels": [ + "job", + "instance" + ], + "mode": "rows" + } + }, + { + "id": "merge", + "options": {} + } + ], + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Graph panel remains unchanged", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": -1, + "title": "Row with nested panels", + "type": "row" + }, + { + "fieldConfig": { + "defaults": { + "unit": "bytes" + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Nested stat panel", + "type": "stat" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "environment", + "options": [], + "query": {}, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V32 No-Op Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v32.no_op_migration.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "", - "name": "Deployments" - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with transformations remains unchanged", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "labelsToFields", - "spec": { - "id": "labelsToFields", - "options": { - "keepLabels": [ - "job", - "instance" - ], - "mode": "rows" - } - } - }, - { - "kind": "merge", - "spec": { - "id": "merge", - "options": {} - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Graph panel remains unchanged", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Nested stat panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "unit": "bytes" - }, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row with nested panels", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - } - ] - } - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V32 No-Op Migration Test Dashboard", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "environment", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "never", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - } - ] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v33.panel_ds_name_to_ref.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v33.panel_ds_name_to_ref.v0alpha1.json index 06f420e30b9..a860cf2dd06 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v33.panel_ds_name_to_ref.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v33.panel_ds_name_to_ref.v0alpha1.json @@ -4,762 +4,341 @@ "metadata": { "name": "v33.panel_ds_name_to_ref.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "description": "Tests v33 migration behavior when panel datasource is explicitly null. Should remain null after migration (returnDefaultAsNull: true).", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "non-default-test-ds-uid" + }, + "description": "Target with UID reference should migrate to full object", + "refId": "A" + } + ], + "title": "Panel Datasource: null → should stay null", + "type": "stat" + }, + { + "description": "Tests v33 migration behavior when panel datasource is already a proper object reference. Should remain unchanged.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "description": "Target with existing object should remain unchanged", + "refId": "A" + } + ], + "title": "Panel Datasource: existing object → should stay unchanged", + "type": "stat" + }, + { + "description": "Tests v33 migration when panel datasource is a string name. Should convert to proper object with uid, type, apiVersion.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "non-default-test-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel Datasource: string name → should migrate to object", + "type": "table" + }, + { + "description": "Tests v33 migration when panel has datasource string but empty targets array. Panel datasource should still migrate.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel Datasource: string name with empty targets → should migrate", + "type": "table" + }, + { + "datasource": { + "type": "mixed", + "uid": "-- Mixed --" + }, + "description": "Tests v33 target migration with various edge cases: null target (unchanged), valid string (migrated), non-existing string (preserved), missing datasource field (unchanged).", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "non-default-test-ds-uid" + }, + "description": "Null target datasource should remain null", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "description": "Valid string should migrate to object", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "non-existing-ds" + }, + "description": "Non-existing datasource should be preserved as-is (migration returns nil)", + "refId": "C" + }, + { + "datasource": { + "type": "loki", + "uid": "non-default-test-ds-uid" + }, + "description": "Target without datasource field should remain unchanged", + "refId": "D" + } + ], + "title": "Target Datasources: mixed null/string/non-existing scenarios", + "type": "timeseries" + }, + { + "datasource": { + "type": "mixed", + "uid": "-- Mixed --" + }, + "description": "Tests v33 migration when panel datasource is null but targets have mixed reference types (object, string). Panel should stay null, targets should migrate appropriately.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "existing-ref" + }, + "description": "Existing object target should remain unchanged", + "refId": "A" + }, + { + "datasource": { + "type": "loki", + "uid": "non-default-test-ds-uid" + }, + "description": "String target should migrate to object", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "description": "Default datasource string should migrate to object", + "refId": "C" + } + ], + "title": "Panel: null datasource with mixed target types", + "type": "timeseries" + }, + { + "description": "Tests v33 migration behavior with empty string datasource. Should migrate to empty object {} based on MigrateDatasourceNameToRef logic.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 7, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "description": "Empty string target should also migrate to empty object {}", + "refId": "A" + } + ], + "title": "Empty string datasource → should return empty object {}", + "type": "stat" + }, + { + "datasource": { + "type": "mixed", + "uid": "-- Mixed --" + }, + "description": "Tests v33 migration with completely unknown datasource names. Since migration returns nil for unknown datasources, they should be preserved unchanged.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "also-missing-ds" + }, + "description": "Unknown target datasource should remain unchanged (migration returns nil)", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "completely-missing-ds" + }, + "description": "Empty string target should migrate to {}", + "refId": "B" + } + ], + "title": "Non-existing datasources → should be preserved as-is", + "type": "table" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": -1, + "panels": [ + { + "description": "Nested panel with string datasource should migrate to proper object reference, proving row panel recursion works.", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 10, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "description": "Nested target should also migrate from string to object", + "refId": "A" + } + ], + "title": "Nested Panel: string datasource → should migrate to object", + "type": "timeseries" + } + ], + "title": "Row Panel: nested panels should also migrate", + "type": "row" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V33 Panel Datasource Name to Ref Test" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v33.panel_ds_name_to_ref.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel Datasource: null → should stay null", - "description": "Tests v33 migration behavior when panel datasource is explicitly null. Should remain null after migration (returnDefaultAsNull: true).", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "loki", - "version": "v0", - "datasource": { - "name": "non-default-test-ds-uid" - }, - "spec": { - "description": "Target with UID reference should migrate to full object" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-10": { - "kind": "Panel", - "spec": { - "id": 10, - "title": "Nested Panel: string datasource → should migrate to object", - "description": "Nested panel with string datasource should migrate to proper object reference, proving row panel recursion works.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "description": "Nested target should also migrate from string to object" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Panel Datasource: existing object → should stay unchanged", - "description": "Tests v33 migration behavior when panel datasource is already a proper object reference. Should remain unchanged.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": { - "description": "Target with existing object should remain unchanged" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel Datasource: string name → should migrate to object", - "description": "Tests v33 migration when panel datasource is a string name. Should convert to proper object with uid, type, apiVersion.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "loki", - "version": "v0", - "datasource": { - "name": "non-default-test-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel Datasource: string name with empty targets → should migrate", - "description": "Tests v33 migration when panel has datasource string but empty targets array. Panel datasource should still migrate.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Target Datasources: mixed null/string/non-existing scenarios", - "description": "Tests v33 target migration with various edge cases: null target (unchanged), valid string (migrated), non-existing string (preserved), missing datasource field (unchanged).", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "loki", - "version": "v0", - "datasource": { - "name": "non-default-test-ds-uid" - }, - "spec": { - "description": "Null target datasource should remain null" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "description": "Valid string should migrate to object" - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "non-existing-ds" - }, - "spec": { - "description": "Non-existing datasource should be preserved as-is (migration returns nil)" - } - }, - "refId": "C", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "loki", - "version": "v0", - "datasource": { - "name": "non-default-test-ds-uid" - }, - "spec": { - "description": "Target without datasource field should remain unchanged" - } - }, - "refId": "D", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Panel: null datasource with mixed target types", - "description": "Tests v33 migration when panel datasource is null but targets have mixed reference types (object, string). Panel should stay null, targets should migrate appropriately.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "existing-ref" - }, - "spec": { - "description": "Existing object target should remain unchanged" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "loki", - "version": "v0", - "datasource": { - "name": "non-default-test-ds-uid" - }, - "spec": { - "description": "String target should migrate to object" - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "description": "Default datasource string should migrate to object" - } - }, - "refId": "C", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Empty string datasource → should return empty object {}", - "description": "Tests v33 migration behavior with empty string datasource. Should migrate to empty object {} based on MigrateDatasourceNameToRef logic.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "spec": { - "description": "Empty string target should also migrate to empty object {}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Non-existing datasources → should be preserved as-is", - "description": "Tests v33 migration with completely unknown datasource names. Since migration returns nil for unknown datasources, they should be preserved unchanged.", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "also-missing-ds" - }, - "spec": { - "description": "Unknown target datasource should remain unchanged (migration returns nil)" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "completely-missing-ds" - }, - "spec": { - "description": "Empty string target should migrate to {}" - } - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": true, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row Panel: nested panels should also migrate", - "collapse": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-10" - } - } - } - ] - } - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V33 Panel Datasource Name to Ref Test", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v34.multiple_stats_cloudwatch.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v34.multiple_stats_cloudwatch.v0alpha1.json index 12b14926782..af5a9eb4fb2 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v34.multiple_stats_cloudwatch.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v34.multiple_stats_cloudwatch.v0alpha1.json @@ -4,1980 +4,1063 @@ "metadata": { "name": "v34.multiple_stats_cloudwatch.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-123456" + }, + "enable": true, + "hide": false, + "iconColor": "red", + "name": "CloudWatch Annotation Single Statistic", + "namespace": "AWS/EC2", + "prefixMatching": false, + "region": "us-east-1", + "statistic": "Average" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-789012" + }, + "enable": true, + "hide": false, + "iconColor": "blue", + "name": "CloudWatch Annotation Multiple Statistics - Maximum", + "namespace": "AWS/RDS", + "prefixMatching": false, + "region": "us-west-2", + "statistic": "Maximum" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "LoadBalancer": "my-lb" + }, + "enable": true, + "hide": false, + "iconColor": "green", + "name": "CloudWatch Annotation Empty Statistics", + "namespace": "AWS/ApplicationELB", + "prefixMatching": false, + "region": "us-west-1" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "TableName": "my-table" + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "CloudWatch Annotation Invalid Statistics - InvalidStat", + "namespace": "AWS/DynamoDB", + "prefixMatching": false, + "region": "us-east-1", + "statistic": "InvalidStat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-null-annotation" + }, + "enable": true, + "hide": false, + "iconColor": "orange", + "name": "CloudWatch Annotation with Null in Statistics - null", + "namespace": "AWS/EC2", + "prefixMatching": false, + "region": "us-east-1" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-invalid-annotation" + }, + "enable": true, + "hide": false, + "iconColor": "pink", + "name": "CloudWatch Annotation Only Invalid Statistics - 123", + "namespace": "AWS/EC2", + "prefixMatching": false, + "region": "us-east-1", + "statistic": 123 + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "enable": true, + "hide": false, + "iconColor": "purple", + "name": "Non-CloudWatch Annotation" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-789012" + }, + "enable": true, + "hide": false, + "iconColor": "blue", + "name": "CloudWatch Annotation Multiple Statistics - Minimum", + "namespace": "AWS/RDS", + "prefixMatching": false, + "region": "us-west-2", + "statistic": "Minimum" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-789012" + }, + "enable": true, + "hide": false, + "iconColor": "blue", + "name": "CloudWatch Annotation Multiple Statistics - Sum", + "namespace": "AWS/RDS", + "prefixMatching": false, + "region": "us-west-2", + "statistic": "Sum" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "TableName": "my-table" + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "CloudWatch Annotation Invalid Statistics - Sum", + "namespace": "AWS/DynamoDB", + "prefixMatching": false, + "region": "us-east-1", + "statistic": "Sum" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "TableName": "my-table" + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "CloudWatch Annotation Invalid Statistics - null", + "namespace": "AWS/DynamoDB", + "prefixMatching": false, + "region": "us-east-1" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "TableName": "my-table" + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "CloudWatch Annotation Invalid Statistics - Average", + "namespace": "AWS/DynamoDB", + "prefixMatching": false, + "region": "us-east-1", + "statistic": "Average" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-null-annotation" + }, + "enable": true, + "hide": false, + "iconColor": "orange", + "name": "CloudWatch Annotation with Null in Statistics - Average", + "namespace": "AWS/EC2", + "prefixMatching": false, + "region": "us-east-1", + "statistic": "Average" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-null-annotation" + }, + "enable": true, + "hide": false, + "iconColor": "orange", + "name": "CloudWatch Annotation with Null in Statistics - ", + "namespace": "AWS/EC2", + "prefixMatching": false, + "region": "us-east-1", + "statistic": "" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-invalid-annotation" + }, + "enable": true, + "hide": false, + "iconColor": "pink", + "name": "CloudWatch Annotation Only Invalid Statistics - true", + "namespace": "AWS/EC2", + "prefixMatching": false, + "region": "us-east-1", + "statistic": true + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-invalid-annotation" + }, + "enable": true, + "hide": false, + "iconColor": "pink", + "name": "CloudWatch Annotation Only Invalid Statistics - [object Object]", + "namespace": "AWS/EC2", + "prefixMatching": false, + "region": "us-east-1", + "statistic": {} + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-123456" + }, + "metricEditorMode": 0, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "period": "300", + "refId": "A", + "region": "us-east-1", + "statistic": "Average" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-123456" + }, + "metricEditorMode": 0, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "period": "300", + "refId": "B", + "region": "us-east-1", + "statistic": "Maximum" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-123456" + }, + "metricEditorMode": 0, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "period": "300", + "refId": "C", + "region": "us-east-1", + "statistic": "Minimum" + } + ], + "title": "CloudWatch Single Query Multiple Statistics", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "LoadBalancer": "my-load-balancer" + }, + "metricEditorMode": 0, + "metricName": "RequestCount", + "metricQueryType": 0, + "namespace": "AWS/ApplicationELB", + "refId": "A", + "region": "us-west-2", + "statistic": "Sum" + } + ], + "title": "CloudWatch Single Query Single Statistic", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "DBInstanceIdentifier": "my-db" + }, + "metricEditorMode": 0, + "metricName": "DatabaseConnections", + "metricQueryType": 0, + "namespace": "AWS/RDS", + "refId": "A", + "region": "us-east-1", + "statistic": "Maximum" + } + ], + "title": "CloudWatch Query No Statistics Array", + "type": "timeseries" + }, + { + "datasource": { + "type": "mixed", + "uid": "-- Mixed --" + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "QueueName": "my-queue" + }, + "metricEditorMode": 0, + "metricName": "ApproximateNumberOfMessages", + "metricQueryType": 0, + "namespace": "AWS/SQS", + "refId": "A", + "region": "us-east-1", + "statistic": "Average" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "expr": "up", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "TopicName": "my-topic" + }, + "metricEditorMode": 0, + "metricName": "NumberOfMessagesPublished", + "metricQueryType": 0, + "namespace": "AWS/SNS", + "refId": "C", + "region": "us-west-1", + "statistic": "Sum" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "QueueName": "my-queue" + }, + "metricEditorMode": 0, + "metricName": "ApproximateNumberOfMessages", + "metricQueryType": 0, + "namespace": "AWS/SQS", + "refId": "D", + "region": "us-east-1", + "statistic": "Maximum" + } + ], + "title": "Mixed CloudWatch and Non-CloudWatch Queries", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "BucketName": "my-bucket" + }, + "metricEditorMode": 0, + "metricName": "BucketSizeBytes", + "metricQueryType": 0, + "namespace": "AWS/S3", + "refId": "A", + "region": "us-east-1" + } + ], + "title": "CloudWatch Query Empty Statistics", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "FunctionName": "my-function" + }, + "metricEditorMode": 0, + "metricName": "Duration", + "metricQueryType": 0, + "namespace": "AWS/Lambda", + "refId": "A", + "region": "us-west-2", + "statistic": "InvalidStat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "FunctionName": "my-function" + }, + "metricEditorMode": 0, + "metricName": "Duration", + "metricQueryType": 0, + "namespace": "AWS/Lambda", + "refId": "B", + "region": "us-west-2", + "statistic": "Average" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "FunctionName": "my-function" + }, + "metricEditorMode": 0, + "metricName": "Duration", + "metricQueryType": 0, + "namespace": "AWS/Lambda", + "refId": "C", + "region": "us-west-2" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "FunctionName": "my-function" + }, + "metricEditorMode": 0, + "metricName": "Duration", + "metricQueryType": 0, + "namespace": "AWS/Lambda", + "refId": "D", + "region": "us-west-2", + "statistic": "Maximum" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "FunctionName": "my-function" + }, + "metricEditorMode": 0, + "metricName": "Duration", + "metricQueryType": 0, + "namespace": "AWS/Lambda", + "refId": "E", + "region": "us-west-2", + "statistic": "" + } + ], + "title": "CloudWatch Query Invalid Statistics", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": -1, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "StreamName": "my-stream" + }, + "metricEditorMode": 0, + "metricName": "IncomingRecords", + "metricQueryType": 0, + "namespace": "AWS/Kinesis", + "refId": "A", + "region": "us-east-1", + "statistic": "Sum" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "StreamName": "my-stream" + }, + "metricEditorMode": 0, + "metricName": "IncomingRecords", + "metricQueryType": 0, + "namespace": "AWS/Kinesis", + "refId": "B", + "region": "us-east-1", + "statistic": "Average" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "StreamName": "my-stream" + }, + "metricEditorMode": 0, + "metricName": "IncomingRecords", + "metricQueryType": 0, + "namespace": "AWS/Kinesis", + "refId": "C", + "region": "us-east-1", + "statistic": "Maximum" + } + ], + "title": "Nested CloudWatch Query Multiple Statistics", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 9, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "ClusterName": "my-cluster" + }, + "metricEditorMode": 1, + "metricName": "CPUUtilization", + "metricQueryType": 1, + "namespace": "AWS/ECS", + "period": "300", + "refId": "A", + "region": "us-east-1", + "statistic": "Average" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "ClusterName": "my-cluster" + }, + "metricEditorMode": 1, + "metricName": "CPUUtilization", + "metricQueryType": 1, + "namespace": "AWS/ECS", + "period": "300", + "refId": "B", + "region": "us-east-1", + "statistic": "Maximum" + } + ], + "title": "CloudWatch Query with Existing Editor Mode", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 10, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-missing-fields" + }, + "metricEditorMode": 0, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "refId": "A", + "region": "us-east-1", + "statistic": "Average" + } + ], + "title": "CloudWatch Query Missing Editor Fields", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 11, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-with-expression" + }, + "expression": "SEARCH('{AWS/EC2,InstanceId} MetricName=\"CPUUtilization\"', 'Average', 300)", + "metricEditorMode": 1, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "refId": "A", + "region": "us-east-1", + "statistic": "Average" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-with-expression" + }, + "expression": "SEARCH('{AWS/EC2,InstanceId} MetricName=\"CPUUtilization\"', 'Average', 300)", + "metricEditorMode": 1, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "refId": "B", + "region": "us-east-1", + "statistic": "Maximum" + } + ], + "title": "CloudWatch Query with Expression (Code Mode)", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 12, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-insights" + }, + "metricEditorMode": 1, + "metricName": "CPUUtilization", + "metricQueryType": 1, + "namespace": "AWS/EC2", + "refId": "A", + "region": "us-east-1", + "statistic": "Average" + } + ], + "title": "CloudWatch Insights Query Missing Editor Mode", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 13, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-null-stats" + }, + "metricEditorMode": 0, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "refId": "A", + "region": "us-east-1" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-null-stats" + }, + "metricEditorMode": 0, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "refId": "B", + "region": "us-east-1", + "statistic": "Average" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-null-stats" + }, + "metricEditorMode": 0, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "refId": "C", + "region": "us-east-1", + "statistic": "" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-null-stats" + }, + "metricEditorMode": 0, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "refId": "D", + "region": "us-east-1", + "statistic": "Maximum" + } + ], + "title": "CloudWatch Query with Null Statistics", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 14, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-invalid-only" + }, + "metricEditorMode": 0, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "refId": "A", + "region": "us-east-1", + "statistic": 123 + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-invalid-only" + }, + "metricEditorMode": 0, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "refId": "B", + "region": "us-east-1", + "statistic": true + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-invalid-only" + }, + "metricEditorMode": 0, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "refId": "C", + "region": "us-east-1", + "statistic": {} + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "dimensions": { + "InstanceId": "i-invalid-only" + }, + "metricEditorMode": 0, + "metricName": "CPUUtilization", + "metricQueryType": 0, + "namespace": "AWS/EC2", + "refId": "D", + "region": "us-east-1", + "statistic": [] + } + ], + "title": "CloudWatch Query with Only Invalid Statistics", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 15, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "expr": "cpu_usage", + "refId": "A" + } + ], + "title": "Non-CloudWatch Panel", + "type": "timeseries" + } + ], + "title": "Collapsed Row with CloudWatch", + "type": "row" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "CloudWatch Multiple Statistics Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v34.multiple_stats_cloudwatch.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "red", - "name": "CloudWatch Annotation Single Statistic", - "legacyOptions": { - "dimensions": { - "InstanceId": "i-123456" - }, - "namespace": "AWS/EC2", - "prefixMatching": false, - "region": "us-east-1", - "statistic": "Average" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "blue", - "name": "CloudWatch Annotation Multiple Statistics - Maximum", - "legacyOptions": { - "dimensions": { - "InstanceId": "i-789012" - }, - "namespace": "AWS/RDS", - "prefixMatching": false, - "region": "us-west-2", - "statistic": "Maximum" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "green", - "name": "CloudWatch Annotation Empty Statistics", - "legacyOptions": { - "dimensions": { - "LoadBalancer": "my-lb" - }, - "namespace": "AWS/ApplicationELB", - "prefixMatching": false, - "region": "us-west-1" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "yellow", - "name": "CloudWatch Annotation Invalid Statistics - InvalidStat", - "legacyOptions": { - "dimensions": { - "TableName": "my-table" - }, - "namespace": "AWS/DynamoDB", - "prefixMatching": false, - "region": "us-east-1", - "statistic": "InvalidStat" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "orange", - "name": "CloudWatch Annotation with Null in Statistics - null", - "legacyOptions": { - "dimensions": { - "InstanceId": "i-null-annotation" - }, - "namespace": "AWS/EC2", - "prefixMatching": false, - "region": "us-east-1" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "pink", - "name": "CloudWatch Annotation Only Invalid Statistics - 123", - "legacyOptions": { - "dimensions": { - "InstanceId": "i-invalid-annotation" - }, - "namespace": "AWS/EC2", - "prefixMatching": false, - "region": "us-east-1", - "statistic": 123 - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "purple", - "name": "Non-CloudWatch Annotation" - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "blue", - "name": "CloudWatch Annotation Multiple Statistics - Minimum", - "legacyOptions": { - "dimensions": { - "InstanceId": "i-789012" - }, - "namespace": "AWS/RDS", - "prefixMatching": false, - "region": "us-west-2", - "statistic": "Minimum" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "blue", - "name": "CloudWatch Annotation Multiple Statistics - Sum", - "legacyOptions": { - "dimensions": { - "InstanceId": "i-789012" - }, - "namespace": "AWS/RDS", - "prefixMatching": false, - "region": "us-west-2", - "statistic": "Sum" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "yellow", - "name": "CloudWatch Annotation Invalid Statistics - Sum", - "legacyOptions": { - "dimensions": { - "TableName": "my-table" - }, - "namespace": "AWS/DynamoDB", - "prefixMatching": false, - "region": "us-east-1", - "statistic": "Sum" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "yellow", - "name": "CloudWatch Annotation Invalid Statistics - null", - "legacyOptions": { - "dimensions": { - "TableName": "my-table" - }, - "namespace": "AWS/DynamoDB", - "prefixMatching": false, - "region": "us-east-1" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "yellow", - "name": "CloudWatch Annotation Invalid Statistics - Average", - "legacyOptions": { - "dimensions": { - "TableName": "my-table" - }, - "namespace": "AWS/DynamoDB", - "prefixMatching": false, - "region": "us-east-1", - "statistic": "Average" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "orange", - "name": "CloudWatch Annotation with Null in Statistics - Average", - "legacyOptions": { - "dimensions": { - "InstanceId": "i-null-annotation" - }, - "namespace": "AWS/EC2", - "prefixMatching": false, - "region": "us-east-1", - "statistic": "Average" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "orange", - "name": "CloudWatch Annotation with Null in Statistics - ", - "legacyOptions": { - "dimensions": { - "InstanceId": "i-null-annotation" - }, - "namespace": "AWS/EC2", - "prefixMatching": false, - "region": "us-east-1", - "statistic": "" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "pink", - "name": "CloudWatch Annotation Only Invalid Statistics - true", - "legacyOptions": { - "dimensions": { - "InstanceId": "i-invalid-annotation" - }, - "namespace": "AWS/EC2", - "prefixMatching": false, - "region": "us-east-1", - "statistic": true - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "pink", - "name": "CloudWatch Annotation Only Invalid Statistics - [object Object]", - "legacyOptions": { - "dimensions": { - "InstanceId": "i-invalid-annotation" - }, - "namespace": "AWS/EC2", - "prefixMatching": false, - "region": "us-east-1", - "statistic": {} - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "CloudWatch Single Query Multiple Statistics", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-123456" - }, - "metricEditorMode": 0, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "period": "300", - "region": "us-east-1", - "statistic": "Average" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-123456" - }, - "metricEditorMode": 0, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "period": "300", - "region": "us-east-1", - "statistic": "Maximum" - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-123456" - }, - "metricEditorMode": 0, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "period": "300", - "region": "us-east-1", - "statistic": "Minimum" - } - }, - "refId": "C", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-10": { - "kind": "Panel", - "spec": { - "id": 10, - "title": "CloudWatch Query Missing Editor Fields", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-missing-fields" - }, - "metricEditorMode": 0, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "region": "us-east-1", - "statistic": "Average" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-11": { - "kind": "Panel", - "spec": { - "id": 11, - "title": "CloudWatch Query with Expression (Code Mode)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-with-expression" - }, - "expression": "SEARCH('{AWS/EC2,InstanceId} MetricName=\"CPUUtilization\"', 'Average', 300)", - "metricEditorMode": 1, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "region": "us-east-1", - "statistic": "Average" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-with-expression" - }, - "expression": "SEARCH('{AWS/EC2,InstanceId} MetricName=\"CPUUtilization\"', 'Average', 300)", - "metricEditorMode": 1, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "region": "us-east-1", - "statistic": "Maximum" - } - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-12": { - "kind": "Panel", - "spec": { - "id": 12, - "title": "CloudWatch Insights Query Missing Editor Mode", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-insights" - }, - "metricEditorMode": 1, - "metricName": "CPUUtilization", - "metricQueryType": 1, - "namespace": "AWS/EC2", - "region": "us-east-1", - "statistic": "Average" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-13": { - "kind": "Panel", - "spec": { - "id": 13, - "title": "CloudWatch Query with Null Statistics", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-null-stats" - }, - "metricEditorMode": 0, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "region": "us-east-1" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-null-stats" - }, - "metricEditorMode": 0, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "region": "us-east-1", - "statistic": "Average" - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-null-stats" - }, - "metricEditorMode": 0, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "region": "us-east-1", - "statistic": "" - } - }, - "refId": "C", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-null-stats" - }, - "metricEditorMode": 0, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "region": "us-east-1", - "statistic": "Maximum" - } - }, - "refId": "D", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-14": { - "kind": "Panel", - "spec": { - "id": 14, - "title": "CloudWatch Query with Only Invalid Statistics", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-invalid-only" - }, - "metricEditorMode": 0, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "region": "us-east-1", - "statistic": 123 - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-invalid-only" - }, - "metricEditorMode": 0, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "region": "us-east-1", - "statistic": true - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-invalid-only" - }, - "metricEditorMode": 0, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "region": "us-east-1", - "statistic": {} - } - }, - "refId": "C", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "InstanceId": "i-invalid-only" - }, - "metricEditorMode": 0, - "metricName": "CPUUtilization", - "metricQueryType": 0, - "namespace": "AWS/EC2", - "region": "us-east-1", - "statistic": [] - } - }, - "refId": "D", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-15": { - "kind": "Panel", - "spec": { - "id": 15, - "title": "Non-CloudWatch Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "prometheus" - }, - "spec": { - "expr": "cpu_usage" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "CloudWatch Single Query Single Statistic", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "LoadBalancer": "my-load-balancer" - }, - "metricEditorMode": 0, - "metricName": "RequestCount", - "metricQueryType": 0, - "namespace": "AWS/ApplicationELB", - "region": "us-west-2", - "statistic": "Sum" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "CloudWatch Query No Statistics Array", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "DBInstanceIdentifier": "my-db" - }, - "metricEditorMode": 0, - "metricName": "DatabaseConnections", - "metricQueryType": 0, - "namespace": "AWS/RDS", - "region": "us-east-1", - "statistic": "Maximum" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Mixed CloudWatch and Non-CloudWatch Queries", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "QueueName": "my-queue" - }, - "metricEditorMode": 0, - "metricName": "ApproximateNumberOfMessages", - "metricQueryType": 0, - "namespace": "AWS/SQS", - "region": "us-east-1", - "statistic": "Average" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "prometheus" - }, - "spec": { - "expr": "up" - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "TopicName": "my-topic" - }, - "metricEditorMode": 0, - "metricName": "NumberOfMessagesPublished", - "metricQueryType": 0, - "namespace": "AWS/SNS", - "region": "us-west-1", - "statistic": "Sum" - } - }, - "refId": "C", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "QueueName": "my-queue" - }, - "metricEditorMode": 0, - "metricName": "ApproximateNumberOfMessages", - "metricQueryType": 0, - "namespace": "AWS/SQS", - "region": "us-east-1", - "statistic": "Maximum" - } - }, - "refId": "D", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "CloudWatch Query Empty Statistics", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "BucketName": "my-bucket" - }, - "metricEditorMode": 0, - "metricName": "BucketSizeBytes", - "metricQueryType": 0, - "namespace": "AWS/S3", - "region": "us-east-1" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "CloudWatch Query Invalid Statistics", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "FunctionName": "my-function" - }, - "metricEditorMode": 0, - "metricName": "Duration", - "metricQueryType": 0, - "namespace": "AWS/Lambda", - "region": "us-west-2", - "statistic": "InvalidStat" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "FunctionName": "my-function" - }, - "metricEditorMode": 0, - "metricName": "Duration", - "metricQueryType": 0, - "namespace": "AWS/Lambda", - "region": "us-west-2", - "statistic": "Average" - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "FunctionName": "my-function" - }, - "metricEditorMode": 0, - "metricName": "Duration", - "metricQueryType": 0, - "namespace": "AWS/Lambda", - "region": "us-west-2" - } - }, - "refId": "C", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "FunctionName": "my-function" - }, - "metricEditorMode": 0, - "metricName": "Duration", - "metricQueryType": 0, - "namespace": "AWS/Lambda", - "region": "us-west-2", - "statistic": "Maximum" - } - }, - "refId": "D", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "FunctionName": "my-function" - }, - "metricEditorMode": 0, - "metricName": "Duration", - "metricQueryType": 0, - "namespace": "AWS/Lambda", - "region": "us-west-2", - "statistic": "" - } - }, - "refId": "E", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Nested CloudWatch Query Multiple Statistics", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "StreamName": "my-stream" - }, - "metricEditorMode": 0, - "metricName": "IncomingRecords", - "metricQueryType": 0, - "namespace": "AWS/Kinesis", - "region": "us-east-1", - "statistic": "Sum" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "StreamName": "my-stream" - }, - "metricEditorMode": 0, - "metricName": "IncomingRecords", - "metricQueryType": 0, - "namespace": "AWS/Kinesis", - "region": "us-east-1", - "statistic": "Average" - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "StreamName": "my-stream" - }, - "metricEditorMode": 0, - "metricName": "IncomingRecords", - "metricQueryType": 0, - "namespace": "AWS/Kinesis", - "region": "us-east-1", - "statistic": "Maximum" - } - }, - "refId": "C", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-9": { - "kind": "Panel", - "spec": { - "id": 9, - "title": "CloudWatch Query with Existing Editor Mode", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "ClusterName": "my-cluster" - }, - "metricEditorMode": 1, - "metricName": "CPUUtilization", - "metricQueryType": 1, - "namespace": "AWS/ECS", - "period": "300", - "region": "us-east-1", - "statistic": "Average" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "dimensions": { - "ClusterName": "my-cluster" - }, - "metricEditorMode": 1, - "metricName": "CPUUtilization", - "metricQueryType": 1, - "namespace": "AWS/ECS", - "period": "300", - "region": "us-east-1", - "statistic": "Maximum" - } - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": true, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Collapsed Row with CloudWatch", - "collapse": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-9" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-10" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-11" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-12" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-13" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-14" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-15" - } - } - } - ] - } - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "CloudWatch Multiple Statistics Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v35.ensure_x_axis_visibility.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v35.ensure_x_axis_visibility.v0alpha1.json index 4aa5fd009aa..83e0d94fd78 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v35.ensure_x_axis_visibility.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v35.ensure_x_axis_visibility.v0alpha1.json @@ -4,628 +4,327 @@ "metadata": { "name": "v35.ensure_x_axis_visibility.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v35.ensure_x_axis_visibility.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-10": { - "kind": "Panel", - "spec": { - "id": 10, - "title": "Timeseries with Missing Defaults", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-11": { - "kind": "Panel", - "spec": { - "id": 11, - "title": "Timeseries with Missing Custom Config", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "unit": "bytes" - }, - "overrides": [] - } - } - } - } - }, - "panel-12": { - "kind": "Panel", - "spec": { - "id": 12, - "title": "Timeseries with Missing Overrides Array", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "axisPlacement": "hidden" - } - }, - "overrides": [ - { - "matcher": { - "id": "byType", - "options": "time" - }, - "properties": [ - { - "id": "custom.axisPlacement", - "value": "auto" - } - ] - } - ] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Timeseries with Missing FieldConfig", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Timeseries with Hidden Axis", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "axisPlacement": "hidden" - } - }, - "overrides": [ - { - "matcher": { - "id": "byType", - "options": "time" - }, - "properties": [ - { - "id": "custom.axisPlacement", - "value": "auto" - } - ] - } - ] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Timeseries with Hidden Axis and Existing Overrides", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "axisPlacement": "hidden" - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Series A" - }, - "properties": [ - { - "id": "color.mode", - "value": "palette-classic" - } - ] - }, - { - "matcher": { - "id": "byType", - "options": "time" - }, - "properties": [ - { - "id": "custom.axisPlacement", - "value": "auto" - } - ] - } - ] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Timeseries with Auto Axis (No Change Expected)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "axisPlacement": "auto" - } - }, - "overrides": [] - } - } - } - } - }, - "panel-9": { - "kind": "Panel", - "spec": { - "id": 9, - "title": "Stat Panel with Hidden Axis (No Change Expected)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "axisPlacement": "hidden" - } - }, - "overrides": [] - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "fieldConfig": { + "defaults": { + "custom": { + "axisPlacement": "hidden" } }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ + "overrides": [ + { + "matcher": { + "id": "byType", + "options": "time" + }, + "properties": [ { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-9" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-10" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-11" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-12" - } - } + "id": "custom.axisPlacement", + "value": "auto" } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "X-Axis Visibility Test Dashboard", - "variables": [] + ] }, - "status": {} + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Timeseries with Hidden Axis", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "axisPlacement": "hidden" + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Series A" + }, + "properties": [ + { + "id": "color.mode", + "value": "palette-classic" + } + ] + }, + { + "matcher": { + "id": "byType", + "options": "time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "auto" + } + ] + } + ] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 7, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Timeseries with Hidden Axis and Existing Overrides", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "axisPlacement": "auto" + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Timeseries with Auto Axis (No Change Expected)", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "axisPlacement": "hidden" + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 9, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Stat Panel with Hidden Axis (No Change Expected)", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Timeseries with Missing FieldConfig", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 10, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Timeseries with Missing Defaults", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "unit": "bytes" + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 11, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Timeseries with Missing Custom Config", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "axisPlacement": "hidden" + } + }, + "overrides": [ + { + "matcher": { + "id": "byType", + "options": "time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "auto" + } + ] + } + ] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 12, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Timeseries with Missing Overrides Array", + "type": "timeseries" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "X-Axis Visibility Test Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v36.ds_name_to_ref.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v36.ds_name_to_ref.v0alpha1.json index f1aaa0a3418..6cfba3afdaf 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v36.ds_name_to_ref.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v36.ds_name_to_ref.v0alpha1.json @@ -4,1081 +4,528 @@ "metadata": { "name": "v36.ds_name_to_ref.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "enable": false, + "hide": false, + "iconColor": "", + "name": "Default Annotation - Tests default datasource migration" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "enable": false, + "hide": false, + "iconColor": "", + "name": "Named Datasource Annotation - Tests migration by datasource name" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "enable": false, + "hide": false, + "iconColor": "", + "name": "UID Datasource Annotation - Tests migration by datasource UID" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "enable": false, + "hide": false, + "iconColor": "", + "name": "Null Datasource Annotation - Tests null datasource fallback to default" + }, + { + "datasource": { + "type": "prometheus", + "uid": "unknown-datasource-name" + }, + "enable": false, + "hide": false, + "iconColor": "", + "name": "Unknown Datasource Annotation - Tests unknown datasource preserved as UID" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "description": "Tests null panel datasource migration with targets - should fallback to default", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with Null Datasource and Targets", + "type": "timeseries" + }, + { + "description": "Tests null panel datasource with empty targets array - should create default target", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with Null Datasource and Empty Targets", + "type": "timeseries" + }, + { + "description": "Tests null panel datasource with missing targets - should create default target array", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "Panel with No Targets Array", + "type": "timeseries" + }, + { + "datasource": { + "type": "mixed", + "uid": "-- Mixed --" + }, + "description": "Tests mixed datasource panel - targets should migrate independently", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "refId": "B" + } + ], + "title": "Panel with Mixed Datasources", + "type": "timeseries" + }, + { + "description": "Tests panel with already migrated datasource object - should preserve existing refs", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "refId": "A" + } + ], + "title": "Panel with Existing Object Datasource", + "type": "timeseries" + }, + { + "description": "Tests panel with unknown datasource - should preserve as UID-only reference", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "unknown-target-datasource" + }, + "refId": "A" + } + ], + "title": "Panel with Unknown Datasource Name", + "type": "timeseries" + }, + { + "datasource": { + "type": "mixed", + "uid": "-- Mixed --" + }, + "description": "Tests panel with expression query - should not inherit expression as panel datasource", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 7, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "refId": "A" + }, + { + "datasource": { + "type": "__expr__", + "uid": "__expr__" + }, + "refId": "B" + } + ], + "title": "Panel with Expression Query", + "type": "timeseries" + }, + { + "description": "Tests panel inheriting datasource from target when panel datasource was default", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "refId": "A" + } + ], + "title": "Panel Inheriting from Target", + "type": "timeseries" + }, + { + "description": "Tests panel with datasource referenced by name - should migrate to full object", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 9, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "refId": "A" + } + ], + "title": "Panel with Named Datasource", + "type": "timeseries" + }, + { + "description": "Tests panel with datasource referenced by UID - should migrate to full object", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 10, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "refId": "A" + } + ], + "title": "Panel with UID Datasource", + "type": "timeseries" + }, + { + "collapsed": false, + "id": -1, + "title": "Simple Row Panel", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": -1, + "panels": [ + { + "description": "Nested panel in collapsed row with default datasource", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 1 + }, + "id": 13, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "refId": "A" + } + ], + "title": "Nested Panel with Default Datasource", + "type": "timeseries" + }, + { + "description": "Nested panel in collapsed row with unknown datasource", + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 1 + }, + "id": 14, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "refId": "A" + } + ], + "title": "Nested Panel with Unknown Datasource", + "type": "timeseries" + } + ], + "title": "Collapsed Row with Nested Panels", + "type": "row" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "query_var_null", + "options": [], + "query": {}, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "query_var_named", + "options": [], + "query": {}, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "query_var_uid", + "options": [], + "query": {}, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "unknown-datasource" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "query_var_unknown", + "options": [], + "query": {}, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "text": "", + "value": "" + }, + "hide": 2, + "name": "non_query_var", + "query": "", + "skipUrlSync": false, + "type": "constant" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Datasource Reference Migration Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v36.ds_name_to_ref.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": false, - "hide": false, - "iconColor": "", - "name": "Default Annotation - Tests default datasource migration" - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": {} - }, - "enable": false, - "hide": false, - "iconColor": "", - "name": "Named Datasource Annotation - Tests migration by datasource name" - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": {} - }, - "enable": false, - "hide": false, - "iconColor": "", - "name": "UID Datasource Annotation - Tests migration by datasource UID" - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": false, - "hide": false, - "iconColor": "", - "name": "Null Datasource Annotation - Tests null datasource fallback to default" - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "unknown-datasource-name" - }, - "spec": {} - }, - "enable": false, - "hide": false, - "iconColor": "", - "name": "Unknown Datasource Annotation - Tests unknown datasource preserved as UID" - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with Null Datasource and Targets", - "description": "Tests null panel datasource migration with targets - should fallback to default", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-10": { - "kind": "Panel", - "spec": { - "id": 10, - "title": "Panel with UID Datasource", - "description": "Tests panel with datasource referenced by UID - should migrate to full object", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-13": { - "kind": "Panel", - "spec": { - "id": 13, - "title": "Nested Panel with Default Datasource", - "description": "Nested panel in collapsed row with default datasource", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-14": { - "kind": "Panel", - "spec": { - "id": 14, - "title": "Nested Panel with Unknown Datasource", - "description": "Nested panel in collapsed row with unknown datasource", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Panel with Null Datasource and Empty Targets", - "description": "Tests null panel datasource with empty targets array - should create default target", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel with No Targets Array", - "description": "Tests null panel datasource with missing targets - should create default target array", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel with Mixed Datasources", - "description": "Tests mixed datasource panel - targets should migrate independently", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": {} - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Panel with Existing Object Datasource", - "description": "Tests panel with already migrated datasource object - should preserve existing refs", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Panel with Unknown Datasource Name", - "description": "Tests panel with unknown datasource - should preserve as UID-only reference", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "unknown-target-datasource" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Panel with Expression Query", - "description": "Tests panel with expression query - should not inherit expression as panel datasource", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "__expr__", - "version": "v0", - "datasource": { - "name": "__expr__" - }, - "spec": {} - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Panel Inheriting from Target", - "description": "Tests panel inheriting datasource from target when panel datasource was default", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-9": { - "kind": "Panel", - "spec": { - "id": 9, - "title": "Panel with Named Datasource", - "description": "Tests panel with datasource referenced by name - should migrate to full object", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-9" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-10" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Simple Row Panel", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Collapsed Row with Nested Panels", - "collapse": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-13" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-14" - } - } - } - ] - } - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Datasource Reference Migration Test Dashboard", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "query_var_null", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "never", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "query_var_named", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "never", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "query_var_uid", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "never", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "existing-target-uid" - }, - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "query_var_unknown", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "never", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "unknown-datasource" - }, - "spec": {} - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "ConstantVariable", - "spec": { - "name": "non_query_var", - "query": "", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "skipUrlSync": false - } - } - ] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v37.legend_normalization.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v37.legend_normalization.v0alpha1.json index 4df4909750e..02605744e6d 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v37.legend_normalization.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v37.legend_normalization.v0alpha1.json @@ -4,658 +4,279 @@ "metadata": { "name": "v37.legend_normalization.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": true + }, + "pluginVersion": "", + "targets": [], + "title": "Panel with Boolean Legend True", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "legend": false + }, + "pluginVersion": "", + "targets": [], + "title": "Panel with Boolean Legend False", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "displayMode": "list", + "showLegend": false + } + }, + "pluginVersion": "", + "targets": [], + "title": "Panel with Hidden DisplayMode", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": { + "legend": { + "displayMode": "list", + "showLegend": false + } + }, + "pluginVersion": "", + "targets": [], + "title": "Panel with ShowLegend False", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": { + "legend": { + "displayMode": "table", + "placement": "bottom", + "showLegend": true + } + }, + "pluginVersion": "", + "targets": [], + "title": "Panel with Table Legend", + "type": "barchart" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": { + "legend": { + "displayMode": "list", + "placement": "right", + "showLegend": true + } + }, + "pluginVersion": "", + "targets": [], + "title": "Panel with List Legend", + "type": "histogram" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 7, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with No Options", + "type": "text" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 8, + "options": { + "reduceOptions": { + "fields": "/.*temperature.*/" + } + }, + "pluginVersion": "", + "targets": [], + "title": "Panel with No Legend Config", + "type": "gauge" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 9, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with Null Legend", + "type": "piechart" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": -1, + "title": "Row with Nested Panels Having Various Legend Configs", + "type": "row" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 11, + "options": { + "legend": true + }, + "pluginVersion": "", + "targets": [], + "title": "Nested Panel with Boolean Legend", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 12, + "options": { + "legend": { + "displayMode": "list", + "showLegend": false + } + }, + "pluginVersion": "", + "targets": [], + "title": "Nested Panel with Hidden DisplayMode", + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 13, + "options": { + "legend": { + "displayMode": "list", + "showLegend": false + } + }, + "pluginVersion": "", + "targets": [], + "title": "Nested Panel with Conflicting Properties", + "type": "stat" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V37 Legend Normalization Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v37.legend_normalization.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with Boolean Legend True", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": true - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-11": { - "kind": "Panel", - "spec": { - "id": 11, - "title": "Nested Panel with Boolean Legend", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": true - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-12": { - "kind": "Panel", - "spec": { - "id": 12, - "title": "Nested Panel with Hidden DisplayMode", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "displayMode": "list", - "showLegend": false - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-13": { - "kind": "Panel", - "spec": { - "id": 13, - "title": "Nested Panel with Conflicting Properties", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": { - "legend": { - "displayMode": "list", - "showLegend": false - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Panel with Boolean Legend False", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": false - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel with Hidden DisplayMode", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": { - "legend": { - "displayMode": "list", - "showLegend": false - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel with ShowLegend False", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": { - "legend": { - "displayMode": "list", - "showLegend": false - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Panel with Table Legend", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "barchart", - "version": "", - "spec": { - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": true - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Panel with List Legend", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "histogram", - "version": "", - "spec": { - "options": { - "legend": { - "displayMode": "list", - "placement": "right", - "showLegend": true - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Panel with No Options", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "text", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Panel with No Legend Config", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "gauge", - "version": "", - "spec": { - "options": { - "reduceOptions": { - "fields": "/.*temperature.*/" - } - }, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-9": { - "kind": "Panel", - "spec": { - "id": 9, - "title": "Panel with Null Legend", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "piechart", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-9" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row with Nested Panels Having Various Legend Configs", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-11" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-12" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-13" - } - } - } - ] - } - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V37 Legend Normalization Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v38.table_displaymode_comprehensive.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v38.table_displaymode_comprehensive.v0alpha1.json index e7b413717ff..b874385c59b 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v38.table_displaymode_comprehensive.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v38.table_displaymode_comprehensive.v0alpha1.json @@ -4,687 +4,368 @@ "metadata": { "name": "v38.table_displaymode_comprehensive.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v38.table_displaymode_comprehensive.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "basic", + "type": "gauge" } } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Table with Basic Gauge", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "basic", - "type": "gauge" - } - } - }, - "overrides": [] - } - } - } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with Basic Gauge", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "gradient", + "type": "gauge" } - }, - "panel-11": { - "kind": "Panel", - "spec": { - "id": 11, - "title": "Nested Table with Basic Mode", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "basic", - "type": "gauge" - } - } - }, - "overrides": [] - } - } - } + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with Gradient Gauge", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "lcd", + "type": "gauge" } - }, - "panel-12": { - "kind": "Panel", - "spec": { - "id": 12, - "title": "Nested Table with Gradient Gauge", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "gradient", - "type": "gauge" - } - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "NestedField" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "mode": "lcd", - "type": "gauge" - } - } - ] - } - ] - } - } - } + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with LCD Gauge", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "gradient", + "type": "color-background" } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Table with Gradient Gauge", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "gradient", - "type": "gauge" - } - } - }, - "overrides": [] - } - } - } + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with Color Background", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "basic", + "type": "color-background" } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Table with LCD Gauge", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "lcd", - "type": "gauge" - } - } - }, - "overrides": [] - } - } - } + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with Color Background Solid", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "type": "some-other-mode" } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Table with Color Background", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "gradient", - "type": "color-background" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Table with Color Background Solid", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "basic", - "type": "color-background" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Table with Unknown Mode", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "some-other-mode" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Table with No Display Mode", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "width": 100 - } - }, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Table with Overrides", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "basic", - "type": "gauge" - } - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Field1" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "mode": "gradient", - "type": "gauge" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Field2" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "mode": "gradient", - "type": "color-background" - } - } - ] - } - ] - } - } - } - } - }, - "panel-9": { - "kind": "Panel", - "spec": { - "id": 9, - "title": "Non-table Panel (Should Remain Unchanged)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with Unknown Mode", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "width": 100 + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 7, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with No Display Mode", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "basic", + "type": "gauge" } } }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Field1" + }, + "properties": [ { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-9" - } - } - } - ] - } - } + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge" } - }, + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Field2" + }, + "properties": [ { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row with Nested Table Panels", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-11" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-12" - } - } - } - ] - } - } + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "color-background" } } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V38 Table Migration Comprehensive Test Dashboard", - "variables": [] + ] }, - "status": {} + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with Overrides", + "type": "table" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 9, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Non-table Panel (Should Remain Unchanged)", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": -1, + "title": "Row with Nested Table Panels", + "type": "row" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "basic", + "type": "gauge" + } + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 11, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Nested Table with Basic Mode", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "gradient", + "type": "gauge" + } + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "NestedField" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "lcd", + "type": "gauge" + } + } + ] + } + ] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 12, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Nested Table with Gradient Gauge", + "type": "table" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V38 Table Migration Comprehensive Test Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v38.timeseries_table_display_mode.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v38.timeseries_table_display_mode.v0alpha1.json index d9de3d6d3bf..d22e01dd10d 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v38.timeseries_table_display_mode.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v38.timeseries_table_display_mode.v0alpha1.json @@ -4,687 +4,368 @@ "metadata": { "name": "v38.timeseries_table_display_mode.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v38.timeseries_table_display_mode.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "basic", + "type": "gauge" } } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Table with Basic Gauge", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "basic", - "type": "gauge" - } - } - }, - "overrides": [] - } - } - } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with Basic Gauge", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "gradient", + "type": "gauge" } - }, - "panel-11": { - "kind": "Panel", - "spec": { - "id": 11, - "title": "Nested Table with Basic Mode", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "basic", - "type": "gauge" - } - } - }, - "overrides": [] - } - } - } + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with Gradient Gauge", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "lcd", + "type": "gauge" } - }, - "panel-12": { - "kind": "Panel", - "spec": { - "id": 12, - "title": "Nested Table with Gradient Gauge", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "gradient", - "type": "gauge" - } - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "NestedField" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "mode": "lcd", - "type": "gauge" - } - } - ] - } - ] - } - } - } + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with LCD Gauge", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "gradient", + "type": "color-background" } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Table with Gradient Gauge", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "gradient", - "type": "gauge" - } - } - }, - "overrides": [] - } - } - } + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with Color Background", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "basic", + "type": "color-background" } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Table with LCD Gauge", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "lcd", - "type": "gauge" - } - } - }, - "overrides": [] - } - } - } + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with Color Background Solid", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "type": "some-other-mode" } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Table with Color Background", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "gradient", - "type": "color-background" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Table with Color Background Solid", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "basic", - "type": "color-background" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Table with Unknown Mode", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "type": "some-other-mode" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Table with No Display Mode", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "width": 100 - } - }, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Table with Overrides", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": { - "custom": { - "cellOptions": { - "mode": "basic", - "type": "gauge" - } - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Field1" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "mode": "gradient", - "type": "gauge" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Field2" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "mode": "gradient", - "type": "color-background" - } - } - ] - } - ] - } - } - } - } - }, - "panel-9": { - "kind": "Panel", - "spec": { - "id": 9, - "title": "Non-table Panel (Should Remain Unchanged)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with Unknown Mode", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "width": 100 + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 7, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with No Display Mode", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "basic", + "type": "gauge" } } }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Field1" + }, + "properties": [ { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-9" - } - } - } - ] - } - } + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge" } - }, + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Field2" + }, + "properties": [ { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row with Nested Table Panels", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-11" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-12" - } - } - } - ] - } - } + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "color-background" } } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V38 Table Migration Test Dashboard", - "variables": [] + ] }, - "status": {} + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Table with Overrides", + "type": "table" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 9, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Non-table Panel (Should Remain Unchanged)", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": -1, + "title": "Row with Nested Table Panels", + "type": "row" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "basic", + "type": "gauge" + } + } + } + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 11, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Nested Table with Basic Mode", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "custom": { + "cellOptions": { + "mode": "gradient", + "type": "gauge" + } + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "NestedField" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "lcd", + "type": "gauge" + } + } + ] + } + ] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 12, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Nested Table with Gradient Gauge", + "type": "table" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V38 Table Migration Test Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v39.transform_timeseries_table.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v39.transform_timeseries_table.v0alpha1.json index 531febf7672..e57acfe6aa2 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v39.transform_timeseries_table.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v39.transform_timeseries_table.v0alpha1.json @@ -4,612 +4,295 @@ "metadata": { "name": "v39.transform_timeseries_table.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v39.transform_timeseries_table.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with TimeSeriesTable Transformation - Single Stat", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [ - { - "kind": "timeSeriesTable", - "spec": { - "id": "timeSeriesTable", - "options": { - "A": { - "stat": "mean" - } - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-10": { - "kind": "Panel", - "spec": { - "id": 10, - "title": "Nested Panel with TimeSeriesTable", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [ - { - "kind": "timeSeriesTable", - "spec": { - "id": "timeSeriesTable", - "options": { - "NestedA": { - "stat": "median" - }, - "NestedB": { - "stat": "stdDev" - } - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Panel with TimeSeriesTable Transformation - Multiple Stats", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [ - { - "kind": "timeSeriesTable", - "spec": { - "id": "timeSeriesTable", - "options": { - "A": { - "stat": "mean" - }, - "B": { - "stat": "max" - }, - "C": { - "stat": "min" - }, - "D": { - "stat": "sum" - } - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel with TimeSeriesTable Transformation - Mixed with Other Transforms", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [ - { - "kind": "reduce", - "spec": { - "id": "reduce", - "options": { - "reducers": [ - "mean" - ] - } - } - }, - { - "kind": "timeSeriesTable", - "spec": { - "id": "timeSeriesTable", - "options": { - "A": { - "stat": "last" - }, - "B": { - "stat": "first" - } - } - } - }, - { - "kind": "organize", - "spec": { - "id": "organize", - "options": { - "excludeByName": {} - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel with Non-TimeSeriesTable Transformation (Should Remain Unchanged)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [ - { - "kind": "reduce", - "spec": { - "id": "reduce", - "options": { - "reducers": [ - "mean", - "max" - ] - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Panel with TimeSeriesTable - Empty RefIdToStat", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [ - { - "kind": "timeSeriesTable", - "spec": { - "id": "timeSeriesTable", - "options": {} - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Panel with TimeSeriesTable - No Options (Should Skip)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [ - { - "kind": "timeSeriesTable", - "spec": { - "id": "timeSeriesTable", - "options": null - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Panel with TimeSeriesTable - Invalid Options (Should Skip)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [ - { - "kind": "timeSeriesTable", - "spec": { - "id": "timeSeriesTable", - "options": { - "someOtherOption": "value" - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-8": { - "kind": "Panel", - "spec": { - "id": 8, - "title": "Panel with No Transformations (Should Remain Unchanged)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-8" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row with Nested Panels Having TimeSeriesTable Transformations", - "collapse": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-10" - } - } - } - ] - } - } - } - } + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with TimeSeriesTable Transformation - Single Stat", + "transformations": [ + { + "id": "timeSeriesTable", + "options": { + "A": { + "stat": "mean" + } + } + } + ], + "type": "table" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with TimeSeriesTable Transformation - Multiple Stats", + "transformations": [ + { + "id": "timeSeriesTable", + "options": { + "A": { + "stat": "mean" + }, + "B": { + "stat": "max" + }, + "C": { + "stat": "min" + }, + "D": { + "stat": "sum" + } + } + } + ], + "type": "table" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with TimeSeriesTable Transformation - Mixed with Other Transforms", + "transformations": [ + { + "id": "reduce", + "options": { + "reducers": [ + "mean" ] } }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 + { + "id": "timeSeriesTable", + "options": { + "A": { + "stat": "last" + }, + "B": { + "stat": "first" + } + } }, - "title": "V39 TimeSeriesTable Transformation Migration Test Dashboard", - "variables": [] + { + "id": "organize", + "options": { + "excludeByName": {} + } + } + ], + "type": "timeseries" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 }, - "status": {} + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with Non-TimeSeriesTable Transformation (Should Remain Unchanged)", + "transformations": [ + { + "id": "reduce", + "options": { + "reducers": [ + "mean", + "max" + ] + } + } + ], + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with TimeSeriesTable - Empty RefIdToStat", + "transformations": [ + { + "id": "timeSeriesTable", + "options": {} + } + ], + "type": "table" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with TimeSeriesTable - No Options (Should Skip)", + "transformations": [ + { + "id": "timeSeriesTable", + "options": null + } + ], + "type": "table" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 7, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with TimeSeriesTable - Invalid Options (Should Skip)", + "transformations": [ + { + "id": "timeSeriesTable", + "options": { + "someOtherOption": "value" + } + } + ], + "type": "table" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 8, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with No Transformations (Should Remain Unchanged)", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": -1, + "title": "Row with Nested Panels Having TimeSeriesTable Transformations", + "type": "row" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 10, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Nested Panel with TimeSeriesTable", + "transformations": [ + { + "id": "timeSeriesTable", + "options": { + "NestedA": { + "stat": "median" + }, + "NestedB": { + "stat": "stdDev" + } + } + } + ], + "type": "table" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V39 TimeSeriesTable Transformation Migration Test Dashboard" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v4.no-op.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v4.no-op.v0alpha1.json index 3a560f9acf5..5daafe44636 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v4.no-op.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v4.no-op.v0alpha1.json @@ -4,260 +4,123 @@ "metadata": { "name": "v4.no-op.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V4 No-Op Migration Test" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v4.no-op.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V4 No-Op Migration Test", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_empty_string.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_empty_string.v0alpha1.json index f017236b335..238fd0e0861 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_empty_string.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_empty_string.v0alpha1.json @@ -4,81 +4,55 @@ "metadata": { "name": "v40.refresh_empty_string.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Empty String Refresh Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v40.refresh_empty_string.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": {}, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Empty String Refresh Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_false.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_false.v0alpha1.json index a1f67edc2fe..2e51011773f 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_false.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_false.v0alpha1.json @@ -4,81 +4,55 @@ "metadata": { "name": "v40.refresh_false.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Boolean False Refresh Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v40.refresh_false.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": {}, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Boolean False Refresh Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_not_set.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_not_set.v0alpha1.json index 7e3758e1f87..43bd2fe817e 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_not_set.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_not_set.v0alpha1.json @@ -4,81 +4,55 @@ "metadata": { "name": "v40.refresh_not_set.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Refresh Not Set Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v40.refresh_not_set.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": {}, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Refresh Not Set Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_numeric.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_numeric.v0alpha1.json index 8af0bfdc64d..30b4531dcd0 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_numeric.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_numeric.v0alpha1.json @@ -4,81 +4,55 @@ "metadata": { "name": "v40.refresh_numeric.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Numeric Refresh Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v40.refresh_numeric.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": {}, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Numeric Refresh Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_string.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_string.v0alpha1.json index 99ff57db3b0..e16149e4bea 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_string.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_string.v0alpha1.json @@ -4,81 +4,55 @@ "metadata": { "name": "v40.refresh_string.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "preload": false, + "refresh": "1m", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "String Refresh Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v40.refresh_string.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": {}, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "1m", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "String Refresh Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_true.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_true.v0alpha1.json index d02ec352241..08a1150b27f 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_true.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v40.refresh_true.v0alpha1.json @@ -4,81 +4,55 @@ "metadata": { "name": "v40.refresh_true.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Boolean Refresh Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v40.refresh_true.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": {}, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Boolean Refresh Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v41.no_time_picker.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v41.no_time_picker.v0alpha1.json index fb208d18b60..077deeb8d51 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v41.no_time_picker.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v41.no_time_picker.v0alpha1.json @@ -4,81 +4,55 @@ "metadata": { "name": "v41.no_time_picker.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "No Time Picker Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v41.no_time_picker.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": {}, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "No Time Picker Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v41.time_picker_no_time_options.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v41.time_picker_no_time_options.v0alpha1.json index c97f595093f..4547a681dfe 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v41.time_picker_no_time_options.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v41.time_picker_no_time_options.v0alpha1.json @@ -4,81 +4,55 @@ "metadata": { "name": "v41.time_picker_no_time_options.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Time Picker No Time Options Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v41.time_picker_no_time_options.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": {}, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Time Picker No Time Options Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v41.time_picker_time_options.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v41.time_picker_time_options.v0alpha1.json index fd6af872656..708f2cb7bdc 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v41.time_picker_time_options.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v41.time_picker_time_options.v0alpha1.json @@ -4,81 +4,55 @@ "metadata": { "name": "v41.time_picker_time_options.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Time Picker Time Options Test Dashboard" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v41.time_picker_time_options.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": {}, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Time Picker Time Options Test Dashboard", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v42.harky_must.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v42.harky_must.v0alpha1.json index 519b1852887..da0b6aed0a7 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v42.harky_must.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v42.harky_must.v0alpha1.json @@ -4,141 +4,90 @@ "metadata": { "name": "v42.harky_must.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v42.harky_must.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with hideFrom.viz = true", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Field1" - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "tooltip": true, - "viz": true - } - } - ] - } - ] - } - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Field1" + }, + "properties": [ { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } + "id": "custom.hideFrom", + "value": { + "tooltip": true, + "viz": true } } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "v42 Migration Test - Harky Must", - "variables": [] + ] }, - "status": {} + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with hideFrom.viz = true", + "type": "timeseries" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "v42 Migration Test - Harky Must" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v42.hidefrom_tooltip.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v42.hidefrom_tooltip.v0alpha1.json index 14b9e4e7d31..4f1a1cd446e 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v42.hidefrom_tooltip.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v42.hidefrom_tooltip.v0alpha1.json @@ -4,484 +4,293 @@ "metadata": { "name": "v42.hidefrom_tooltip.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v42.hidefrom_tooltip.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with hideFrom.viz = true", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Field1" - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "tooltip": true, - "viz": true - } - } - ] - } - ] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Panel with multiple overrides", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Field2" - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": false, - "tooltip": true, - "viz": true - } - } - ] - }, - { - "__systemRef": "hideSeriesFrom", - "matcher": { - "id": "byNames", - "options": { - "mode": "exclude", - "names": [ - "foo" - ], - "prefix": "All except:", - "readOnly": true - } - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": false, - "tooltip": true, - "viz": true - } - } - ] - } - ] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Nested panel with hideFrom", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*/" - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "tooltip": true, - "viz": true - } - } - ] - } - ] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Panel without hideFrom", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "table", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Time" - }, - "properties": [ - { - "id": "unit", - "value": "short" - } - ] - } - ] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Panel with viz false (should not be modified)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "gauge", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [ - { - "matcher": { - "id": "byValue", - "options": { - "op": "gte", - "reducer": "allIsZero", - "value": 0 - } - }, - "properties": [ - { - "id": "unit", - "value": "short" - } - ] - } - ] - } - } - } - } - }, - "panel-7": { - "kind": "Panel", - "spec": { - "id": 7, - "title": "Panel with already set tooltip (should not be modified)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "barchart", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "{__name__=\"ALERTS\", alertname=\"k6CloudServiceErrorsLogged\"}" - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": false, - "tooltip": true, - "viz": true - } - } - ] - } - ] - } - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Field1" + }, + "properties": [ { - "kind": "RowsLayoutRow", - "spec": { - "title": "", - "collapse": true, - "hideHeader": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row with nested panels", - "collapse": true, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-7" - } - } - } - ] - } - } + "id": "custom.hideFrom", + "value": { + "tooltip": true, + "viz": true } } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "v42 Migration Test - HideFrom Tooltip", - "variables": [] + ] }, - "status": {} + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with hideFrom.viz = true", + "type": "timeseries" + }, + { + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Field2" + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": true, + "viz": true + } + } + ] + }, + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "foo" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": true, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with multiple overrides", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": -1, + "panels": [ + { + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*/" + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "tooltip": true, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 4, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Nested panel with hideFrom", + "type": "stat" + }, + { + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + } + ] + } + ] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 5, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel without hideFrom", + "type": "table" + }, + { + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byValue", + "options": { + "op": "gte", + "reducer": "allIsZero", + "value": 0 + } + }, + "properties": [ + { + "id": "unit", + "value": "short" + } + ] + } + ] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 6, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with viz false (should not be modified)", + "type": "gauge" + }, + { + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "{__name__=\"ALERTS\", alertname=\"k6CloudServiceErrorsLogged\"}" + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": true, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 7, + "options": {}, + "pluginVersion": "", + "targets": [], + "title": "Panel with already set tooltip (should not be modified)", + "type": "barchart" + } + ], + "title": "Row with nested panels", + "type": "row" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "v42 Migration Test - HideFrom Tooltip" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v5.no-op.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v5.no-op.v0alpha1.json index c411f444308..4872dd21894 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v5.no-op.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v5.no-op.v0alpha1.json @@ -4,260 +4,123 @@ "metadata": { "name": "v5.no-op.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V5 No-Op Migration Test" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v5.no-op.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V5 No-Op Migration Test", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v6.pulldowns_and_templating.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v6.pulldowns_and_templating.v0alpha1.json index 2691389f814..7f61b3e7b90 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v6.pulldowns_and_templating.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v6.pulldowns_and_templating.v0alpha1.json @@ -4,360 +4,219 @@ "metadata": { "name": "v6.pulldowns_and_templating.v42" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v6.pulldowns_and_templating.v42" + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" }, - "spec": { - "annotations": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "enable": true, + "hide": false, + "iconColor": "red", + "name": "deployment", + "query": "ALERTS{alertname=\"DeploymentStarted\"}" + }, + { + "datasource": { + "type": "loki", + "uid": "loki-uid" + }, + "enable": false, + "hide": false, + "iconColor": "yellow", + "name": "alerts", + "query": "{job=\"alertmanager\"}" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "cpu_usage{environment=\"$environment\", service=\"$service\"}", + "refId": "A" + } + ], + "title": "CPU Usage", + "type": "timeseries" + }, + { + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "memory_usage{region=\"$region\"}", + "refId": "B" + } + ], + "title": "Memory Usage", + "type": "stat" + } + ], + "preload": false, + "refresh": "30s", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "environment", + "options": [], + "query": "label_values(up, instance)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "service", + "options": [], + "query": "label_values(up, instance)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "region", + "options": [ { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } + "selected": false, + "text": "us-east-1", + "value": "us-east-1" }, { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "enable": true, - "hide": false, - "iconColor": "red", - "name": "deployment", - "legacyOptions": { - "query": "ALERTS{alertname=\"DeploymentStarted\"}" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "loki", - "version": "v0", - "datasource": { - "name": "loki-uid" - }, - "spec": {} - }, - "enable": false, - "hide": false, - "iconColor": "yellow", - "name": "alerts", - "legacyOptions": { - "query": "{job=\"alertmanager\"}" - } - } + "selected": false, + "text": "us-west-2", + "value": "us-west-2" } ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "CPU Usage", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "expr": "cpu_usage{environment=\"$environment\", service=\"$service\"}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Memory Usage", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "expr": "memory_usage{region=\"$region\"}" - } - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 12, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-1h", - "to": "now", - "autoRefresh": "30s", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V6 Pulldowns and Template Variables Migration Test", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "environment", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "__legacyStringValue": "label_values(up, instance)" - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "service", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "__legacyStringValue": "label_values(up, instance)" - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "CustomVariable", - "spec": { - "name": "region", - "query": "", - "current": { - "text": "", - "value": "" - }, - "options": [ - { - "selected": false, - "text": "us-east-1", - "value": "us-east-1" - }, - { - "selected": false, - "text": "us-west-2", - "value": "us-west-2" - } - ], - "multi": false, - "includeAll": false, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "instance", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "__legacyStringValue": "label_values(up, instance)" - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - } - ] + "query": "", + "skipUrlSync": false, + "type": "custom" }, - "status": {} - } + { + "allowCustomValue": true, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "instance", + "options": [], + "query": "label_values(up, instance)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V6 Pulldowns and Template Variables Migration Test" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v7.timepicker.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v7.timepicker.v0alpha1.json index 5efa0ef30b2..100c239dc08 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v7.timepicker.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v7.timepicker.v0alpha1.json @@ -4,162 +4,88 @@ "metadata": { "name": "v7.timepicker.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "up", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "expr": "cpu_usage", + "refId": "B" + } + ], + "title": "", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "No Title" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v7.timepicker.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "expr": "up" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": { - "expr": "cpu_usage" - } - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "No Title", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v9.no-op.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v9.no-op.v0alpha1.json index 4c97717ced1..3f575f7f5fc 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v9.no-op.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v9.no-op.v0alpha1.json @@ -4,260 +4,123 @@ "metadata": { "name": "v9.no-op.v42" }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 2, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "stat" + }, + { + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 3, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, + "refId": "A" + } + ], + "title": "", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "V9 No-Op Migration Test" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "v9.no-op.v42" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "default-ds-uid" - }, - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 6, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - } - ] - } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "V9 No-Op Migration Test", - "variables": [] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-elasticsearch/v0alpha1.elasticsearch_complex.v42.v2alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-elasticsearch/v0alpha1.elasticsearch_complex.v42.v2alpha1.json index 4ba14d53c0c..253b6471087 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-elasticsearch/v0alpha1.elasticsearch_complex.v42.v2alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-elasticsearch/v0alpha1.elasticsearch_complex.v42.v2alpha1.json @@ -7234,9 +7234,9 @@ "type": "elasticsearch", "uid": "gdev-elasticsearch" }, - "baseFilters": null, + "baseFilters": [], "filters": [], - "defaultKeys": null, + "defaultKeys": [], "hide": "dontHide", "skipUrlSync": false, "allowCustomValue": true diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-elasticsearch/v0alpha1.elasticsearch_complex.v42.v2beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-elasticsearch/v0alpha1.elasticsearch_complex.v42.v2beta1.json index 7de7561d8af..54edeecb540 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-elasticsearch/v0alpha1.elasticsearch_complex.v42.v2beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-elasticsearch/v0alpha1.elasticsearch_complex.v42.v2beta1.json @@ -7335,9 +7335,9 @@ }, "spec": { "name": "adhoc", - "baseFilters": null, + "baseFilters": [], "filters": [], - "defaultKeys": null, + "defaultKeys": [], "hide": "dontHide", "skipUrlSync": false, "allowCustomValue": true diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-influxdb/v0alpha1.influxdb-templated.v42.v2alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-influxdb/v0alpha1.influxdb-templated.v42.v2alpha1.json index c04c33b8edb..3b776907f83 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-influxdb/v0alpha1.influxdb-templated.v42.v2alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-influxdb/v0alpha1.influxdb-templated.v42.v2alpha1.json @@ -307,9 +307,9 @@ "kind": "AdhocVariable", "spec": { "name": "adhoc", - "baseFilters": null, + "baseFilters": [], "filters": [], - "defaultKeys": null, + "defaultKeys": [], "hide": "dontHide", "skipUrlSync": false, "allowCustomValue": true diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-influxdb/v0alpha1.influxdb-templated.v42.v2beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-influxdb/v0alpha1.influxdb-templated.v42.v2beta1.json index 731506b101b..a6ebf10b8f0 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-influxdb/v0alpha1.influxdb-templated.v42.v2beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-influxdb/v0alpha1.influxdb-templated.v42.v2beta1.json @@ -317,9 +317,9 @@ "datasource": {}, "spec": { "name": "adhoc", - "baseFilters": null, + "baseFilters": [], "filters": [], - "defaultKeys": null, + "defaultKeys": [], "hide": "dontHide", "skipUrlSync": false, "allowCustomValue": true diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-loki/v0alpha1.loki_fakedata.v42.v2alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-loki/v0alpha1.loki_fakedata.v42.v2alpha1.json index 495d5ae8ced..d8a362c5029 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-loki/v0alpha1.loki_fakedata.v42.v2alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-loki/v0alpha1.loki_fakedata.v42.v2alpha1.json @@ -604,9 +604,9 @@ "type": "loki", "uid": "PDDA8E780A17E7EF1" }, - "baseFilters": null, + "baseFilters": [], "filters": [], - "defaultKeys": null, + "defaultKeys": [], "label": "Ad-hoc", "hide": "dontHide", "skipUrlSync": false, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-loki/v0alpha1.loki_fakedata.v42.v2beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-loki/v0alpha1.loki_fakedata.v42.v2beta1.json index 0a0142cb3ed..029c2bcf218 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-loki/v0alpha1.loki_fakedata.v42.v2beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/datasource-loki/v0alpha1.loki_fakedata.v42.v2beta1.json @@ -616,9 +616,9 @@ }, "spec": { "name": "adhoc", - "baseFilters": null, + "baseFilters": [], "filters": [], - "defaultKeys": null, + "defaultKeys": [], "label": "Ad-hoc", "hide": "dontHide", "skipUrlSync": false, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_footer.v42.v2alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_footer.v42.v2alpha1.json index bf4adacd2bc..2697100f4cd 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_footer.v42.v2alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_footer.v42.v2alpha1.json @@ -1885,7 +1885,7 @@ "name": "Filters", "baseFilters": [], "filters": [], - "defaultKeys": null, + "defaultKeys": [], "hide": "dontHide", "skipUrlSync": false, "allowCustomValue": true diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_footer.v42.v2beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_footer.v42.v2beta1.json index 89f22b62bf0..ec3f1d1ed5c 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_footer.v42.v2beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_footer.v42.v2beta1.json @@ -1931,7 +1931,7 @@ "name": "Filters", "baseFilters": [], "filters": [], - "defaultKeys": null, + "defaultKeys": [], "hide": "dontHide", "skipUrlSync": false, "allowCustomValue": true diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_kitchen_sink.v42.v2alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_kitchen_sink.v42.v2alpha1.json index c06c7e81260..d2ec399b434 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_kitchen_sink.v42.v2alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_kitchen_sink.v42.v2alpha1.json @@ -2184,7 +2184,7 @@ "name": "Filters", "baseFilters": [], "filters": [], - "defaultKeys": null, + "defaultKeys": [], "hide": "dontHide", "skipUrlSync": false, "allowCustomValue": true diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_kitchen_sink.v42.v2beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_kitchen_sink.v42.v2beta1.json index 4b98f1b4c55..a2ea184c554 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_kitchen_sink.v42.v2beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_kitchen_sink.v42.v2beta1.json @@ -2219,7 +2219,7 @@ "name": "Filters", "baseFilters": [], "filters": [], - "defaultKeys": null, + "defaultKeys": [], "hide": "dontHide", "skipUrlSync": false, "allowCustomValue": true diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_v12_2_migrations.v42.v2alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_v12_2_migrations.v42.v2alpha1.json index de3fd99993b..b8e6725ca5a 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_v12_2_migrations.v42.v2alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_v12_2_migrations.v42.v2alpha1.json @@ -2499,7 +2499,7 @@ "name": "Filters", "baseFilters": [], "filters": [], - "defaultKeys": null, + "defaultKeys": [], "hide": "dontHide", "skipUrlSync": false, "allowCustomValue": true diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_v12_2_migrations.v42.v2beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_v12_2_migrations.v42.v2beta1.json index fb856d2bdea..4a7ea3bcf33 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_v12_2_migrations.v42.v2beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dev_dashboards/panel-table/v0alpha1.table_v12_2_migrations.v42.v2beta1.json @@ -2542,7 +2542,7 @@ "name": "Filters", "baseFilters": [], "filters": [], - "defaultKeys": null, + "defaultKeys": [], "hide": "dontHide", "skipUrlSync": false, "allowCustomValue": true diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.annotation-conversions.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.annotation-conversions.v0alpha1.json index 0e488407f34..10463c8e142 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.annotation-conversions.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.annotation-conversions.v0alpha1.json @@ -239,4 +239,4 @@ "storedVersion": "v1beta1" } } -} +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.panel-datasource-type-datasource.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.panel-datasource-type-datasource.v0alpha1.json new file mode 100644 index 00000000000..3ee27b33fd6 --- /dev/null +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.panel-datasource-type-datasource.v0alpha1.json @@ -0,0 +1,158 @@ +{ + "kind": "Dashboard", + "apiVersion": "dashboard.grafana.app/v0alpha1", + "metadata": { + "name": "ad5vfcn", + "namespace": "default", + "uid": "dlMZZl6GndU8gJLUQSmgZxXBPCNXyXhNBeQJhHXl0r4X", + "resourceVersion": "2", + "generation": 2, + "creationTimestamp": "2025-11-28T10:14:21Z", + "labels": { + "grafana.app/deprecatedInternalID": "288" + }, + "annotations": { + "grafana.app/createdBy": "user:eex2ofwuj0agwd", + "grafana.app/updatedBy": "user:eex2ofwuj0agwd", + "grafana.app/updatedTimestamp": "2025-11-28T10:15:06Z" + } + }, + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 288, + "links": [], + "panels": [ + { + "datasource": { + "type": "testdata", + "uid": "gdev-testdata" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-pre", + "targets": [ + { + "datasource": {}, + "queryType": "randomWalk", + "refId": "A" + } + ], + "title": "New panel", + "type": "timeseries" + } + ], + "preload": false, + "schemaVersion": 42, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Panel ds inheritance ", + "uid": "ad5vfcn", + "version": 2 + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v1beta1" + } + } +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.panel-datasource-type-datasource.v2alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.panel-datasource-type-datasource.v2alpha1.json new file mode 100644 index 00000000000..5a0a8e074e6 --- /dev/null +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.panel-datasource-type-datasource.v2alpha1.json @@ -0,0 +1,205 @@ +{ + "kind": "Dashboard", + "apiVersion": "dashboard.grafana.app/v2alpha1", + "metadata": { + "name": "ad5vfcn", + "namespace": "default", + "uid": "dlMZZl6GndU8gJLUQSmgZxXBPCNXyXhNBeQJhHXl0r4X", + "resourceVersion": "2", + "generation": 2, + "creationTimestamp": "2025-11-28T10:14:21Z", + "labels": { + "grafana.app/deprecatedInternalID": "288" + }, + "annotations": { + "grafana.app/createdBy": "user:eex2ofwuj0agwd", + "grafana.app/updatedBy": "user:eex2ofwuj0agwd", + "grafana.app/updatedTimestamp": "2025-11-28T10:15:06Z" + } + }, + "spec": { + "annotations": [ + { + "kind": "AnnotationQuery", + "spec": { + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "query": { + "kind": "grafana", + "spec": {} + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "builtIn": true, + "legacyOptions": { + "type": "dashboard" + } + } + } + ], + "cursorSync": "Off", + "editable": true, + "elements": { + "panel-1": { + "kind": "Panel", + "spec": { + "id": 1, + "title": "New panel", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "testdata", + "spec": { + "queryType": "randomWalk" + } + }, + "datasource": { + "type": "testdata", + "uid": "gdev-testdata" + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "timeseries", + "spec": { + "pluginVersion": "12.4.0-pre", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + } + }, + "layout": { + "kind": "GridLayout", + "spec": { + "items": [ + { + "kind": "GridLayoutItem", + "spec": { + "x": 0, + "y": 0, + "width": 12, + "height": 8, + "element": { + "kind": "ElementReference", + "name": "panel-1" + } + } + } + ] + } + }, + "links": [], + "liveNow": false, + "preload": false, + "tags": [], + "timeSettings": { + "timezone": "browser", + "from": "now-6h", + "to": "now", + "autoRefresh": "", + "autoRefreshIntervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "hideTimepicker": false, + "fiscalYearStartMonth": 0 + }, + "title": "Panel ds inheritance ", + "variables": [] + }, + "status": {} +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.panel-datasource-type-datasource.v2beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.panel-datasource-type-datasource.v2beta1.json new file mode 100644 index 00000000000..3a13853c08e --- /dev/null +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v1beta1.panel-datasource-type-datasource.v2beta1.json @@ -0,0 +1,208 @@ +{ + "kind": "Dashboard", + "apiVersion": "dashboard.grafana.app/v2beta1", + "metadata": { + "name": "ad5vfcn", + "namespace": "default", + "uid": "dlMZZl6GndU8gJLUQSmgZxXBPCNXyXhNBeQJhHXl0r4X", + "resourceVersion": "2", + "generation": 2, + "creationTimestamp": "2025-11-28T10:14:21Z", + "labels": { + "grafana.app/deprecatedInternalID": "288" + }, + "annotations": { + "grafana.app/createdBy": "user:eex2ofwuj0agwd", + "grafana.app/updatedBy": "user:eex2ofwuj0agwd", + "grafana.app/updatedTimestamp": "2025-11-28T10:15:06Z" + } + }, + "spec": { + "annotations": [ + { + "kind": "AnnotationQuery", + "spec": { + "query": { + "kind": "DataQuery", + "group": "grafana", + "version": "v0", + "datasource": { + "name": "-- Grafana --" + }, + "spec": {} + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "builtIn": true, + "legacyOptions": { + "type": "dashboard" + } + } + } + ], + "cursorSync": "Off", + "editable": true, + "elements": { + "panel-1": { + "kind": "Panel", + "spec": { + "id": 1, + "title": "New panel", + "description": "", + "links": [], + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "query": { + "kind": "DataQuery", + "group": "testdata", + "version": "v0", + "datasource": { + "name": "gdev-testdata" + }, + "spec": { + "queryType": "randomWalk" + } + }, + "refId": "A", + "hidden": false + } + } + ], + "transformations": [], + "queryOptions": {} + } + }, + "vizConfig": { + "kind": "VizConfig", + "group": "timeseries", + "version": "12.4.0-pre", + "spec": { + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + { + "value": 0, + "color": "green" + }, + { + "value": 80, + "color": "red" + } + ] + }, + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + } + }, + "overrides": [] + } + } + } + } + } + }, + "layout": { + "kind": "GridLayout", + "spec": { + "items": [ + { + "kind": "GridLayoutItem", + "spec": { + "x": 0, + "y": 0, + "width": 12, + "height": 8, + "element": { + "kind": "ElementReference", + "name": "panel-1" + } + } + } + ] + } + }, + "links": [], + "liveNow": false, + "preload": false, + "tags": [], + "timeSettings": { + "timezone": "browser", + "from": "now-6h", + "to": "now", + "autoRefresh": "", + "autoRefreshIntervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "hideTimepicker": false, + "fiscalYearStartMonth": 0 + }, + "title": "Panel ds inheritance ", + "variables": [] + }, + "status": {} +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v0alpha1.json index 18d0371f1c4..e3e0747bfc4 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v0alpha1.json @@ -10,516 +10,390 @@ "description": "Complete example of v2alpha1 dashboard features" } }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2alpha1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2alpha1", - "metadata": { - "name": "test-v2alpha1-complete", - "labels": { - "category": "test" + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "annotations": { - "description": "Complete example of v2alpha1 dashboard features" - } + "enable": true, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "query": { - "kind": "grafana", - "spec": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - } - }, - "enable": true, - "hide": false, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "datasource": { - "type": "prometheus", - "uid": "gdev-prometheus" - }, - "query": { - "kind": "prometheus", - "spec": { - "expr": "changes(process_start_time_seconds[1m])", - "refId": "Anno" - } - }, - "enable": true, - "hide": false, - "iconColor": "yellow", - "name": "Prometheus Annotations", - "builtIn": false - } - } - ], - "cursorSync": "Tooltip", - "description": "This dashboard demonstrates all features that need to be converted from v2alpha1 to v2beta1", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with Conditional Rendering", - "description": "This panel demonstrates conditional rendering features", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "prometheus", - "spec": { - "expr": "up{job=\"grafana\"}" - } - }, - "datasource": { - "type": "prometheus", - "uid": "gdev-prometheus" - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "reduce", - "spec": { - "id": "reduce", - "options": { - "includeTimeField": false, - "mode": "reduceFields", - "reducers": [ - "mean" - ] - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "stat", - "spec": { - "pluginVersion": "12.1.0-pre", - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "textMode": "auto" - }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "type": "value", - "options": { - "0": { - "text": "Down", - "color": "red" - }, - "1": { - "text": "Up", - "color": "green" - } - } - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "red" - }, - { - "value": 1, - "color": "green" - } - ] - }, - "color": { - "mode": "thresholds" - } - }, - "overrides": [] - } - } - } - } - } + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "Row", - "spec": { - "title": "Conditional Row", - "collapse": false, - "hideHeader": false, - "fillScreen": false, - "conditionalRendering": { - "kind": "ConditionalRenderingGroup", - "spec": { - "visibility": "show", - "condition": "and", - "items": [ - { - "kind": "ConditionalRenderingVariable", - "spec": { - "variable": "group_by", - "operator": "includes", - "value": "instance" - } - }, - { - "kind": "ConditionalRenderingData", - "spec": { - "value": true - } - }, - { - "kind": "ConditionalRenderingTimeRangeSize", - "spec": { - "value": "1h" - } - } - ] - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 24, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - } - ] - } - } + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "Prometheus Annotations", + "target": { + "expr": "changes(process_start_time_seconds[1m])", + "refId": "Anno" + } + } + ] + }, + "description": "This dashboard demonstrates all features that need to be converted from v2alpha1 to v2beta1", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 2, + "liveNow": true, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": -1, + "title": "Conditional Row", + "type": "row" + }, + { + "description": "This panel demonstrates conditional rendering features", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "color": "red", + "text": "Down" + }, + "1": { + "color": "green", + "text": "Up" } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": 0 + }, + { + "color": "green", + "value": 1 } ] } - }, - "links": [], - "liveNow": true, - "preload": true, - "tags": [ - "test", - "example", - "migration" - ], - "timeSettings": { - "timezone": "browser", - "from": "now-6h", - "to": "now", - "autoRefresh": "10s", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "weekStart": "monday", - "fiscalYearStartMonth": 0 - }, - "title": "Test: Complete V2alpha1 Dashboard Example", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "prometheus_query", - "current": { - "text": "All", - "value": [ - "$__all" - ] - }, - "label": "Prometheus Query", - "hide": "dontHide", - "refresh": "time", - "skipUrlSync": false, - "description": "Shows all up metrics", - "datasource": { - "type": "prometheus", - "uid": "gdev-prometheus" - }, - "query": { - "kind": "prometheus", - "spec": { - "expr": "up" - } - }, - "regex": "", - "sort": "alphabetical", - "definition": "up", - "options": null, - "multi": true, - "includeAll": true, - "allowCustomValue": false - } - }, - { - "kind": "TextVariable", - "spec": { - "name": "text_var", - "current": { - "selected": true, - "text": "server1", - "value": "server1" - }, - "query": "server1,server2,server3", - "label": "Text Variable", - "hide": "dontHide", - "skipUrlSync": false, - "description": "A simple text variable" - } - }, - { - "kind": "ConstantVariable", - "spec": { - "name": "constant_var", - "query": "production", - "current": { - "selected": true, - "text": "production", - "value": "production" - }, - "label": "Constant", - "hide": "dontHide", - "skipUrlSync": true, - "description": "A constant value" - } - }, - { - "kind": "DatasourceVariable", - "spec": { - "name": "ds_var", - "pluginId": "prometheus", - "refresh": "load", - "regex": "/^gdev-/", - "current": { - "text": "gdev-prometheus", - "value": "gdev-prometheus" - }, - "options": [ - { - "text": "gdev-prometheus", - "value": "gdev-prometheus" - } - ], - "multi": false, - "includeAll": false, - "label": "Datasource", - "hide": "dontHide", - "skipUrlSync": false, - "description": "Select a datasource", - "allowCustomValue": false - } - }, - { - "kind": "IntervalVariable", - "spec": { - "name": "interval", - "query": "1m,5m,10m,30m,1h,6h,12h,1d", - "current": { - "selected": true, - "text": "5m", - "value": "5m" - }, - "options": [ - { - "text": "1m", - "value": "1m" - }, - { - "text": "5m", - "value": "5m" - }, - { - "text": "10m", - "value": "10m" - }, - { - "text": "30m", - "value": "30m" - }, - { - "text": "1h", - "value": "1h" - }, - { - "text": "6h", - "value": "6h" - }, - { - "text": "12h", - "value": "12h" - }, - { - "text": "1d", - "value": "1d" - } - ], - "auto": true, - "auto_min": "10s", - "auto_count": 30, - "refresh": "load", - "label": "Interval", - "hide": "dontHide", - "skipUrlSync": false, - "description": "Time interval selection" - } - }, - { - "kind": "CustomVariable", - "spec": { - "name": "custom_var", - "query": "prod : Production, staging : Staging, dev : Development", - "current": { - "text": [ - "Production" - ], - "value": [ - "prod" - ] - }, - "options": [ - { - "text": "Production", - "value": "prod" - }, - { - "text": "Staging", - "value": "staging" - }, - { - "text": "Development", - "value": "dev" - } - ], - "multi": true, - "includeAll": true, - "allValue": "*", - "label": "Custom Options", - "hide": "dontHide", - "skipUrlSync": false, - "description": "Custom multi-value variable", - "allowCustomValue": true - } - }, - { - "kind": "GroupByVariable", - "spec": { - "name": "group_by", - "datasource": { - "type": "prometheus", - "uid": "gdev-prometheus" - }, - "current": { - "text": "instance", - "value": "instance" - }, - "options": null, - "multi": false, - "label": "Group By", - "hide": "dontHide", - "skipUrlSync": false, - "description": "Group metrics by label" - } - }, - { - "kind": "AdhocVariable", - "spec": { - "name": "filters", - "datasource": { - "type": "prometheus", - "uid": "gdev-prometheus" - }, - "baseFilters": [ - { - "key": "job", - "operator": "=", - "value": "grafana", - "condition": "AND" - } - ], - "filters": [], - "defaultKeys": [ - { - "text": "job", - "value": "job", - "expandable": true - }, - { - "text": "instance", - "value": "instance", - "expandable": true - } - ], - "label": "Filters", - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": false - } - } - ] - }, - "status": { - "conversion": { - "failed": false, - "storedVersion": "v2beta1" } - } + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "textMode": "auto" + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "expr": "up{job=\"grafana\"}", + "refId": "A" + } + ], + "title": "Panel with Conditional Rendering", + "transformations": [ + { + "id": "reduce", + "options": { + "includeTimeField": false, + "mode": "reduceFields", + "reducers": [ + "mean" + ] + } + } + ], + "type": "stat" } + ], + "preload": true, + "refresh": "10s", + "schemaVersion": 42, + "tags": [ + "test", + "example", + "migration" + ], + "templating": { + "list": [ + { + "allowCustomValue": false, + "current": { + "text": "All", + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "definition": "up", + "description": "Shows all up metrics", + "hide": 0, + "includeAll": true, + "label": "Prometheus Query", + "multi": true, + "name": "prometheus_query", + "options": [], + "query": { + "expr": "up" + }, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "text": "server1", + "value": "server1" + }, + "description": "A simple text variable", + "hide": 0, + "label": "Text Variable", + "name": "text_var", + "query": "server1,server2,server3", + "skipUrlSync": false, + "type": "textbox" + }, + { + "current": { + "text": "production", + "value": "production" + }, + "description": "A constant value", + "hide": 2, + "label": "Constant", + "name": "constant_var", + "query": "production", + "skipUrlSync": true, + "type": "constant" + }, + { + "allowCustomValue": false, + "current": { + "text": "gdev-prometheus", + "value": "gdev-prometheus" + }, + "description": "Select a datasource", + "hide": 0, + "includeAll": false, + "label": "Datasource", + "multi": false, + "name": "ds_var", + "options": [ + { + "text": "gdev-prometheus", + "value": "gdev-prometheus" + } + ], + "query": "prometheus", + "refresh": 0, + "regex": "/^gdev-/", + "skipUrlSync": false, + "type": "datasource" + }, + { + "auto": true, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "description": "Time interval selection", + "hide": 0, + "label": "Interval", + "name": "interval", + "options": [ + { + "text": "1m", + "value": "1m" + }, + { + "text": "5m", + "value": "5m" + }, + { + "text": "10m", + "value": "10m" + }, + { + "text": "30m", + "value": "30m" + }, + { + "text": "1h", + "value": "1h" + }, + { + "text": "6h", + "value": "6h" + }, + { + "text": "12h", + "value": "12h" + }, + { + "text": "1d", + "value": "1d" + } + ], + "query": "1m,5m,10m,30m,1h,6h,12h,1d", + "skipUrlSync": false, + "type": "interval" + }, + { + "allValue": "*", + "allowCustomValue": true, + "current": { + "text": [ + "Production" + ], + "value": [ + "prod" + ] + }, + "description": "Custom multi-value variable", + "hide": 0, + "includeAll": true, + "label": "Custom Options", + "multi": true, + "name": "custom_var", + "options": [ + { + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "staging" + }, + { + "text": "Development", + "value": "dev" + } + ], + "query": "prod : Production, staging : Staging, dev : Development", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "text": "instance", + "value": "instance" + }, + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "description": "Group metrics by label", + "hide": 0, + "label": "Group By", + "multi": false, + "name": "group_by", + "options": [], + "skipUrlSync": false, + "type": "groupby" + }, + { + "allowCustomValue": false, + "baseFilters": [ + { + "condition": "AND", + "key": "job", + "operator": "=", + "value": "grafana" + } + ], + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "defaultKeys": [ + { + "expandable": true, + "text": "job", + "value": "job" + }, + { + "expandable": true, + "text": "instance", + "value": "instance" + } + ], + "hide": 0, + "label": "Filters", + "name": "filters", + "skipUrlSync": false, + "type": "adhoc" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "Test: Complete V2alpha1 Dashboard Example", + "weekStart": "monday" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2alpha1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v0alpha1.json index 50b2b4e9038..e648923e684 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v0alpha1.json @@ -4,1070 +4,825 @@ "metadata": { "name": "test-v2alpha1-annotations" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2alpha1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2alpha1", - "metadata": { - "name": "test-v2alpha1-annotations" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "query": { - "kind": "grafana", - "spec": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - } - }, - "enable": true, - "hide": false, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" - }, - "query": { - "kind": "grafana-testdata-datasource", - "spec": { - "lines": 10, - "refId": "Anno", - "scenarioId": "annotations" - } - }, - "enable": true, - "hide": false, - "iconColor": "blue", - "name": "testdata-annos", - "builtIn": false - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "prometheus", - "spec": { - "lines": 10, - "refId": "Anno", - "scenarioId": "annotations" - } - }, - "enable": true, - "hide": false, - "iconColor": "blue", - "name": "no-ds-testdata-annos", - "builtIn": false - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "datasource": { - "type": "prometheus", - "uid": "gdev-prometheus" - }, - "query": { - "kind": "prometheus", - "spec": { - "expr": "{action=\"add_client\"}", - "interval": "", - "lines": 10, - "refId": "Anno", - "scenarioId": "annotations" - } - }, - "enable": true, - "hide": false, - "iconColor": "yellow", - "name": "prom-annos", - "builtIn": false - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "prometheus", - "spec": { - "expr": "{action=\"add_client\"}", - "interval": "", - "lines": 10, - "refId": "Anno", - "scenarioId": "annotations" - } - }, - "enable": true, - "hide": false, - "iconColor": "yellow", - "name": "no-ds-prom-annos", - "builtIn": false - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "datasource": { - "type": "grafana-postgresql-datasource", - "uid": "PBBCEC2D313BC06C3" - }, - "query": { - "kind": "grafana-postgresql-datasource", - "spec": { - "editorMode": "builder", - "format": "table", - "lines": 10, - "rawSql": "", - "refId": "Anno", - "scenarioId": "annotations", - "sql": { - "columns": [ - { - "parameters": [], - "type": "function" - } - ], - "groupBy": [ - { - "property": { - "type": "string" - }, - "type": "groupBy" - } - ], - "limit": 50 - } - } - }, - "enable": true, - "hide": false, - "iconColor": "red", - "name": "postgress-annos", - "builtIn": false - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "datasource": { - "type": "elasticsearch", - "uid": "gdev-elasticsearch" - }, - "query": { - "kind": "elasticsearch", - "spec": { - "lines": 10, - "query": "test query", - "refId": "Anno", - "scenarioId": "annotations" - } - }, - "enable": true, - "hide": false, - "iconColor": "red", - "name": "elastic - annos", - "builtIn": false, - "legacyOptions": { - "tagsField": "asd", - "textField": "asd", - "timeEndField": "asdas", - "timeField": "asd" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Simple timeseries (WITH DS REF)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "grafana-testdata-datasource", - "spec": { - "scenarioId": "random_walk", - "seriesCount": 3 - } - }, - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "gdev-testdata" - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "timeseries", - "spec": { - "pluginVersion": "12.1.0-pre", - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Simple stat (NO DS REF)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "grafana-testdata-datasource", - "spec": { - "scenarioId": "random_walk", - "seriesCount": 4 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "stat", - "spec": { - "pluginVersion": "12.1.0-pre", - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "thresholds" - } - }, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel with NO REF to gdev-prometheus", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "prometheus", - "spec": { - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(counters_requests[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "instant": false, - "legendFormat": "__auto", - "range": true, - "useBackend": false - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "timeseries", - "spec": { - "pluginVersion": "12.1.0-pre", - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel with ref to gdev-prometheus", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "prometheus", - "spec": { - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(counters_requests[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "instant": false, - "legendFormat": "__auto", - "range": true, - "useBackend": false - } - }, - "datasource": { - "type": "prometheus", - "uid": "gdev-prometheus" - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "timeseries", - "spec": { - "pluginVersion": "12.1.0-pre", - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Mixed DS WITH REFS", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "prometheus", - "spec": { - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "legendFormat": "__auto", - "range": true, - "useBackend": false - } - }, - "datasource": { - "type": "prometheus", - "uid": "gdev-prometheus" - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "grafana-testdata-datasource", - "spec": {} - }, - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "gdev-testdata" - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "timeseries", - "spec": { - "pluginVersion": "12.1.0-pre", - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Mixed DS WITHOUT REFS", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "prometheus", - "spec": { - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "legendFormat": "__auto", - "range": true, - "useBackend": false - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "grafana-testdata-datasource", - "spec": {} - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "timeseries", - "spec": { - "pluginVersion": "12.1.0-pre", - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [ + "enable": true, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "enable": true, + "hide": false, + "iconColor": "blue", + "name": "testdata-annos", + "target": { + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + { + "datasource": { + "type": "prometheus" + }, + "enable": true, + "hide": false, + "iconColor": "blue", + "name": "no-ds-testdata-annos", + "target": { + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "prom-annos", + "target": { + "expr": "{action=\"add_client\"}", + "interval": "", + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + { + "datasource": { + "type": "prometheus" + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "no-ds-prom-annos", + "target": { + "expr": "{action=\"add_client\"}", + "interval": "", + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PBBCEC2D313BC06C3" + }, + "enable": true, + "hide": false, + "iconColor": "red", + "name": "postgress-annos", + "target": { + "editorMode": "builder", + "format": "table", + "lines": 10, + "rawSql": "", + "refId": "Anno", + "scenarioId": "annotations", + "sql": { + "columns": [ { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "enable": true, + "hide": false, + "iconColor": "red", + "name": "elastic - annos", + "tagsField": "asd", + "target": { + "lines": 10, + "query": "test query", + "refId": "Anno", + "scenarioId": "annotations" + }, + "textField": "asd", + "timeEndField": "asdas", + "timeField": "asd" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 }, { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } + "color": "red", + "value": 80 } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "browser", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Test: V2alpha1 dashboard with annotations", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "variable-ds-prometheus", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "", - "skipUrlSync": false, - "datasource": { - "type": "prometheus", - "uid": "gdev-prometheus" - }, - "query": { - "kind": "prometheus", - "spec": { - "expr": "up" - } - }, - "regex": "", - "sort": "", - "options": null, - "multi": false, - "includeAll": false, - "allowCustomValue": false - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "variable-no-ds", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "", - "skipUrlSync": false, - "query": { - "kind": "grafana-testdata-datasource", - "spec": { - "csv": "1,2,3,4", - "scenarioId": "csv_metric_values" - } - }, - "regex": "", - "sort": "", - "options": null, - "multi": false, - "includeAll": false, - "allowCustomValue": false - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "variable-no-ds-empty-query", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "", - "skipUrlSync": false, - "query": { - "kind": "grafana-testdata-datasource", - "spec": {} - }, - "regex": "", - "sort": "", - "options": null, - "multi": false, - "includeAll": false, - "allowCustomValue": false - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "variable-no-default-ds", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "", - "skipUrlSync": false, - "query": { - "kind": "prometheus", - "spec": { - "expr": "up" - } - }, - "regex": "", - "sort": "", - "options": null, - "multi": false, - "includeAll": false, - "allowCustomValue": false - } - } - ] - }, - "status": { - "conversion": { - "failed": false, - "storedVersion": "v2beta1" } - } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "prometheus" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Panel with NO REF to gdev-prometheus", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Panel with ref to gdev-prometheus", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 4 + } + ], + "title": "Simple stat (NO DS REF)", + "type": "stat" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 9 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 3 + } + ], + "title": "Simple timeseries (WITH DS REF)", + "type": "timeseries" + }, + { + "datasource": { + "type": "mixed", + "uid": "-- Mixed --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 9 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, + "refId": "B" + } + ], + "title": "Mixed DS WITH REFS", + "type": "timeseries" + }, + { + "datasource": { + "type": "mixed", + "uid": "-- Mixed --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 9 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "prometheus" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "B" + } + ], + "title": "Mixed DS WITHOUT REFS", + "type": "timeseries" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": false, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "variable-ds-prometheus", + "options": [], + "query": { + "expr": "up" + }, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": false, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "grafana-testdata-datasource" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "variable-no-ds", + "options": [], + "query": { + "csv": "1,2,3,4", + "scenarioId": "csv_metric_values" + }, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": false, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "grafana-testdata-datasource" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "variable-no-ds-empty-query", + "options": [], + "query": {}, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": false, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "variable-no-default-ds", + "options": [], + "query": { + "expr": "up" + }, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "Test: V2alpha1 dashboard with annotations" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2alpha1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.groupby-adhoc-vars.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.groupby-adhoc-vars.v0alpha1.json index d03d476b881..cae121bdef7 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.groupby-adhoc-vars.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.groupby-adhoc-vars.v0alpha1.json @@ -4,110 +4,91 @@ "metadata": { "name": "test-v2alpha1-groupby-adhoc-vars" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2alpha1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2alpha1", - "metadata": { - "name": "test-v2alpha1-groupby-adhoc-vars" - }, - "spec": { - "annotations": [], - "cursorSync": "", - "elements": {}, - "layout": null, - "links": [], - "preload": false, - "tags": null, - "timeSettings": { - "from": "", - "to": "", - "autoRefresh": "", - "autoRefreshIntervals": null, - "hideTimepicker": false, - "fiscalYearStartMonth": 0 + "spec": { + "annotations": { + "list": [] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "current": { + "text": "text7", + "value": "value7" }, - "title": "Test: V2alpha1 dashboard with group by and adhoc variables", - "variables": [ + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "description": "A group by variable", + "hide": 0, + "label": "Group By Variable", + "multi": false, + "name": "", + "options": [], + "skipUrlSync": false, + "type": "groupby" + }, + { + "allowCustomValue": true, + "baseFilters": [ { - "kind": "GroupByVariable", - "spec": { - "name": "", - "datasource": { - "type": "prometheus", - "uid": "gdev-prometheus" - }, - "current": { - "text": "text7", - "value": "value7" - }, - "options": null, - "multi": false, - "label": "Group By Variable", - "hide": "dontHide", - "skipUrlSync": false, - "description": "A group by variable" - } + "condition": "AND", + "key": "key1", + "operator": "=", + "value": "value1" }, { - "kind": "AdhocVariable", - "spec": { - "name": "adhocVar", - "datasource": { - "type": "prometheus", - "uid": "datasource-3" - }, - "baseFilters": [ - { - "key": "key1", - "operator": "=", - "value": "value1", - "condition": "AND" - }, - { - "key": "key2", - "operator": "=", - "value": "value2", - "condition": "OR" - } - ], - "filters": [ - { - "key": "key3", - "operator": "=", - "value": "value3", - "condition": "AND" - } - ], - "defaultKeys": [ - { - "text": "defaultKey1", - "value": "defaultKey1", - "group": "defaultGroup1", - "expandable": true - } - ], - "label": "Adhoc Variable", - "hide": "dontHide", - "skipUrlSync": false, - "description": "An adhoc variable", - "allowCustomValue": true - } + "condition": "OR", + "key": "key2", + "operator": "=", + "value": "value2" } - ] - }, - "status": { - "conversion": { - "failed": false, - "storedVersion": "v2beta1" - } + ], + "datasource": { + "type": "prometheus", + "uid": "datasource-3" + }, + "defaultKeys": [ + { + "expandable": true, + "group": "defaultGroup1", + "text": "defaultKey1", + "value": "defaultKey1" + } + ], + "description": "An adhoc variable", + "filters": [ + { + "condition": "AND", + "key": "key3", + "operator": "=", + "value": "value3" + } + ], + "hide": 0, + "label": "Adhoc Variable", + "name": "adhocVar", + "skipUrlSync": false, + "type": "adhoc" } - } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "title": "Test: V2alpha1 dashboard with group by and adhoc variables" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2alpha1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v0alpha1.json index c5bd133a7fb..37bbba541cd 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v0alpha1.json @@ -4,185 +4,133 @@ "metadata": { "name": "test-v2alpha1-viz-config" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2alpha1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2alpha1", - "metadata": { - "name": "test-v2alpha1-viz-config" - }, - "spec": { - "annotations": [], - "cursorSync": "", - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Simple timeseries (WITH DS REF)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "grafana-testdata-datasource", - "spec": { - "scenarioId": "random_walk", - "seriesCount": 3 - } - }, - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "gdev-testdata" - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "timeseries", - "spec": { - "pluginVersion": "12.1.0-pre", - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } + "spec": { + "annotations": { + "list": [] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } - } - }, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [ + }, + "thresholds": { + "mode": "absolute", + "steps": [ { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "browser", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Test: V2alpha1 dashboard with viz config", - "variables": [] - }, - "status": { - "conversion": { - "failed": false, - "storedVersion": "v2beta1" } - } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 3 + } + ], + "title": "Simple timeseries (WITH DS REF)", + "type": "timeseries" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "Test: V2alpha1 dashboard with viz config" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2alpha1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.complete.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.complete.v0alpha1.json index 21f71a5b188..b942305c98d 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.complete.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.complete.v0alpha1.json @@ -10,534 +10,415 @@ "description": "Complete example of v2alpha1 dashboard features" } }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "test-v2alpha1-complete", - "labels": { - "category": "test" + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "annotations": { - "description": "Complete example of v2alpha1 dashboard features" - } + "enable": true, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - } - }, - "enable": true, - "hide": false, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "gdev-prometheus" - }, - "spec": { - "expr": "changes(process_start_time_seconds[1m])", - "refId": "Anno" - } - }, - "enable": true, - "hide": false, - "iconColor": "yellow", - "name": "Prometheus Annotations", - "builtIn": false - } - } - ], - "cursorSync": "Tooltip", - "description": "This dashboard demonstrates all features that need to be converted from v2alpha1 to v2beta1", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with Conditional Rendering", - "description": "This panel demonstrates conditional rendering features", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "gdev-prometheus" - }, - "spec": { - "expr": "up{job=\"grafana\"}" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [ - { - "kind": "reduce", - "spec": { - "id": "reduce", - "options": { - "includeTimeField": false, - "mode": "reduceFields", - "reducers": [ - "mean" - ] - } - } - } - ], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "12.1.0-pre", - "spec": { - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "textMode": "auto" - }, - "fieldConfig": { - "defaults": { - "mappings": [ - { - "type": "value", - "options": { - "0": { - "text": "Down", - "color": "red" - }, - "1": { - "text": "Up", - "color": "green" - } - } - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "red" - }, - { - "value": 1, - "color": "green" - } - ] - }, - "color": { - "mode": "thresholds" - } - }, - "overrides": [] - } - } - } - } - } + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "Row", - "spec": { - "title": "Conditional Row", - "collapse": false, - "hideHeader": false, - "fillScreen": false, - "conditionalRendering": { - "kind": "ConditionalRenderingGroup", - "spec": { - "visibility": "show", - "condition": "and", - "items": [ - { - "kind": "ConditionalRenderingVariable", - "spec": { - "variable": "group_by", - "operator": "includes", - "value": "instance" - } - }, - { - "kind": "ConditionalRenderingData", - "spec": { - "value": true - } - }, - { - "kind": "ConditionalRenderingTimeRangeSize", - "spec": { - "value": "1h" - } - } - ] - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 24, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - } - ] - } - } + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "Prometheus Annotations", + "target": { + "expr": "changes(process_start_time_seconds[1m])", + "refId": "Anno" + } + } + ] + }, + "description": "This dashboard demonstrates all features that need to be converted from v2alpha1 to v2beta1", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 2, + "liveNow": true, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": -1, + "title": "Conditional Row", + "type": "row" + }, + { + "description": "This panel demonstrates conditional rendering features", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "color": "red", + "text": "Down" + }, + "1": { + "color": "green", + "text": "Up" } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": 0 + }, + { + "color": "green", + "value": 1 } ] } - }, - "links": [], - "liveNow": true, - "preload": true, - "tags": [ - "test", - "example", - "migration" - ], - "timeSettings": { - "timezone": "browser", - "from": "now-6h", - "to": "now", - "autoRefresh": "10s", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "weekStart": "monday", - "fiscalYearStartMonth": 0 - }, - "title": "Test: Complete V2alpha1 Dashboard Example", - "variables": [ - { - "kind": "SwitchVariable", - "spec": { - "name": "switch_var", - "current": "false", - "enabledValue": "true", - "disabledValue": "false", - "label": "Enable Feature", - "hide": "dontHide", - "skipUrlSync": false, - "description": "Toggle feature on/off" - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "prometheus_query", - "current": { - "text": "All", - "value": [ - "$__all" - ] - }, - "label": "Prometheus Query", - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "description": "Shows all up metrics", - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "gdev-prometheus" - }, - "spec": { - "expr": "up" - } - }, - "regex": "", - "sort": "alphabetical", - "definition": "up", - "options": null, - "multi": true, - "includeAll": true, - "allowCustomValue": false - } - }, - { - "kind": "TextVariable", - "spec": { - "name": "text_var", - "current": { - "selected": true, - "text": "server1", - "value": "server1" - }, - "query": "server1,server2,server3", - "label": "Text Variable", - "hide": "dontHide", - "skipUrlSync": false, - "description": "A simple text variable" - } - }, - { - "kind": "ConstantVariable", - "spec": { - "name": "constant_var", - "query": "production", - "current": { - "selected": true, - "text": "production", - "value": "production" - }, - "label": "Constant", - "hide": "dontHide", - "skipUrlSync": true, - "description": "A constant value" - } - }, - { - "kind": "DatasourceVariable", - "spec": { - "name": "ds_var", - "pluginId": "prometheus", - "refresh": "load", - "regex": "/^gdev-/", - "current": { - "text": "gdev-prometheus", - "value": "gdev-prometheus" - }, - "options": [ - { - "text": "gdev-prometheus", - "value": "gdev-prometheus" - } - ], - "multi": false, - "includeAll": false, - "label": "Datasource", - "hide": "dontHide", - "skipUrlSync": false, - "description": "Select a datasource", - "allowCustomValue": false - } - }, - { - "kind": "IntervalVariable", - "spec": { - "name": "interval", - "query": "1m,5m,10m,30m,1h,6h,12h,1d", - "current": { - "selected": true, - "text": "5m", - "value": "5m" - }, - "options": [ - { - "text": "1m", - "value": "1m" - }, - { - "text": "5m", - "value": "5m" - }, - { - "text": "10m", - "value": "10m" - }, - { - "text": "30m", - "value": "30m" - }, - { - "text": "1h", - "value": "1h" - }, - { - "text": "6h", - "value": "6h" - }, - { - "text": "12h", - "value": "12h" - }, - { - "text": "1d", - "value": "1d" - } - ], - "auto": true, - "auto_min": "10s", - "auto_count": 30, - "refresh": "onTimeRangeChanged", - "label": "Interval", - "hide": "dontHide", - "skipUrlSync": false, - "description": "Time interval selection" - } - }, - { - "kind": "CustomVariable", - "spec": { - "name": "custom_var", - "query": "prod : Production, staging : Staging, dev : Development", - "current": { - "text": [ - "Production" - ], - "value": [ - "prod" - ] - }, - "options": [ - { - "text": "Production", - "value": "prod" - }, - { - "text": "Staging", - "value": "staging" - }, - { - "text": "Development", - "value": "dev" - } - ], - "multi": true, - "includeAll": true, - "allValue": "*", - "label": "Custom Options", - "hide": "dontHide", - "skipUrlSync": false, - "description": "Custom multi-value variable", - "allowCustomValue": true - } - }, - { - "kind": "GroupByVariable", - "group": "prometheus", - "datasource": { - "name": "gdev-prometheus" - }, - "spec": { - "name": "group_by", - "current": { - "text": "instance", - "value": "instance" - }, - "options": null, - "multi": false, - "label": "Group By", - "hide": "dontHide", - "skipUrlSync": false, - "description": "Group metrics by label" - } - }, - { - "kind": "AdhocVariable", - "group": "prometheus", - "datasource": { - "name": "gdev-prometheus" - }, - "spec": { - "name": "filters", - "baseFilters": [ - { - "key": "job", - "operator": "=", - "value": "grafana", - "condition": "AND" - } - ], - "filters": [], - "defaultKeys": [ - { - "text": "job", - "value": "job", - "expandable": true - }, - { - "text": "instance", - "value": "instance", - "expandable": true - } - ], - "label": "Filters", - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": false - } - } - ] - }, - "status": { - "conversion": { - "failed": false, - "storedVersion": "v2alpha1" } - } + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "textMode": "auto" + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "expr": "up{job=\"grafana\"}", + "refId": "A" + } + ], + "title": "Panel with Conditional Rendering", + "transformations": [ + { + "id": "reduce", + "options": { + "includeTimeField": false, + "mode": "reduceFields", + "reducers": [ + "mean" + ] + } + } + ], + "type": "stat" } + ], + "preload": true, + "refresh": "10s", + "schemaVersion": 42, + "tags": [ + "test", + "example", + "migration" + ], + "templating": { + "list": [ + { + "current": { + "text": "false", + "value": "false" + }, + "description": "Toggle feature on/off", + "hide": 0, + "label": "Enable Feature", + "name": "switch_var", + "options": [ + { + "selected": false, + "text": "true", + "value": "true" + }, + { + "selected": true, + "text": "false", + "value": "false" + } + ], + "query": "", + "skipUrlSync": false, + "type": "switch" + }, + { + "allowCustomValue": false, + "current": { + "text": "All", + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "definition": "up", + "description": "Shows all up metrics", + "hide": 0, + "includeAll": true, + "label": "Prometheus Query", + "multi": true, + "name": "prometheus_query", + "options": [], + "query": { + "expr": "up" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "text": "server1", + "value": "server1" + }, + "description": "A simple text variable", + "hide": 0, + "label": "Text Variable", + "name": "text_var", + "query": "server1,server2,server3", + "skipUrlSync": false, + "type": "textbox" + }, + { + "current": { + "text": "production", + "value": "production" + }, + "description": "A constant value", + "hide": 2, + "label": "Constant", + "name": "constant_var", + "query": "production", + "skipUrlSync": true, + "type": "constant" + }, + { + "allowCustomValue": false, + "current": { + "text": "gdev-prometheus", + "value": "gdev-prometheus" + }, + "description": "Select a datasource", + "hide": 0, + "includeAll": false, + "label": "Datasource", + "multi": false, + "name": "ds_var", + "options": [ + { + "text": "gdev-prometheus", + "value": "gdev-prometheus" + } + ], + "query": "prometheus", + "refresh": 0, + "regex": "/^gdev-/", + "skipUrlSync": false, + "type": "datasource" + }, + { + "auto": true, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "description": "Time interval selection", + "hide": 0, + "label": "Interval", + "name": "interval", + "options": [ + { + "text": "1m", + "value": "1m" + }, + { + "text": "5m", + "value": "5m" + }, + { + "text": "10m", + "value": "10m" + }, + { + "text": "30m", + "value": "30m" + }, + { + "text": "1h", + "value": "1h" + }, + { + "text": "6h", + "value": "6h" + }, + { + "text": "12h", + "value": "12h" + }, + { + "text": "1d", + "value": "1d" + } + ], + "query": "1m,5m,10m,30m,1h,6h,12h,1d", + "skipUrlSync": false, + "type": "interval" + }, + { + "allValue": "*", + "allowCustomValue": true, + "current": { + "text": [ + "Production" + ], + "value": [ + "prod" + ] + }, + "description": "Custom multi-value variable", + "hide": 0, + "includeAll": true, + "label": "Custom Options", + "multi": true, + "name": "custom_var", + "options": [ + { + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "staging" + }, + { + "text": "Development", + "value": "dev" + } + ], + "query": "prod : Production, staging : Staging, dev : Development", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "text": "instance", + "value": "instance" + }, + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "description": "Group metrics by label", + "hide": 0, + "label": "Group By", + "multi": false, + "name": "group_by", + "options": [], + "skipUrlSync": false, + "type": "groupby" + }, + { + "allowCustomValue": false, + "baseFilters": [ + { + "condition": "AND", + "key": "job", + "operator": "=", + "value": "grafana" + } + ], + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "defaultKeys": [ + { + "expandable": true, + "text": "job", + "value": "job" + }, + { + "expandable": true, + "text": "instance", + "value": "instance" + } + ], + "hide": 0, + "label": "Filters", + "name": "filters", + "skipUrlSync": false, + "type": "adhoc" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "Test: Complete V2alpha1 Dashboard Example", + "weekStart": "monday" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.dashboard-properties.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.dashboard-properties.v0alpha1.json index 94507deec93..8ed346c0bc2 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.dashboard-properties.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.dashboard-properties.v0alpha1.json @@ -7,221 +7,158 @@ "test": "dashboard-properties" } }, - "spec": null, + "spec": { + "annotations": { + "list": [ + { + "enable": true, + "hide": false, + "iconColor": "blue", + "name": "Simple Annotation", + "target": { + "refId": "Anno" + } + } + ] + }, + "description": "Testing dashboard-level property transformations including time settings, cursor sync, and links", + "editable": true, + "fiscalYearStartMonth": 4, + "graphTooltip": 2, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "monitoring", + "alerts" + ], + "targetBlank": true, + "title": "External Monitoring System", + "tooltip": "View in external system", + "type": "link", + "url": "https://monitoring.example.com/dashboard?from=${__from}\u0026to=${__to}" + }, + { + "asDropdown": true, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [ + "grafana", + "internal" + ], + "targetBlank": false, + "title": "Related Dashboards", + "tooltip": "Navigate to related dashboards", + "type": "dashboards", + "url": "" + }, + { + "asDropdown": false, + "icon": "info", + "includeVars": false, + "keepTime": false, + "placement": "inControlsMenu", + "tags": [], + "targetBlank": true, + "title": "Documentation", + "tooltip": "View documentation", + "type": "link", + "url": "https://docs.example.com/dashboard-guide" + }, + { + "asDropdown": false, + "icon": "tag", + "includeVars": true, + "keepTime": true, + "tags": [ + "alerts" + ], + "targetBlank": false, + "title": "Tag-based Link", + "tooltip": "Filtered by tags", + "type": "tag", + "url": "/dashboards/tag/alerts" + } + ], + "liveNow": true, + "panels": [ + { + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": {}, + "pluginVersion": "", + "targets": [ + { + "refId": "A" + } + ], + "title": "Simple Panel", + "type": "stat" + } + ], + "preload": true, + "refresh": "30s", + "schemaVersion": 42, + "tags": [ + "test", + "properties", + "metadata" + ], + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "value1", + "value": "value1" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "simple_var", + "options": [], + "query": "value1,value2,value3", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-12h", + "to": "now" + }, + "timepicker": { + "nowDelay": "1m", + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "America/New_York", + "title": "Dashboard Properties Test", + "weekStart": "sunday" + }, "status": { "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "dashboard-properties-test", - "labels": { - "test": "dashboard-properties" - } - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "spec": { - "refId": "Anno" - } - }, - "enable": true, - "hide": false, - "iconColor": "blue", - "name": "Simple Annotation", - "builtIn": false - } - } - ], - "cursorSync": "Tooltip", - "description": "Testing dashboard-level property transformations including time settings, cursor sync, and links", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Simple Panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - } - ] - } - }, - "links": [ - { - "title": "External Monitoring System", - "type": "link", - "icon": "external link", - "tooltip": "View in external system", - "url": "https://monitoring.example.com/dashboard?from=${__from}\u0026to=${__to}", - "tags": [ - "monitoring", - "alerts" - ], - "asDropdown": false, - "targetBlank": true, - "includeVars": true, - "keepTime": true - }, - { - "title": "Related Dashboards", - "type": "dashboards", - "icon": "dashboard", - "tooltip": "Navigate to related dashboards", - "url": "", - "tags": [ - "grafana", - "internal" - ], - "asDropdown": true, - "targetBlank": false, - "includeVars": false, - "keepTime": false - }, - { - "title": "Documentation", - "type": "link", - "icon": "info", - "tooltip": "View documentation", - "url": "https://docs.example.com/dashboard-guide", - "tags": [], - "asDropdown": false, - "targetBlank": true, - "includeVars": false, - "keepTime": false, - "placement": "inControlsMenu" - }, - { - "title": "Tag-based Link", - "type": "tag", - "icon": "tag", - "tooltip": "Filtered by tags", - "url": "/dashboards/tag/alerts", - "tags": [ - "alerts" - ], - "asDropdown": false, - "targetBlank": false, - "includeVars": true, - "keepTime": true - } - ], - "liveNow": true, - "preload": true, - "tags": [ - "test", - "properties", - "metadata" - ], - "timeSettings": { - "timezone": "America/New_York", - "from": "now-12h", - "to": "now", - "autoRefresh": "30s", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "weekStart": "sunday", - "fiscalYearStartMonth": 4, - "nowDelay": "1m" - }, - "title": "Dashboard Properties Test", - "variables": [ - { - "kind": "CustomVariable", - "spec": { - "name": "simple_var", - "query": "value1,value2,value3", - "current": { - "text": "value1", - "value": "value1" - }, - "options": [], - "multi": false, - "includeAll": false, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - } - ] - }, - "status": {} - } + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.datasource-resolution.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.datasource-resolution.v0alpha1.json index eaa7c1c2549..c1066edc211 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.datasource-resolution.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.datasource-resolution.v0alpha1.json @@ -4,813 +4,575 @@ "metadata": { "name": "test-v2beta1-datasource-resolution" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "test-v2beta1-datasource-resolution" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - } - }, - "enable": true, - "hide": false, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true, - "legacyOptions": { - "type": "dashboard" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "existing-ref-uid" - }, - "spec": { - "expr": "ALERTS{alertstate=\"firing\"}", - "interval": "1m", - "refId": "Anno", - "step": 60 - } - }, - "enable": true, - "hide": false, - "iconColor": "red", - "name": "Annotation with DS UID defined", - "builtIn": false, - "legacyOptions": { - "type": "prometheus" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "spec": { - "query": "tags:deployment", - "refId": "Anno", - "timeField": "@timestamp" - } - }, - "enable": true, - "hide": false, - "iconColor": "yellow", - "name": "Annotations only with group defined", - "builtIn": false, - "legacyOptions": { - "tagsField": "tags", - "textField": "message", - "timeEndField": "end_time", - "timeField": "@timestamp", - "type": "elasticsearch" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "spec": { - "format": "table", - "rawSql": "SELECT time, title, text, tags FROM annotations WHERE $__timeFilter(time)", - "refId": "Anno" - } - }, - "enable": true, - "hide": false, - "iconColor": "green", - "name": "Annotation without group or UID defined ", - "builtIn": false - } - } - ], - "cursorSync": "Tooltip", - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Panel with group and name defined", - "description": "This should resolve to the grafana-testdata-datasource datasource", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "gdev-testdata" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 3 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.1.0-pre", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Panel with group defined but no name", - "description": "This should resolve to the first elasticsearch datasource", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "spec": { - "alias": "", - "bucketAggs": [], - "metrics": [], - "query": "", - "timeField": "@timestamp" - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.1.0-pre", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel with no group defined", - "description": "This should resolve to the default datasource", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "spec": { - "scenarioId": "random_walk", - "seriesCount": 3 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.1.0-pre", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel mixed Datasource and Group defined", - "description": "This should resolve to a mixed datasource", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "existing-ref-uid" - }, - "spec": { - "query": "up" - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "spec": { - "bucketAggs": [ - { - "field": "@host", - "id": "2", - "type": "terms" - } - ], - "query": "*", - "size": 100 - } - }, - "refId": "B", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "spec": { - "scenarioId": "random_walk", - "seriesCount": 3 - } - }, - "refId": "C", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.1.0-pre", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ + "enable": true, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + }, + { + "datasource": { + "type": "prometheus", + "uid": "existing-ref-uid" + }, + "enable": true, + "hide": false, + "iconColor": "red", + "name": "Annotation with DS UID defined", + "target": { + "expr": "ALERTS{alertstate=\"firing\"}", + "interval": "1m", + "refId": "Anno", + "step": 60 + }, + "type": "prometheus" + }, + { + "datasource": { + "type": "elasticsearch" + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "Annotations only with group defined", + "tagsField": "tags", + "target": { + "query": "tags:deployment", + "refId": "Anno", + "timeField": "@timestamp" + }, + "textField": "message", + "timeEndField": "end_time", + "timeField": "@timestamp", + "type": "elasticsearch" + }, + { + "enable": true, + "hide": false, + "iconColor": "green", + "name": "Annotation without group or UID defined ", + "target": { + "format": "table", + "rawSql": "SELECT time, title, text, tags FROM annotations WHERE $__timeFilter(time)", + "refId": "Anno" + } + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 2, + "liveNow": false, + "panels": [ + { + "description": "This should resolve to the grafana-testdata-datasource datasource", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ { - "kind": "Row", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "fillScreen": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 8, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 3, - "width": 8, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 6, - "width": 8, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 9, - "width": 8, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - } - ] - } - } - } + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "browser", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Test: V2beta1 dashboard with datasource resolution", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "group_and_uid_defined", - "current": { - "text": "legacy_value", - "value": "legacy_string_content" - }, - "label": "Group and UID defined", - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "description": "Variable with group and UID defined", - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "existing-ref-uid" - }, - "spec": { - "__legacyStringValue": "up" - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "group_defined_but_no_name", - "current": { - "text": "legacy_value", - "value": "legacy_string_content" - }, - "label": "Group defined but no name", - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "description": "Variable with group defined but no name", - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "spec": { - "bucketAggs": [ - { - "field": "@host", - "id": "2", - "type": "terms" - } - ], - "query": "*", - "size": 100 - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "no_group_defined", - "current": { - "text": "legacy_value", - "value": "legacy_string_content" - }, - "label": "No group defined", - "hide": "dontHide", - "refresh": "onDashboardLoad", - "skipUrlSync": false, - "description": "Variable with no group defined", - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "spec": { - "scenarioId": "random_walk", - "seriesCount": 3 - } - }, - "regex": "", - "sort": "disabled", - "options": [], - "multi": false, - "includeAll": false, - "allowCustomValue": true - } - } - ] - }, - "status": { - "conversion": { - "failed": false, - "storedVersion": "v2beta1" } - } + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 3 + } + ], + "title": "Panel with group and name defined", + "type": "timeseries" + }, + { + "description": "This should resolve to the first elasticsearch datasource", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 3 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch" + }, + "metrics": [], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Panel with group defined but no name", + "type": "timeseries" + }, + { + "description": "This should resolve to the default datasource", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 6 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 3 + } + ], + "title": "Panel with no group defined", + "type": "timeseries" + }, + { + "datasource": { + "type": "mixed", + "uid": "-- Mixed --" + }, + "description": "This should resolve to a mixed datasource", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 9 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "existing-ref-uid" + }, + "query": "up", + "refId": "A" + }, + { + "bucketAggs": [ + { + "field": "@host", + "id": "2", + "type": "terms" + } + ], + "datasource": { + "type": "elasticsearch" + }, + "query": "*", + "refId": "B", + "size": 100 + }, + { + "refId": "C", + "scenarioId": "random_walk", + "seriesCount": 3 + } + ], + "title": "Panel mixed Datasource and Group defined", + "type": "timeseries" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": "legacy_value", + "value": "legacy_string_content" + }, + "datasource": { + "type": "prometheus", + "uid": "existing-ref-uid" + }, + "description": "Variable with group and UID defined", + "hide": 0, + "includeAll": false, + "label": "Group and UID defined", + "multi": false, + "name": "group_and_uid_defined", + "options": [], + "query": "up", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "legacy_value", + "value": "legacy_string_content" + }, + "datasource": { + "type": "elasticsearch" + }, + "description": "Variable with group defined but no name", + "hide": 0, + "includeAll": false, + "label": "Group defined but no name", + "multi": false, + "name": "group_defined_but_no_name", + "options": [], + "query": { + "bucketAggs": [ + { + "field": "@host", + "id": "2", + "type": "terms" + } + ], + "query": "*", + "size": 100 + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": true, + "current": { + "text": "legacy_value", + "value": "legacy_string_content" + }, + "description": "Variable with no group defined", + "hide": 0, + "includeAll": false, + "label": "No group defined", + "multi": false, + "name": "no_group_defined", + "options": [], + "query": { + "scenarioId": "random_walk", + "seriesCount": 3 + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "Test: V2beta1 dashboard with datasource resolution" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.ds-data-query.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.ds-data-query.v0alpha1.json index 121b020c0f0..6a418f1e21d 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.ds-data-query.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.ds-data-query.v0alpha1.json @@ -4,1141 +4,825 @@ "metadata": { "name": "test-v2alpha1-annotations" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "test-v2alpha1-annotations" - }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - } - }, - "enable": true, - "hide": false, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "PD8C576611E62080A" - }, - "spec": { - "lines": 10, - "refId": "Anno", - "scenarioId": "annotations" - } - }, - "enable": true, - "hide": false, - "iconColor": "blue", - "name": "testdata-annos", - "builtIn": false - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "lines": 10, - "refId": "Anno", - "scenarioId": "annotations" - } - }, - "enable": true, - "hide": false, - "iconColor": "blue", - "name": "no-ds-testdata-annos", - "builtIn": false - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "gdev-prometheus" - }, - "spec": { - "expr": "{action=\"add_client\"}", - "interval": "", - "lines": 10, - "refId": "Anno", - "scenarioId": "annotations" - } - }, - "enable": true, - "hide": false, - "iconColor": "yellow", - "name": "prom-annos", - "builtIn": false - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "expr": "{action=\"add_client\"}", - "interval": "", - "lines": 10, - "refId": "Anno", - "scenarioId": "annotations" - } - }, - "enable": true, - "hide": false, - "iconColor": "yellow", - "name": "no-ds-prom-annos", - "builtIn": false - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-postgresql-datasource", - "version": "v0", - "datasource": { - "name": "PBBCEC2D313BC06C3" - }, - "spec": { - "editorMode": "builder", - "format": "table", - "lines": 10, - "rawSql": "", - "refId": "Anno", - "scenarioId": "annotations", - "sql": { - "columns": [ - { - "parameters": [], - "type": "function" - } - ], - "groupBy": [ - { - "property": { - "type": "string" - }, - "type": "groupBy" - } - ], - "limit": 50 - } - } - }, - "enable": true, - "hide": false, - "iconColor": "red", - "name": "postgress-annos", - "builtIn": false - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "elasticsearch", - "version": "v0", - "datasource": { - "name": "gdev-elasticsearch" - }, - "spec": { - "lines": 10, - "query": "test query", - "refId": "Anno", - "scenarioId": "annotations" - } - }, - "enable": true, - "hide": false, - "iconColor": "red", - "name": "elastic - annos", - "builtIn": false, - "legacyOptions": { - "tagsField": "asd", - "textField": "asd", - "timeEndField": "asdas", - "timeField": "asd" - } - } - } - ], - "cursorSync": "Off", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Simple timeseries (WITH DS REF)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "gdev-testdata" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 3 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.1.0-pre", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "Simple stat (NO DS REF)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "spec": { - "scenarioId": "random_walk", - "seriesCount": 4 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "stat", - "version": "12.1.0-pre", - "spec": { - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "thresholds" - } - }, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel with NO REF to gdev-prometheus", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(counters_requests[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "instant": false, - "legendFormat": "__auto", - "range": true, - "useBackend": false - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.1.0-pre", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel with ref to gdev-prometheus", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "gdev-prometheus" - }, - "spec": { - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(counters_requests[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "instant": false, - "legendFormat": "__auto", - "range": true, - "useBackend": false - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.1.0-pre", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Mixed DS WITH REFS", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "gdev-prometheus" - }, - "spec": { - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "legendFormat": "__auto", - "range": true, - "useBackend": false - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "gdev-testdata" - }, - "spec": {} - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.1.0-pre", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Mixed DS WITHOUT REFS", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "legendFormat": "__auto", - "range": true, - "useBackend": false - } - }, - "refId": "A", - "hidden": false - } - }, - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "spec": {} - }, - "refId": "B", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.1.0-pre", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - } + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ + "enable": true, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "enable": true, + "hide": false, + "iconColor": "blue", + "name": "testdata-annos", + "target": { + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + { + "datasource": { + "type": "prometheus" + }, + "enable": true, + "hide": false, + "iconColor": "blue", + "name": "no-ds-testdata-annos", + "target": { + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "prom-annos", + "target": { + "expr": "{action=\"add_client\"}", + "interval": "", + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + { + "datasource": { + "type": "prometheus" + }, + "enable": true, + "hide": false, + "iconColor": "yellow", + "name": "no-ds-prom-annos", + "target": { + "expr": "{action=\"add_client\"}", + "interval": "", + "lines": 10, + "refId": "Anno", + "scenarioId": "annotations" + } + }, + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PBBCEC2D313BC06C3" + }, + "enable": true, + "hide": false, + "iconColor": "red", + "name": "postgress-annos", + "target": { + "editorMode": "builder", + "format": "table", + "lines": 10, + "rawSql": "", + "refId": "Anno", + "scenarioId": "annotations", + "sql": { + "columns": [ { - "kind": "Row", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "fillScreen": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 8, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 8, - "y": 0, - "width": 8, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 0, - "width": 8, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 3, - "width": 8, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 8, - "y": 3, - "width": 8, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "x": 16, - "y": 3, - "width": 8, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } - } - ] - } - } - } + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "enable": true, + "hide": false, + "iconColor": "red", + "name": "elastic - annos", + "tagsField": "asd", + "target": { + "lines": 10, + "query": "test query", + "refId": "Anno", + "scenarioId": "annotations" + }, + "textField": "asd", + "timeEndField": "asdas", + "timeField": "asd" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "browser", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Test: V2alpha1 dashboard with annotations", - "variables": [ - { - "kind": "QueryVariable", - "spec": { - "name": "variable-ds-prometheus", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "datasource": { - "name": "gdev-prometheus" - }, - "spec": { - "expr": "up" - } - }, - "regex": "", - "sort": "", - "options": null, - "multi": false, - "includeAll": false, - "allowCustomValue": false - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "variable-no-ds", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "spec": { - "csv": "1,2,3,4", - "scenarioId": "csv_metric_values" - } - }, - "regex": "", - "sort": "", - "options": null, - "multi": false, - "includeAll": false, - "allowCustomValue": false - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "variable-no-ds-empty-query", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "spec": {} - }, - "regex": "", - "sort": "", - "options": null, - "multi": false, - "includeAll": false, - "allowCustomValue": false - } - }, - { - "kind": "QueryVariable", - "spec": { - "name": "variable-no-default-ds", - "current": { - "text": "", - "value": "" - }, - "hide": "dontHide", - "refresh": "", - "skipUrlSync": false, - "query": { - "kind": "DataQuery", - "group": "prometheus", - "version": "v0", - "spec": { - "expr": "up" - } - }, - "regex": "", - "sort": "", - "options": null, - "multi": false, - "includeAll": false, - "allowCustomValue": false - } - } - ] - }, - "status": { - "conversion": { - "failed": false, - "storedVersion": "v2alpha1" } - } + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "prometheus" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Panel with NO REF to gdev-prometheus", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Panel with ref to gdev-prometheus", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 4 + } + ], + "title": "Simple stat (NO DS REF)", + "type": "stat" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 3 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 3 + } + ], + "title": "Simple timeseries (WITH DS REF)", + "type": "timeseries" + }, + { + "datasource": { + "type": "mixed", + "uid": "-- Mixed --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 8, + "y": 3 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, + "refId": "B" + } + ], + "title": "Mixed DS WITH REFS", + "type": "timeseries" + }, + { + "datasource": { + "type": "mixed", + "uid": "-- Mixed --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 16, + "y": 3 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "prometheus" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "B" + } + ], + "title": "Mixed DS WITHOUT REFS", + "type": "timeseries" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": false, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "variable-ds-prometheus", + "options": [], + "query": { + "expr": "up" + }, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": false, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "grafana-testdata-datasource" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "variable-no-ds", + "options": [], + "query": { + "csv": "1,2,3,4", + "scenarioId": "csv_metric_values" + }, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": false, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "grafana-testdata-datasource" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "variable-no-ds-empty-query", + "options": [], + "query": {}, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allowCustomValue": false, + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "variable-no-default-ds", + "options": [], + "query": { + "expr": "up" + }, + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "Test: V2alpha1 dashboard with annotations" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.groupby-adhoc-vars.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.groupby-adhoc-vars.v0alpha1.json index 9de5535160d..c165c9de4e6 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.groupby-adhoc-vars.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.groupby-adhoc-vars.v0alpha1.json @@ -4,115 +4,91 @@ "metadata": { "name": "test-v2alpha1-groupby-adhoc-vars" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "test-v2alpha1-groupby-adhoc-vars" + "spec": { + "annotations": { + "list": [] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "current": { + "text": "text7", + "value": "value7" + }, + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, + "description": "A group by variable", + "hide": 0, + "label": "Group By Variable", + "multi": false, + "name": "", + "options": [], + "skipUrlSync": false, + "type": "groupby" }, - "spec": { - "annotations": [], - "cursorSync": "", - "elements": {}, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [] - } - }, - "links": [], - "preload": false, - "tags": [], - "timeSettings": { - "from": "", - "to": "", - "autoRefresh": "", - "autoRefreshIntervals": null, - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Test: V2alpha1 dashboard with group by and adhoc variables", - "variables": [ + { + "allowCustomValue": true, + "baseFilters": [ { - "kind": "GroupByVariable", - "group": "prometheus", - "datasource": { - "name": "gdev-prometheus" - }, - "spec": { - "name": "", - "current": { - "text": "text7", - "value": "value7" - }, - "options": null, - "multi": false, - "label": "Group By Variable", - "hide": "dontHide", - "skipUrlSync": false, - "description": "A group by variable" - } + "condition": "AND", + "key": "key1", + "operator": "=", + "value": "value1" }, { - "kind": "AdhocVariable", - "group": "prometheus", - "datasource": { - "name": "datasource-3" - }, - "spec": { - "name": "adhocVar", - "baseFilters": [ - { - "key": "key1", - "operator": "=", - "value": "value1", - "condition": "AND" - }, - { - "key": "key2", - "operator": "=", - "value": "value2", - "condition": "OR" - } - ], - "filters": [ - { - "key": "key3", - "operator": "=", - "value": "value3", - "condition": "AND" - } - ], - "defaultKeys": [ - { - "text": "defaultKey1", - "value": "defaultKey1", - "group": "defaultGroup1", - "expandable": true - } - ], - "label": "Adhoc Variable", - "hide": "dontHide", - "skipUrlSync": false, - "description": "An adhoc variable", - "allowCustomValue": true - } + "condition": "OR", + "key": "key2", + "operator": "=", + "value": "value2" } - ] - }, - "status": { - "conversion": { - "failed": false, - "storedVersion": "v2alpha1" - } + ], + "datasource": { + "type": "prometheus", + "uid": "datasource-3" + }, + "defaultKeys": [ + { + "expandable": true, + "group": "defaultGroup1", + "text": "defaultKey1", + "value": "defaultKey1" + } + ], + "description": "An adhoc variable", + "filters": [ + { + "condition": "AND", + "key": "key3", + "operator": "=", + "value": "value3" + } + ], + "hide": 0, + "label": "Adhoc Variable", + "name": "adhocVar", + "skipUrlSync": false, + "type": "adhoc" } - } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "title": "Test: V2alpha1 dashboard with group by and adhoc variables" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.rows-with-nested-tabs.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.rows-with-nested-tabs.v0alpha1.json index fc54e3d14ff..f81abd723dc 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.rows-with-nested-tabs.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.rows-with-nested-tabs.v0alpha1.json @@ -17,567 +17,416 @@ "grafana.app/saved-from-ui": "Grafana Cloud" } }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "ivx9964", - "namespace": "stacks-5756", - "uid": "627d3b09-32b6-4e0c-b5b7-b94be6fc94b6", - "resourceVersion": "1764589364114772", - "generation": 1, - "creationTimestamp": "2025-12-01T11:42:44Z", - "labels": { - "grafana.app/deprecatedInternalID": "363903738712064" + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "annotations": { - "grafana.app/createdBy": "user:ff3wylp4sgpa8a", - "grafana.app/folder": "", - "grafana.app/saved-from-ui": "Grafana Cloud" - } + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "description": "", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true - } - } - ], - "cursorSync": "Off", - "description": "", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "New panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "defin43am9o1sd" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 1 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.4.0-19736337744", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "showValues": false, - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } + "id": -1, + "panels": [], + "title": "Row with tabs", + "type": "row" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1 + }, + "id": -1, + "panels": [], + "title": "Tab with panels", + "type": "row" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "New panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "defin43am9o1sd" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 1 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.4.0-19736337744", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "showValues": false, - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "New panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "defin43am9o1sd" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 1 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.4.0-19736337744", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "showValues": false, - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ + "thresholds": { + "mode": "absolute", + "steps": [ { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row with tabs", - "collapse": false, - "layout": { - "kind": "TabsLayout", - "spec": { - "tabs": [ - { - "kind": "TabsLayoutTab", - "spec": { - "title": "Tab with panels", - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - } - ] - } - } - } - }, - { - "kind": "TabsLayoutTab", - "spec": { - "title": "Empty tab", - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [] - } - } - } - } - ] - } - } - } + "color": "green", + "value": 0 }, { - "kind": "RowsLayoutRow", - "spec": { - "title": "Empty row", - "collapse": false, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row with rows", - "collapse": false, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Empty nested row", - "collapse": false, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row with panels filling screen", - "collapse": false, - "fillScreen": true, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [ - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - }, - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - } - ] - } - } - } - } - ] - } - } - } + "color": "red", + "value": 80 } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "browser", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Rows with nested tabs", - "variables": [] + } }, - "status": {} + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 2 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1 + } + ], + "title": "New panel", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": -1, + "panels": [], + "title": "Empty tab", + "type": "row" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": -1, + "title": "Empty row", + "type": "row" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": -1, + "panels": [], + "title": "Row with rows", + "type": "row" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 12 + }, + "id": -1, + "title": "Empty nested row", + "type": "row" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 12 + }, + "id": -1, + "title": "Row with panels filling screen", + "type": "row" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 12 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1 + } + ], + "title": "New panel", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 12 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1 + } + ], + "title": "New panel", + "type": "timeseries" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "Rows with nested tabs" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-and-rows-repeated.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-and-rows-repeated.v0alpha1.json index 5a8c0a0965b..ef513d48d97 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-and-rows-repeated.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-and-rows-repeated.v0alpha1.json @@ -17,1003 +17,727 @@ "grafana.app/saved-from-ui": "Grafana Cloud" } }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "ivc5gfp", - "namespace": "stacks-5756", - "uid": "353905c9-661c-47af-89ac-a0e966c5b3c7", - "resourceVersion": "1764588557728998", - "generation": 2, - "creationTimestamp": "2025-12-01T11:29:17Z", - "labels": { - "grafana.app/deprecatedInternalID": "360521534459904" + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "annotations": { - "grafana.app/createdBy": "user:ff3wylp4sgpa8a", - "grafana.app/folder": "", - "grafana.app/saved-from-ui": "Grafana Cloud" - } + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "description": "", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true - } - } - ], - "cursorSync": "Off", - "description": "", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "New panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "defin43am9o1sd" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 4 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.4.0-19736337744", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "showValues": false, - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } + "id": -1, + "panels": [], + "title": "Tab without rows", + "type": "row" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "New panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "defin43am9o1sd" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 5 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.4.0-19736337744", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "showValues": false, - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "Panel in collapsed row 1", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "defin43am9o1sd" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 1 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.4.0-19736337744", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "showValues": false, - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "Panel in collapsed row 2", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "defin43am9o1sd" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 1 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.4.0-19736337744", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "showValues": false, - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "id": 5, - "title": "Panel in hidden header row", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "defin43am9o1sd" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 5 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.4.0-19736337744", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "showValues": false, - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "id": 6, - "title": "Repeated Panel within tab \"$custom_var_panel\"", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "", - "version": "v0", - "spec": {} - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "__unconfigured-panel", - "version": "12.4.0-19736337744", - "spec": { - "options": {}, - "fieldConfig": { - "defaults": {}, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "TabsLayout", - "spec": { - "tabs": [ + "thresholds": { + "mode": "absolute", + "steps": [ { - "kind": "TabsLayoutTab", - "spec": { - "title": "Tab without rows", - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - } - ] - } - } - } + "color": "green", + "value": 0 }, { - "kind": "TabsLayoutTab", - "spec": { - "title": "Tab With Rows", - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row without tabs", - "collapse": true, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [ - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Collapsed row", - "collapse": true, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [ - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Empty row", - "collapse": false, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Hide header row", - "collapse": false, - "hideHeader": true, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [ - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - } - ] - } - } - } - } - ] - } - } - } - }, - { - "kind": "TabsLayoutTab", - "spec": { - "title": "Repeated Tab by \"$custom_var_tab\"", - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Repeated by \"$custom_var_row\"", - "collapse": false, - "repeat": { - "mode": "variable", - "value": "custom_var_row" - }, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [ - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-6" - }, - "repeat": { - "mode": "variable", - "value": "custom_var_panel" - } - } - } - ] - } - } - } - } - ] - } - }, - "repeat": { - "mode": "variable", - "value": "custom_var_tab" - } - } + "color": "red", + "value": 80 } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "browser", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Tabs and rows repeated", - "variables": [ - { - "kind": "CustomVariable", - "spec": { - "name": "custom_var_tab", - "query": "option 1, option 2, option 3", - "current": { - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "options": [ - { - "selected": false, - "text": "option 1", - "value": "option 1" - }, - { - "selected": false, - "text": "option 2", - "value": "option 2" - }, - { - "selected": false, - "text": "option 3", - "value": "option 3" - } - ], - "multi": true, - "includeAll": true, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "CustomVariable", - "spec": { - "name": "custom_var_row", - "query": "option 1 1, Option 1 2, Option 1 3", - "current": { - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "options": [ - { - "selected": false, - "text": "option 1 1", - "value": "option 1 1" - }, - { - "selected": false, - "text": "Option 1 2", - "value": "Option 1 2" - }, - { - "selected": false, - "text": "Option 1 3", - "value": "Option 1 3" - } - ], - "multi": true, - "includeAll": true, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - }, - { - "kind": "CustomVariable", - "spec": { - "name": "custom_var_panel", - "query": "Panel 1, Panel 2, Panel 3", - "current": { - "text": [ - "All" - ], - "value": [ - "$__all" - ] - }, - "options": [ - { - "selected": false, - "text": "Panel 1", - "value": "Panel 1" - }, - { - "selected": false, - "text": "Panel 2", - "value": "Panel 2" - }, - { - "selected": false, - "text": "Panel 3", - "value": "Panel 3" - } - ], - "multi": true, - "includeAll": true, - "hide": "dontHide", - "skipUrlSync": false, - "allowCustomValue": true - } - } - ] + } }, - "status": {} + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 4 + } + ], + "title": "New panel", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": -1, + "panels": [], + "title": "Tab With Rows", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": -1, + "panels": [ + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 11 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 5 + } + ], + "title": "New panel", + "type": "timeseries" + } + ], + "title": "Row without tabs", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": -1, + "panels": [ + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 12 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1 + } + ], + "title": "Panel in collapsed row 1", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 12 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1 + } + ], + "title": "Panel in collapsed row 2", + "type": "timeseries" + } + ], + "title": "Collapsed row", + "type": "row" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 12 + }, + "id": -1, + "title": "Empty row", + "type": "row" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 12 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 5 + } + ], + "title": "Panel in hidden header row", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": -1, + "panels": [], + "title": "Repeated Tab by \"$custom_var_tab\"", + "type": "row" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 22 + }, + "id": -1, + "repeat": "custom_var_row", + "title": "Repeated by \"$custom_var_row\"", + "type": "row" + }, + { + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 22 + }, + "id": 6, + "options": {}, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "refId": "A" + } + ], + "title": "Repeated Panel within tab \"$custom_var_panel\"", + "type": "__unconfigured-panel" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "templating": { + "list": [ + { + "allowCustomValue": true, + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "hide": 0, + "includeAll": true, + "multi": true, + "name": "custom_var_tab", + "options": [ + { + "selected": false, + "text": "option 1", + "value": "option 1" + }, + { + "selected": false, + "text": "option 2", + "value": "option 2" + }, + { + "selected": false, + "text": "option 3", + "value": "option 3" + } + ], + "query": "option 1, option 2, option 3", + "skipUrlSync": false, + "type": "custom" + }, + { + "allowCustomValue": true, + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "hide": 0, + "includeAll": true, + "multi": true, + "name": "custom_var_row", + "options": [ + { + "selected": false, + "text": "option 1 1", + "value": "option 1 1" + }, + { + "selected": false, + "text": "Option 1 2", + "value": "Option 1 2" + }, + { + "selected": false, + "text": "Option 1 3", + "value": "Option 1 3" + } + ], + "query": "option 1 1, Option 1 2, Option 1 3", + "skipUrlSync": false, + "type": "custom" + }, + { + "allowCustomValue": true, + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "hide": 0, + "includeAll": true, + "multi": true, + "name": "custom_var_panel", + "options": [ + { + "selected": false, + "text": "Panel 1", + "value": "Panel 1" + }, + { + "selected": false, + "text": "Panel 2", + "value": "Panel 2" + }, + { + "selected": false, + "text": "Panel 3", + "value": "Panel 3" + } + ], + "query": "Panel 1, Panel 2, Panel 3", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "Tabs and rows repeated" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-with-nested-rows.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-with-nested-rows.v0alpha1.json index b66ff05a9df..6ed7076e121 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-with-nested-rows.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-with-nested-rows.v0alpha1.json @@ -17,675 +17,484 @@ "grafana.app/saved-from-ui": "Grafana Cloud" } }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "ivc5gfp", - "namespace": "stacks-5756", - "uid": "353905c9-661c-47af-89ac-a0e966c5b3c7", - "resourceVersion": "1764588557728998", - "generation": 1, - "creationTimestamp": "2025-12-01T11:29:17Z", - "labels": { - "grafana.app/deprecatedInternalID": "360521534459904" + "spec": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, - "annotations": { - "grafana.app/createdBy": "user:ff3wylp4sgpa8a", - "grafana.app/folder": "", - "grafana.app/saved-from-ui": "Grafana Cloud" - } + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "description": "", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 }, - "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana", - "version": "v0", - "datasource": { - "name": "-- Grafana --" - }, - "spec": {} - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "builtIn": true - } - } - ], - "cursorSync": "Off", - "description": "", - "editable": true, - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "New panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "defin43am9o1sd" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 4 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.4.0-19736337744", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "showValues": false, - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } + "id": -1, + "panels": [], + "title": "Tab without rows", + "type": "row" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "panel-2": { - "kind": "Panel", - "spec": { - "id": 2, - "title": "New panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "defin43am9o1sd" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 5 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.4.0-19736337744", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "showValues": false, - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "id": 3, - "title": "New panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "defin43am9o1sd" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 1 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.4.0-19736337744", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "showValues": false, - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "id": 4, - "title": "New panel", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "defin43am9o1sd" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 1 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.4.0-19736337744", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "showValues": false, - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } - } - } - }, - "layout": { - "kind": "TabsLayout", - "spec": { - "tabs": [ + "thresholds": { + "mode": "absolute", + "steps": [ { - "kind": "TabsLayoutTab", - "spec": { - "title": "Tab without rows", - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 12, - "height": 8, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - } - ] - } - } - } + "color": "green", + "value": 0 }, { - "kind": "TabsLayoutTab", - "spec": { - "title": "Tab With Rows", - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row without tabs", - "collapse": true, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [ - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-2" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Row with tabs", - "collapse": true, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [ - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - } - ] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Empty row", - "collapse": false, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [] - } - } - } - }, - { - "kind": "RowsLayoutRow", - "spec": { - "title": "Hide header row", - "collapse": false, - "hideHeader": true, - "layout": { - "kind": "AutoGridLayout", - "spec": { - "maxColumnCount": 3, - "columnWidthMode": "standard", - "rowHeightMode": "standard", - "items": [] - } - } - } - } - ] - } - } - } + "color": "red", + "value": 80 } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "browser", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Dashboard with tabs and rows", - "variables": [] + } }, - "status": {} + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 4 + } + ], + "title": "New panel", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": -1, + "panels": [], + "title": "Tab With Rows", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": -1, + "panels": [ + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 11 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 5 + } + ], + "title": "New panel", + "type": "timeseries" + } + ], + "title": "Row without tabs", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": -1, + "panels": [ + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 12 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1 + } + ], + "title": "New panel", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "showValues": false, + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + } + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 12 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.4.0-19736337744", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1 + } + ], + "title": "New panel", + "type": "timeseries" + } + ], + "title": "Row with tabs", + "type": "row" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 12 + }, + "id": -1, + "title": "Empty row", + "type": "row" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "Dashboard with tabs and rows" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.viz-config.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.viz-config.v0alpha1.json index 66354d45ff6..0502ebf6b4c 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.viz-config.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.viz-config.v0alpha1.json @@ -4,204 +4,133 @@ "metadata": { "name": "test-v2beta1-viz-config" }, - "spec": null, - "status": { - "conversion": { - "failed": true, - "error": "backend conversion not yet implemented", - "storedVersion": "v2beta1", - "source": { - "kind": "Dashboard", - "apiVersion": "dashboard.grafana.app/v2beta1", - "metadata": { - "name": "test-v2beta1-viz-config" - }, - "spec": { - "annotations": [], - "cursorSync": "Tooltip", - "elements": { - "panel-1": { - "kind": "Panel", - "spec": { - "id": 1, - "title": "Simple timeseries (WITH DS REF)", - "description": "", - "links": [], - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "datasource": { - "name": "gdev-testdata" - }, - "spec": { - "scenarioId": "random_walk", - "seriesCount": 3 - } - }, - "refId": "A", - "hidden": false - } - } - ], - "transformations": [], - "queryOptions": {} - } - }, - "vizConfig": { - "kind": "VizConfig", - "group": "timeseries", - "version": "12.1.0-pre", - "spec": { - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "fieldConfig": { - "defaults": { - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": 0, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - } - }, - "overrides": [] - } - } - } + "spec": { + "annotations": { + "list": [] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 2, + "liveNow": false, + "panels": [ + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } - } - }, - "layout": { - "kind": "RowsLayout", - "spec": { - "rows": [ + }, + "thresholds": { + "mode": "absolute", + "steps": [ { - "kind": "Row", - "spec": { - "title": "", - "collapse": false, - "hideHeader": true, - "fillScreen": false, - "layout": { - "kind": "GridLayout", - "spec": { - "items": [ - { - "kind": "GridLayoutItem", - "spec": { - "x": 0, - "y": 0, - "width": 8, - "height": 3, - "element": { - "kind": "ElementReference", - "name": "panel-1" - } - } - } - ] - } - } - } + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 } ] } - }, - "links": [], - "liveNow": false, - "preload": false, - "tags": [], - "timeSettings": { - "timezone": "browser", - "from": "now-6h", - "to": "now", - "autoRefresh": "", - "autoRefreshIntervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "hideTimepicker": false, - "fiscalYearStartMonth": 0 - }, - "title": "Test: V2alpha1 dashboard with viz config", - "variables": [] - }, - "status": { - "conversion": { - "failed": false, - "storedVersion": "v2alpha1" } - } + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 3 + } + ], + "title": "Simple timeseries (WITH DS REF)", + "type": "timeseries" } + ], + "preload": false, + "refresh": "", + "schemaVersion": 42, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "Test: V2alpha1 dashboard with viz config" + }, + "status": { + "conversion": { + "failed": false, + "storedVersion": "v2beta1" } } } \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/conversion/v1beta1_to_v2alpha1.go b/apps/dashboard/pkg/migration/conversion/v1beta1_to_v2alpha1.go index da8e8a6ae28..236a4337efb 100644 --- a/apps/dashboard/pkg/migration/conversion/v1beta1_to_v2alpha1.go +++ b/apps/dashboard/pkg/migration/conversion/v1beta1_to_v2alpha1.go @@ -12,6 +12,7 @@ import ( "k8s.io/apiserver/pkg/endpoints/request" "github.com/grafana/authlib/types" + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard" dashv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1" dashv2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1" schemaversion "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" @@ -52,6 +53,16 @@ func getDatasourceTypeByUID(ctx context.Context, uid string, provider schemavers return getDefaultDatasourceType(ctx, provider) } +// resolveGrafanaDatasourceUID resolves the Grafana datasource UID when type is "datasource" and UID is empty. +// The Grafana datasource has type "datasource" and UID "grafana". When a v1beta1 dashboard has +// datasource: { type: "datasource" } with no UID, it should resolve to uid: "grafana". +func resolveGrafanaDatasourceUID(dsType, dsUID string) string { + if dsType == "datasource" && dsUID == "" { + return dashboard.GrafanaDatasourceUID + } + return dsUID +} + // prepareV1beta1ConversionContext sets up the context with namespace and service identity // for v1beta1 dashboard conversions. This context is needed to retrieve datasources for // converting dashboard datasource references. @@ -1528,26 +1539,38 @@ func buildAdhocVariable(ctx context.Context, varMap map[string]interface{}, comm }, } - // Transform baseFilters if they exist + // Transform baseFilters if they exist, otherwise default to empty array if baseFilters, exists := varMap["baseFilters"]; exists { if baseFiltersArray, ok := baseFilters.([]interface{}); ok { adhocVar.Spec.BaseFilters = transformAdHocFilters(baseFiltersArray) } } + // Ensure baseFilters is always set (default to empty array if not present or invalid) + if adhocVar.Spec.BaseFilters == nil { + adhocVar.Spec.BaseFilters = []dashv2alpha1.DashboardAdHocFilterWithLabels{} + } - // Transform filters if they exist + // Transform filters if they exist, otherwise default to empty array if filters, exists := varMap["filters"]; exists { if filtersArray, ok := filters.([]interface{}); ok { adhocVar.Spec.Filters = transformAdHocFilters(filtersArray) } } + // Ensure filters is always set (default to empty array if not present or invalid) + if adhocVar.Spec.Filters == nil { + adhocVar.Spec.Filters = []dashv2alpha1.DashboardAdHocFilterWithLabels{} + } - // Transform defaultKeys if they exist + // Transform defaultKeys if they exist, otherwise default to empty array if defaultKeys, exists := varMap["defaultKeys"]; exists { if defaultKeysArray, ok := defaultKeys.([]interface{}); ok { adhocVar.Spec.DefaultKeys = transformMetricFindValues(defaultKeysArray) } } + // Ensure defaultKeys is always set (default to empty array if not present or invalid) + if adhocVar.Spec.DefaultKeys == nil { + adhocVar.Spec.DefaultKeys = []dashv2alpha1.DashboardMetricFindValue{} + } // Only include datasource if datasourceUID exists (matching frontend behavior) if datasourceUID != "" { @@ -1674,6 +1697,9 @@ func buildGroupByVariable(ctx context.Context, varMap map[string]interface{}, co // If no UID and no type, use default datasourceType = getDefaultDatasourceType(ctx, dsIndexProvider) } + + // Resolve Grafana datasource UID when type is "datasource" and UID is empty + datasourceUID = resolveGrafanaDatasourceUID(datasourceType, datasourceUID) } else { datasourceType = getDefaultDatasourceType(ctx, dsIndexProvider) } @@ -1929,22 +1955,45 @@ func transformPanelQueries(ctx context.Context, panelMap map[string]interface{}, // Get panel datasource var panelDatasource *dashv2alpha1.DashboardDataSourceRef - if ds, ok := panelMap["datasource"].(map[string]interface{}); ok { - dsUID := schemaversion.GetStringValue(ds, "uid") - dsType := schemaversion.GetStringValue(ds, "type") + ds, dsExists := panelMap["datasource"] - // If we have a UID, use it to get the correct type from the datasource service - // BUT: Don't try to resolve types for template variables - if dsUID != "" && dsType == "" && !isTemplateVariable(dsUID) { - dsType = getDatasourceTypeByUID(ctx, dsUID, dsIndexProvider) - } else if dsUID == "" && dsType == "" { - // If no UID and no type, use default - dsType = getDefaultDatasourceType(ctx, dsIndexProvider) - } + if dsExists && ds != nil { + if dsMap, ok := ds.(map[string]interface{}); ok { + // Handle panel datasource as object + dsUID := schemaversion.GetStringValue(dsMap, "uid") + dsType := schemaversion.GetStringValue(dsMap, "type") - panelDatasource = &dashv2alpha1.DashboardDataSourceRef{ - Type: &dsType, - Uid: &dsUID, + // Check if datasource object is effectively empty (no uid and no type) + // Empty objects {} should be preserved as empty, not converted to defaults + isEmpty := dsUID == "" && dsType == "" + + // If we have a UID, use it to get the correct type from the datasource service + // BUT: Don't try to resolve types for template variables + if dsUID != "" && dsType == "" && !isTemplateVariable(dsUID) { + dsType = getDatasourceTypeByUID(ctx, dsUID, dsIndexProvider) + } else if !isEmpty && dsUID == "" && dsType == "" { + // Only set default if datasource is missing (not empty object) + // Empty objects {} should remain empty + dsType = getDefaultDatasourceType(ctx, dsIndexProvider) + } + + // Resolve Grafana datasource UID when type is "datasource" and UID is empty + // Only resolve if we have a type (not for empty objects) + if !isEmpty { + dsUID = resolveGrafanaDatasourceUID(dsType, dsUID) + } + + // Only create panelDatasource if it's not empty after resolution + // Empty objects {} should result in nil panelDatasource + // After resolution, check if we have a type or UID (not just the original isEmpty) + // This ensures that type: "datasource" with empty UID gets resolved to uid: "grafana" + // and panelDatasource is created + if dsType != "" || dsUID != "" { + panelDatasource = &dashv2alpha1.DashboardDataSourceRef{ + Type: &dsType, + Uid: &dsUID, + } + } } } @@ -1971,12 +2020,24 @@ func transformSingleQuery(ctx context.Context, targetMap map[string]interface{}, queryDatasourceUID = schemaversion.GetStringValue(ds, "uid") queryDatasourceType = schemaversion.GetStringValue(ds, "type") - // If we have a UID, use it to get the correct type from the datasource service - // BUT: Don't try to resolve types for template variables - if queryDatasourceUID != "" && queryDatasourceType == "" && !isTemplateVariable(queryDatasourceUID) { - queryDatasourceType = getDatasourceTypeByUID(ctx, queryDatasourceUID, dsIndexProvider) + // If target datasource is empty object {} (no uid and no type), treat it as missing + // and fall through to use panel datasource (matches frontend behavior in v36 migration) + if queryDatasourceUID == "" && queryDatasourceType == "" { + // Empty datasource object - will use panel datasource below + } else { + // If we have a UID, use it to get the correct type from the datasource service + // BUT: Don't try to resolve types for template variables + if queryDatasourceUID != "" && queryDatasourceType == "" && !isTemplateVariable(queryDatasourceUID) { + queryDatasourceType = getDatasourceTypeByUID(ctx, queryDatasourceUID, dsIndexProvider) + } + + // Resolve Grafana datasource UID when type is "datasource" and UID is empty + queryDatasourceUID = resolveGrafanaDatasourceUID(queryDatasourceType, queryDatasourceUID) } - } else if panelDatasource != nil { + } + + // Use panel datasource if target datasource is missing or empty + if queryDatasourceUID == "" && queryDatasourceType == "" && panelDatasource != nil { // Only use panel datasource if it's not a mixed datasource // Mixed datasources should not be propagated to individual queries if panelDatasource.Uid != nil && *panelDatasource.Uid != "-- Mixed --" { @@ -1984,6 +2045,10 @@ func transformSingleQuery(ctx context.Context, targetMap map[string]interface{}, queryDatasourceType = *panelDatasource.Type } queryDatasourceUID = *panelDatasource.Uid + } else if panelDatasource.Type != nil && *panelDatasource.Type == "datasource" { + // Handle case where panel datasource has type "datasource" but no UID + queryDatasourceType = *panelDatasource.Type + queryDatasourceUID = resolveGrafanaDatasourceUID(*panelDatasource.Type, "") } } diff --git a/apps/dashboard/pkg/migration/conversion/v1beta1_to_v2alpha1_test.go b/apps/dashboard/pkg/migration/conversion/v1beta1_to_v2alpha1_test.go new file mode 100644 index 00000000000..3dad9188fe7 --- /dev/null +++ b/apps/dashboard/pkg/migration/conversion/v1beta1_to_v2alpha1_test.go @@ -0,0 +1,228 @@ +package conversion + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/runtime" + + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard" + dashv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1" + dashv2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1" + "github.com/grafana/grafana/apps/dashboard/pkg/migration" + migrationtestutil "github.com/grafana/grafana/apps/dashboard/pkg/migration/testutil" +) + +// TestV1beta1ToV2alpha1 tests conversion from v1beta1 to v2alpha1 with various datasource scenarios +func TestV1beta1ToV2alpha1(t *testing.T) { + // Initialize the migrator with test providers + dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig) + leProvider := migrationtestutil.NewLibraryElementProvider() + migration.Initialize(dsProvider, leProvider) + + // Set up conversion scheme + scheme := runtime.NewScheme() + err := RegisterConversions(scheme, dsProvider, leProvider) + require.NoError(t, err) + + testCases := []struct { + name string + createV1beta1 func() *dashv1.Dashboard + validateV2alpha1 func(t *testing.T, v2alpha1 *dashv2alpha1.Dashboard) + }{ + { + name: "panel datasource type datasource with no UID - resolves to grafana UID", + createV1beta1: func() *dashv1.Dashboard { + return &dashv1.Dashboard{ + Spec: dashv1.DashboardSpec{ + Object: map[string]interface{}{ + "title": "Test Dashboard", + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "bargauge", + // Panel datasource has type: "datasource" but no UID + "datasource": map[string]interface{}{ + "type": "datasource", + // No "uid" field + }, + "targets": []interface{}{ + map[string]interface{}{ + "refId": "A", + "scenarioId": "random_walk", + // Target datasource is empty object {} + "datasource": map[string]interface{}{}, + }, + }, + }, + }, + }, + }, + } + }, + validateV2alpha1: func(t *testing.T, v2alpha1 *dashv2alpha1.Dashboard) { + require.NotNil(t, v2alpha1.Spec.Elements["panel-1"]) + panel := v2alpha1.Spec.Elements["panel-1"].PanelKind + require.NotNil(t, panel) + + // Verify queries have datasource with UID resolved to "grafana" + require.Len(t, panel.Spec.Data.Spec.Queries, 1) + query := panel.Spec.Data.Spec.Queries[0] + require.NotNil(t, query.Spec.Datasource, "Query should have datasource") + + // Verify datasource type is "datasource" + assert.NotNil(t, query.Spec.Datasource.Type) + assert.Equal(t, "datasource", *query.Spec.Datasource.Type) + + // Verify datasource UID is resolved to "grafana" + assert.NotNil(t, query.Spec.Datasource.Uid) + assert.Equal(t, dashboard.GrafanaDatasourceUID, *query.Spec.Datasource.Uid, "type: 'datasource' with no UID should resolve to uid: 'grafana'") + + // Verify query kind matches datasource type + assert.Equal(t, "datasource", query.Spec.Query.Kind) + }, + }, + { + name: "empty target datasource objects inherit from panel datasource", + createV1beta1: func() *dashv1.Dashboard { + return &dashv1.Dashboard{ + Spec: dashv1.DashboardSpec{ + Object: map[string]interface{}{ + "title": "Test Dashboard", + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "bargauge", + // Panel datasource is set + "datasource": map[string]interface{}{ + "type": "prometheus", + "uid": "prometheus-uid", + }, + "targets": []interface{}{ + map[string]interface{}{ + "refId": "A", + "scenarioId": "random_walk", + // Target datasource is empty object {} - should inherit from panel + "datasource": map[string]interface{}{}, + }, + map[string]interface{}{ + "refId": "B", + "scenarioId": "random_walk", + "datasource": map[string]interface{}{}, + }, + }, + }, + }, + }, + }, + } + }, + validateV2alpha1: func(t *testing.T, v2alpha1 *dashv2alpha1.Dashboard) { + require.NotNil(t, v2alpha1.Spec.Elements["panel-1"]) + panel := v2alpha1.Spec.Elements["panel-1"].PanelKind + require.NotNil(t, panel) + + // Verify queries inherit panel datasource + require.Len(t, panel.Spec.Data.Spec.Queries, 2) + for _, query := range panel.Spec.Data.Spec.Queries { + require.NotNil(t, query.Spec.Datasource, "Query should inherit datasource from panel when target datasource is empty") + assert.Equal(t, "prometheus", *query.Spec.Datasource.Type) + assert.Equal(t, "prometheus-uid", *query.Spec.Datasource.Uid) + assert.Equal(t, "prometheus", query.Spec.Query.Kind) + } + }, + }, + { + name: "panel datasource null without empty target datasource objects - no default set", + createV1beta1: func() *dashv1.Dashboard { + return &dashv1.Dashboard{ + Spec: dashv1.DashboardSpec{ + Object: map[string]interface{}{ + "title": "Test Dashboard", + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "bargauge", + // Panel datasource is null + "datasource": nil, + "targets": []interface{}{ + map[string]interface{}{ + "refId": "A", + "scenarioId": "random_walk", + // Target has no datasource field at all (not even empty object) + }, + }, + }, + }, + }, + }, + } + }, + validateV2alpha1: func(t *testing.T, v2alpha1 *dashv2alpha1.Dashboard) { + require.NotNil(t, v2alpha1.Spec.Elements["panel-1"]) + panel := v2alpha1.Spec.Elements["panel-1"].PanelKind + require.NotNil(t, panel) + + // Verify queries don't have datasource when panel is null and targets don't have empty datasource objects + require.Len(t, panel.Spec.Data.Spec.Queries, 1) + query := panel.Spec.Data.Spec.Queries[0] + // Query should not have datasource when panel datasource is null and target doesn't have empty datasource object + assert.Nil(t, query.Spec.Datasource, "Query should not have datasource when panel datasource is null and target has no empty datasource object") + }, + }, + { + name: "empty panel datasource object preserved as empty", + createV1beta1: func() *dashv1.Dashboard { + return &dashv1.Dashboard{ + Spec: dashv1.DashboardSpec{ + Object: map[string]interface{}{ + "title": "Test Dashboard", + "panels": []interface{}{ + map[string]interface{}{ + "id": 1, + "type": "bargauge", + // Panel datasource is empty object {} - should be preserved as empty + "datasource": map[string]interface{}{}, + "targets": []interface{}{ + map[string]interface{}{ + "refId": "A", + "scenarioId": "random_walk", + "datasource": map[string]interface{}{}, + }, + }, + }, + }, + }, + }, + } + }, + validateV2alpha1: func(t *testing.T, v2alpha1 *dashv2alpha1.Dashboard) { + require.NotNil(t, v2alpha1.Spec.Elements["panel-1"]) + panel := v2alpha1.Spec.Elements["panel-1"].PanelKind + require.NotNil(t, panel) + + // Verify queries don't have datasource when panel datasource is empty object {} + require.Len(t, panel.Spec.Data.Spec.Queries, 1) + query := panel.Spec.Data.Spec.Queries[0] + // Empty objects {} should be preserved as empty, not converted to defaults + assert.Nil(t, query.Spec.Datasource, "Query should not have datasource when panel datasource is empty object {}") + assert.Equal(t, "", query.Spec.Query.Kind, "Query kind should be empty when datasource is empty object {}") + }, + }, + } + + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + v1beta1Dash := tt.createV1beta1() + + // Convert to v2alpha1 + var v2alpha1Dash dashv2alpha1.Dashboard + err := scheme.Convert(v1beta1Dash, &v2alpha1Dash, nil) + require.NoError(t, err) + + // Validate the conversion result + tt.validateV2alpha1(t, &v2alpha1Dash) + }) + } +} diff --git a/apps/dashboard/pkg/migration/conversion/v2.go b/apps/dashboard/pkg/migration/conversion/v2.go index 09245f991a3..fee798d3ec5 100644 --- a/apps/dashboard/pkg/migration/conversion/v2.go +++ b/apps/dashboard/pkg/migration/conversion/v2.go @@ -11,22 +11,45 @@ import ( "github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion" ) -func Convert_V2alpha1_to_V0(in *dashv2alpha1.Dashboard, out *dashv0.Dashboard, scope conversion.Scope) error { - out.ObjectMeta = in.ObjectMeta - out.APIVersion = dashv0.APIVERSION - out.Kind = in.Kind - - // TODO: implement V2 to V0 conversion - - out.Status = dashv0.DashboardStatus{ - Conversion: &dashv0.DashboardConversionStatus{ - StoredVersion: ptr.To(dashv2alpha1.VERSION), - Failed: true, - Error: ptr.To("backend conversion not yet implemented"), - Source: in, - }, +func Convert_V2alpha1_to_V0(in *dashv2alpha1.Dashboard, out *dashv0.Dashboard, scope conversion.Scope, dsIndexProvider schemaversion.DataSourceIndexProvider) error { + // Convert v2alpha1 → v1beta1 first, then v1beta1 → v0 + v1beta1 := &dashv1.Dashboard{} + if err := ConvertDashboard_V2alpha1_to_V1beta1(in, v1beta1, scope, dsIndexProvider); err != nil { + out.ObjectMeta = in.ObjectMeta + out.APIVersion = dashv0.APIVERSION + out.Kind = in.Kind + out.Status = dashv0.DashboardStatus{ + Conversion: &dashv0.DashboardConversionStatus{ + StoredVersion: ptr.To(dashv2alpha1.VERSION), + Failed: true, + Error: ptr.To(err.Error()), + Source: in, + }, + } + // For errors, set status but don't return error + return nil } + // Convert v1beta1 → v0 + if err := Convert_V1beta1_to_V0(v1beta1, out, scope); err != nil { + out.ObjectMeta = in.ObjectMeta + out.APIVersion = dashv0.APIVERSION + out.Kind = in.Kind + out.Status = dashv0.DashboardStatus{ + Conversion: &dashv0.DashboardConversionStatus{ + StoredVersion: ptr.To(dashv2alpha1.VERSION), + Failed: true, + Error: ptr.To(err.Error()), + Source: in, + }, + } + // For errors, set status but don't return error + return nil + } + + // Update the stored version to reflect the original source + out.Status.Conversion.StoredVersion = ptr.To(dashv2alpha1.VERSION) + return nil } @@ -46,7 +69,7 @@ func Convert_V2alpha1_to_V1beta1(in *dashv2alpha1.Dashboard, out *dashv1.Dashboa }, } - // For errors, set status but don't return error (matches v1beta1_to_v2alpha1 pattern) + // For errors, set status but don't return error return nil } @@ -91,22 +114,44 @@ func Convert_V2alpha1_to_V2beta1(in *dashv2alpha1.Dashboard, out *dashv2beta1.Da return nil } -func Convert_V2beta1_to_V0(in *dashv2beta1.Dashboard, out *dashv0.Dashboard, scope conversion.Scope) error { - out.ObjectMeta = in.ObjectMeta - out.APIVersion = dashv0.APIVERSION - out.Kind = in.Kind - - // TODO: implement v2beta1 to V0 conversion - - out.Status = dashv0.DashboardStatus{ - Conversion: &dashv0.DashboardConversionStatus{ - StoredVersion: ptr.To(dashv2beta1.VERSION), - Failed: true, - Error: ptr.To("backend conversion not yet implemented"), - Source: in, - }, +func Convert_V2beta1_to_V0(in *dashv2beta1.Dashboard, out *dashv0.Dashboard, scope conversion.Scope, dsIndexProvider schemaversion.DataSourceIndexProvider) error { + // Convert v2beta1 → v1beta1 first, then v1beta1 → v0 + v1beta1 := &dashv1.Dashboard{} + if err := Convert_V2beta1_to_V1beta1(in, v1beta1, scope, dsIndexProvider); err != nil { + out.ObjectMeta = in.ObjectMeta + out.APIVersion = dashv0.APIVERSION + out.Kind = in.Kind + out.Status = dashv0.DashboardStatus{ + Conversion: &dashv0.DashboardConversionStatus{ + StoredVersion: ptr.To(dashv2beta1.VERSION), + Failed: true, + Error: ptr.To(err.Error()), + Source: in, + }, + } + // For errors, set status but don't return error + return nil } + // Convert v1beta1 → v0 + if err := Convert_V1beta1_to_V0(v1beta1, out, scope); err != nil { + out.ObjectMeta = in.ObjectMeta + out.APIVersion = dashv0.APIVERSION + out.Kind = in.Kind + out.Status = dashv0.DashboardStatus{ + Conversion: &dashv0.DashboardConversionStatus{ + StoredVersion: ptr.To(dashv2beta1.VERSION), + Failed: true, + Error: ptr.To(err.Error()), + Source: in, + }, + } + return nil + } + + // Update the stored version to reflect the original source + out.Status.Conversion.StoredVersion = ptr.To(dashv2beta1.VERSION) + return nil } @@ -127,7 +172,7 @@ func Convert_V2beta1_to_V1beta1(in *dashv2beta1.Dashboard, out *dashv1.Dashboard Source: in, }, } - // For errors, set status but don't return error (matches v1beta1_to_v2alpha1 pattern) + // For errors, set status but don't return error return nil } @@ -143,7 +188,7 @@ func Convert_V2beta1_to_V1beta1(in *dashv2beta1.Dashboard, out *dashv1.Dashboard Source: in, }, } - // For errors, set status but don't return error (matches v1beta1_to_v2alpha1 pattern) + // For errors, set status but don't return error return nil } diff --git a/apps/example/go.mod b/apps/example/go.mod index deb8763474c..d63d23be302 100644 --- a/apps/example/go.mod +++ b/apps/example/go.mod @@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/example go 1.25.5 require ( - github.com/grafana/grafana-app-sdk v0.48.4 + github.com/grafana/grafana-app-sdk v0.48.5 github.com/grafana/grafana-app-sdk/logging v0.48.3 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20251017153501-8512b219c5fe k8s.io/apimachinery v0.34.2 diff --git a/apps/example/go.sum b/apps/example/go.sum index 4a43a44d46c..70c83a9fe37 100644 --- a/apps/example/go.sum +++ b/apps/example/go.sum @@ -56,8 +56,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.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 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/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-20251017153501-8512b219c5fe h1:pPoFj2bQKDBg5EyEdOU+Jn+0hQN+M775Qihk73RbdSs= diff --git a/apps/example/kinds/cue.mod/module.cue b/apps/example/kinds/cue.mod/module.cue index b2f49fc6dc6..7720c73be54 100644 --- a/apps/example/kinds/cue.mod/module.cue +++ b/apps/example/kinds/cue.mod/module.cue @@ -1,2 +1,4 @@ module: "github.com/grafana/grafana/apps/example/kinds" -language: version: "v0.8.2" +language: { + version: "v0.11.0" +} diff --git a/apps/folder/Makefile b/apps/folder/Makefile index a6abc7a5337..f72a2bc7dbd 100644 --- a/apps/folder/Makefile +++ b/apps/folder/Makefile @@ -8,5 +8,6 @@ generate: install-app-sdk update-app-sdk ## Run Grafana App SDK code generation --grouping=group \ --defencoding=none \ --genoperatorstate=false \ - --noschemasinmanifest \ - --useoldmanifestkinds + --noschemasinmanifest + + \ No newline at end of file diff --git a/apps/folder/go.mod b/apps/folder/go.mod index 0e04414b8b8..476c6949c73 100644 --- a/apps/folder/go.mod +++ b/apps/folder/go.mod @@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/folder go 1.25.5 require ( - github.com/grafana/grafana-app-sdk v0.48.4 + github.com/grafana/grafana-app-sdk v0.48.5 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e k8s.io/apimachinery v0.34.2 k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 diff --git a/apps/folder/go.sum b/apps/folder/go.sum index c83ee8af102..d8454185267 100644 --- a/apps/folder/go.sum +++ b/apps/folder/go.sum @@ -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.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 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/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-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ= diff --git a/apps/folder/kinds/cue.mod/module.cue b/apps/folder/kinds/cue.mod/module.cue index a127320c53d..cb78692c697 100644 --- a/apps/folder/kinds/cue.mod/module.cue +++ b/apps/folder/kinds/cue.mod/module.cue @@ -1,4 +1,4 @@ module: "github.com/grafana/grafana/apps/folder/kinds" language: { - version: "v0.9.0" + version: "v0.11.0" } diff --git a/apps/folder/kinds/folder.cue b/apps/folder/kinds/folder.cue index 44423768205..24ba0c83dd4 100644 --- a/apps/folder/kinds/folder.cue +++ b/apps/folder/kinds/folder.cue @@ -1,26 +1,13 @@ package folder -folder: { +foldersV1beta1: { kind: "Folder" pluralName: "Folders" - current: "v1beta1" - versions: { - "v1beta1": { - codegen: { - ts: { - enabled: false // Not sure if it should be enabled or not, currently it is. - } - go: { - enabled: true - } - } - schema: { - spec: { - title: string - description?: string - } - status: {} // nothing - } + + schema: { + spec: { + title: string + description?: string } } -} +} \ No newline at end of file diff --git a/apps/folder/kinds/manifest.cue b/apps/folder/kinds/manifest.cue index cc8b8441315..42235710278 100644 --- a/apps/folder/kinds/manifest.cue +++ b/apps/folder/kinds/manifest.cue @@ -3,7 +3,15 @@ package folder manifest: { appName: "folder" groupOverride: "folder.grafana.app" - kinds: [ - folder, - ] -} + versions: { + "v1beta1": { + codegen: { + ts: {enabled: false} + go: {enabled: true} + } + kinds: [ + foldersV1beta1, + ] + } + } +} \ No newline at end of file diff --git a/apps/folder/pkg/apis/folder/v1beta1/folder_client_gen.go b/apps/folder/pkg/apis/folder/v1beta1/folder_client_gen.go index 6923c21d27c..501bf90a722 100644 --- a/apps/folder/pkg/apis/folder/v1beta1/folder_client_gen.go +++ b/apps/folder/pkg/apis/folder/v1beta1/folder_client_gen.go @@ -4,7 +4,6 @@ import ( "context" "github.com/grafana/grafana-app-sdk/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type FolderClient struct { @@ -76,24 +75,6 @@ func (c *FolderClient) Patch(ctx context.Context, identifier resource.Identifier return c.client.Patch(ctx, identifier, req, opts) } -func (c *FolderClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus FolderStatus, opts resource.UpdateOptions) (*Folder, error) { - return c.client.Update(ctx, &Folder{ - TypeMeta: metav1.TypeMeta{ - Kind: FolderKind().Kind(), - APIVersion: GroupVersion.Identifier(), - }, - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: opts.ResourceVersion, - Namespace: identifier.Namespace, - Name: identifier.Name, - }, - Status: newStatus, - }, resource.UpdateOptions{ - Subresource: "status", - ResourceVersion: opts.ResourceVersion, - }) -} - func (c *FolderClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error { return c.client.Delete(ctx, identifier, opts) } diff --git a/apps/folder/pkg/apis/folder/v1beta1/folder_object_gen.go b/apps/folder/pkg/apis/folder/v1beta1/folder_object_gen.go index ad9318cb3d3..6fabb8f8958 100644 --- a/apps/folder/pkg/apis/folder/v1beta1/folder_object_gen.go +++ b/apps/folder/pkg/apis/folder/v1beta1/folder_object_gen.go @@ -21,8 +21,12 @@ type Folder struct { // Spec is the spec of the Folder Spec FolderSpec `json:"spec" yaml:"spec"` +} - Status FolderStatus `json:"status" yaml:"status"` +func NewFolder() *Folder { + return &Folder{ + Spec: *NewFolderSpec(), + } } func (o *Folder) GetSpec() any { @@ -39,15 +43,11 @@ func (o *Folder) SetSpec(spec any) error { } func (o *Folder) GetSubresources() map[string]any { - return map[string]any{ - "status": o.Status, - } + return map[string]any{} } func (o *Folder) GetSubresource(name string) (any, bool) { switch name { - case "status": - return o.Status, true default: return nil, false } @@ -55,13 +55,6 @@ func (o *Folder) GetSubresource(name string) (any, bool) { func (o *Folder) SetSubresource(name string, value any) error { switch name { - case "status": - cast, ok := value.(FolderStatus) - if !ok { - return fmt.Errorf("cannot set status type %#v, not of type FolderStatus", value) - } - o.Status = cast - return nil default: return fmt.Errorf("subresource '%s' does not exist", name) } @@ -233,7 +226,6 @@ func (o *Folder) DeepCopyInto(dst *Folder) { dst.TypeMeta.Kind = o.TypeMeta.Kind o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta) o.Spec.DeepCopyInto(&dst.Spec) - o.Status.DeepCopyInto(&dst.Status) } // Interface compliance compile-time check @@ -305,15 +297,3 @@ func (s *FolderSpec) DeepCopy() *FolderSpec { func (s *FolderSpec) DeepCopyInto(dst *FolderSpec) { resource.CopyObjectInto(dst, s) } - -// DeepCopy creates a full deep copy of FolderStatus -func (s *FolderStatus) DeepCopy() *FolderStatus { - cpy := &FolderStatus{} - s.DeepCopyInto(cpy) - return cpy -} - -// DeepCopyInto deep copies FolderStatus into another FolderStatus object -func (s *FolderStatus) DeepCopyInto(dst *FolderStatus) { - resource.CopyObjectInto(dst, s) -} diff --git a/apps/folder/pkg/apis/folder/v1beta1/folder_schema_gen.go b/apps/folder/pkg/apis/folder/v1beta1/folder_schema_gen.go index f0d4fffe6b0..e626e4773ee 100644 --- a/apps/folder/pkg/apis/folder/v1beta1/folder_schema_gen.go +++ b/apps/folder/pkg/apis/folder/v1beta1/folder_schema_gen.go @@ -10,7 +10,7 @@ import ( // schema is unexported to prevent accidental overwrites var ( - schemaFolder = resource.NewSimpleSchema("folder.grafana.app", "v1beta1", &Folder{}, &FolderList{}, resource.WithKind("Folder"), + schemaFolder = resource.NewSimpleSchema("folder.grafana.app", "v1beta1", NewFolder(), &FolderList{}, resource.WithKind("Folder"), resource.WithPlural("folders"), resource.WithScope(resource.NamespacedScope)) kindFolder = resource.Kind{ Schema: schemaFolder, diff --git a/apps/folder/pkg/apis/folder/v1beta1/folder_status_gen.go b/apps/folder/pkg/apis/folder/v1beta1/folder_status_gen.go deleted file mode 100644 index 1d1cd1f7d24..00000000000 --- a/apps/folder/pkg/apis/folder/v1beta1/folder_status_gen.go +++ /dev/null @@ -1,3 +0,0 @@ -// Code generated - EDITING IS FUTILE. DO NOT EDIT. - -package v1beta1 diff --git a/apps/folder/pkg/apis/folder/v1beta1/zz_generated.openapi.go b/apps/folder/pkg/apis/folder/v1beta1/zz_generated.openapi.go index 235987da8e2..5855d59c65a 100644 --- a/apps/folder/pkg/apis/folder/v1beta1/zz_generated.openapi.go +++ b/apps/folder/pkg/apis/folder/v1beta1/zz_generated.openapi.go @@ -104,18 +104,12 @@ func schema_pkg_apis_folder_v1beta1_Folder(ref common.ReferenceCallback) common. Ref: ref("github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderSpec"), }, }, - "status": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderStatus"), - }, - }, }, - Required: []string{"metadata", "spec", "status"}, + Required: []string{"metadata", "spec"}, }, }, Dependencies: []string{ - "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderSpec", "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1.FolderSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, } } diff --git a/apps/folder/pkg/apis/folder_manifest.go b/apps/folder/pkg/apis/manifestdata/folder_manifest.go similarity index 99% rename from apps/folder/pkg/apis/folder_manifest.go rename to apps/folder/pkg/apis/manifestdata/folder_manifest.go index df164aa6ebc..7c053e52c38 100644 --- a/apps/folder/pkg/apis/folder_manifest.go +++ b/apps/folder/pkg/apis/manifestdata/folder_manifest.go @@ -3,7 +3,7 @@ // DO NOT EDIT // -package apis +package manifestdata import ( "fmt" diff --git a/apps/iam/go.mod b/apps/iam/go.mod index 78da5f7ed9a..474779e0efe 100644 --- a/apps/iam/go.mod +++ b/apps/iam/go.mod @@ -52,7 +52,7 @@ replace github.com/prometheus/alertmanager => github.com/grafana/prometheus-aler require ( github.com/grafana/grafana v0.0.0-00010101000000-000000000000 - github.com/grafana/grafana-app-sdk v0.48.4 + github.com/grafana/grafana-app-sdk v0.48.5 github.com/grafana/grafana-app-sdk/logging v0.48.3 github.com/grafana/grafana/apps/folder v0.0.0 github.com/grafana/grafana/pkg/apimachinery v0.0.0 @@ -221,7 +221,7 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect github.com/googleapis/gax-go/v2 v2.15.0 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/grafana/alerting v0.0.0-20251202151018-58fa500f3232 // indirect + github.com/grafana/alerting v0.0.0-20251204145817-de8c2bbf9eba // indirect github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // indirect github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 // indirect github.com/grafana/dataplane/sdata v0.0.9 // indirect @@ -426,6 +426,7 @@ require ( golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.14.0 // indirect golang.org/x/tools v0.39.0 // indirect + golang.org/x/tools/godoc v0.1.0-deprecated // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect gonum.org/v1/gonum v0.16.0 // indirect diff --git a/apps/iam/go.sum b/apps/iam/go.sum index a10e7d6be79..7f2fd8f462f 100644 --- a/apps/iam/go.sum +++ b/apps/iam/go.sum @@ -817,8 +817,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= 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/alerting v0.0.0-20251202151018-58fa500f3232 h1:I9l/BxoqxTlPUVx05t8OsqbdP/qwqOeD2E5makeeIz0= -github.com/grafana/alerting v0.0.0-20251202151018-58fa500f3232/go.mod h1:l7v67cgP7x72ajB9UPZlumdrHqNztpKoqQ52cU8T3LU= +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/authlib v0.0.0-20250930082137-a40e2c2b094f h1:Cbm6OKkOcJ+7CSZsGsEJzktC/SIa5bxVeYKQLuYK86o= github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f/go.mod h1:axY0cdOg3q0TZHwpHnIz5x16xZ8ZBxJHShsSHHXcHQg= github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 h1:Muoy+FMGrHj3GdFbvsMzUT7eusgii9PKf9L1ZaXDDbY= @@ -835,8 +835,8 @@ github.com/grafana/gofpdf v0.0.0-20250307124105-3b9c5d35577f h1:5xkjl5Y/j2QefJKO github.com/grafana/gofpdf v0.0.0-20250307124105-3b9c5d35577f/go.mod h1:+O5QxOwwgP10jedZHapzXY+IPKTnzHBtIs5UUb9G+kI= github.com/grafana/gomemcache v0.0.0-20250828162811-a96f6acee2fe h1:q+QaVANzNZxvTovycpQvDTfsNZ2rHh4XIIaccMnrIR4= github.com/grafana/gomemcache v0.0.0-20250828162811-a96f6acee2fe/go.mod h1:j/s0jkda4UXTemDs7Pgw/vMT06alWc42CHisvYac0qw= -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 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/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= diff --git a/apps/iam/kinds/cue.mod/module.cue b/apps/iam/kinds/cue.mod/module.cue index d1ddb24fcea..7ca193c8ffd 100644 --- a/apps/iam/kinds/cue.mod/module.cue +++ b/apps/iam/kinds/cue.mod/module.cue @@ -1,4 +1,4 @@ module: "github.com/grafana/grafana/apps/iam/kinds" language: { - version: "v0.9.0" + version: "v0.11.0" } diff --git a/apps/iam/kinds/manifest.cue b/apps/iam/kinds/manifest.cue index bc9c3d47ad7..c6f609cbe15 100644 --- a/apps/iam/kinds/manifest.cue +++ b/apps/iam/kinds/manifest.cue @@ -22,4 +22,32 @@ v0alpha1: { serviceaccountv0alpha1, externalGroupMappingv0alpha1 ] + routes: { + namespaced: { + "/searchTeams": { + "GET": { + request: { + query: { + query?: string + } + } + response: { + #TeamHit: { + name: string + title: string + email: string + provisioned: bool + externalUID: string + } + offset: int64 + totalHits: int64 + hits: [...#TeamHit] + queryCost: float64 + maxScore: float64 + } + responseMetadata: objectMeta: false + } + } + } + } } diff --git a/apps/iam/pkg/apis/iam/v0alpha1/getsearchteams_request_params_object_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/getsearchteams_request_params_object_gen.go new file mode 100644 index 00000000000..76ba539c798 --- /dev/null +++ b/apps/iam/pkg/apis/iam/v0alpha1/getsearchteams_request_params_object_gen.go @@ -0,0 +1,33 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v0alpha1 + +import ( + "github.com/grafana/grafana-app-sdk/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +type GetSearchTeamsRequestParamsObject struct { + metav1.TypeMeta `json:",inline"` + GetSearchTeamsRequestParams `json:",inline"` +} + +func NewGetSearchTeamsRequestParamsObject() *GetSearchTeamsRequestParamsObject { + return &GetSearchTeamsRequestParamsObject{} +} + +func (o *GetSearchTeamsRequestParamsObject) DeepCopyObject() runtime.Object { + dst := NewGetSearchTeamsRequestParamsObject() + o.DeepCopyInto(dst) + return dst +} + +func (o *GetSearchTeamsRequestParamsObject) DeepCopyInto(dst *GetSearchTeamsRequestParamsObject) { + dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion + dst.TypeMeta.Kind = o.TypeMeta.Kind + dstGetSearchTeamsRequestParams := GetSearchTeamsRequestParams{} + _ = resource.CopyObjectInto(&dstGetSearchTeamsRequestParams, &o.GetSearchTeamsRequestParams) +} + +var _ runtime.Object = NewGetSearchTeamsRequestParamsObject() diff --git a/apps/iam/pkg/apis/iam/v0alpha1/getsearchteams_request_params_types_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/getsearchteams_request_params_types_gen.go new file mode 100644 index 00000000000..ffa5067c41b --- /dev/null +++ b/apps/iam/pkg/apis/iam/v0alpha1/getsearchteams_request_params_types_gen.go @@ -0,0 +1,12 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v0alpha1 + +type GetSearchTeamsRequestParams struct { + Query *string `json:"query,omitempty"` +} + +// NewGetSearchTeamsRequestParams creates a new GetSearchTeamsRequestParams object. +func NewGetSearchTeamsRequestParams() *GetSearchTeamsRequestParams { + return &GetSearchTeamsRequestParams{} +} diff --git a/apps/iam/pkg/apis/iam/v0alpha1/getsearchteams_response_body_types_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/getsearchteams_response_body_types_gen.go new file mode 100644 index 00000000000..9fabe93260d --- /dev/null +++ b/apps/iam/pkg/apis/iam/v0alpha1/getsearchteams_response_body_types_gen.go @@ -0,0 +1,33 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v0alpha1 + +// +k8s:openapi-gen=true +type VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit struct { + Name string `json:"name"` + Title string `json:"title"` + Email string `json:"email"` + Provisioned bool `json:"provisioned"` + ExternalUID string `json:"externalUID"` +} + +// NewVersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit creates a new VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit object. +func NewVersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit() *VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit { + return &VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit{} +} + +// +k8s:openapi-gen=true +type GetSearchTeamsBody struct { + Offset int64 `json:"offset"` + TotalHits int64 `json:"totalHits"` + Hits []VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit `json:"hits"` + QueryCost float64 `json:"queryCost"` + MaxScore float64 `json:"maxScore"` +} + +// NewGetSearchTeamsBody creates a new GetSearchTeamsBody object. +func NewGetSearchTeamsBody() *GetSearchTeamsBody { + return &GetSearchTeamsBody{ + Hits: []VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit{}, + } +} diff --git a/apps/iam/pkg/apis/iam/v0alpha1/getsearchteams_response_object_types_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/getsearchteams_response_object_types_gen.go new file mode 100644 index 00000000000..685bd7d85be --- /dev/null +++ b/apps/iam/pkg/apis/iam/v0alpha1/getsearchteams_response_object_types_gen.go @@ -0,0 +1,37 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v0alpha1 + +import ( + "github.com/grafana/grafana-app-sdk/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// +k8s:openapi-gen=true +type GetSearchTeams struct { + metav1.TypeMeta `json:",inline"` + GetSearchTeamsBody `json:",inline"` +} + +func NewGetSearchTeams() *GetSearchTeams { + return &GetSearchTeams{} +} + +func (t *GetSearchTeamsBody) DeepCopyInto(dst *GetSearchTeamsBody) { + _ = resource.CopyObjectInto(dst, t) +} + +func (o *GetSearchTeams) DeepCopyObject() runtime.Object { + dst := NewGetSearchTeams() + o.DeepCopyInto(dst) + return dst +} + +func (o *GetSearchTeams) DeepCopyInto(dst *GetSearchTeams) { + dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion + dst.TypeMeta.Kind = o.TypeMeta.Kind + o.GetSearchTeamsBody.DeepCopyInto(&dst.GetSearchTeamsBody) +} + +var _ runtime.Object = NewGetSearchTeams() diff --git a/apps/iam/pkg/apis/iam/v0alpha1/register.go b/apps/iam/pkg/apis/iam/v0alpha1/register.go index be70a0e1714..05dbc30e684 100644 --- a/apps/iam/pkg/apis/iam/v0alpha1/register.go +++ b/apps/iam/pkg/apis/iam/v0alpha1/register.go @@ -317,6 +317,7 @@ func AddAuthNKnownTypes(scheme *runtime.Scheme) error { &ServiceAccountList{}, &Team{}, &TeamList{}, + &GetSearchTeams{}, &TeamBinding{}, &TeamBindingList{}, &ExternalGroupMapping{}, diff --git a/apps/iam/pkg/apis/iam/v0alpha1/team_search.go b/apps/iam/pkg/apis/iam/v0alpha1/team_search.go new file mode 100644 index 00000000000..545552a4795 --- /dev/null +++ b/apps/iam/pkg/apis/iam/v0alpha1/team_search.go @@ -0,0 +1,35 @@ +package v0alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type TeamSearchResults struct { + metav1.TypeMeta `json:",inline"` + + // Where the query started from + Offset int64 `json:"offset,omitempty"` + + // The number of matching results + TotalHits int64 `json:"totalHits"` + + // The team body + Hits []TeamHit `json:"hits"` + + // Cost of running the query + QueryCost float64 `json:"queryCost,omitempty"` + + // Max score + MaxScore float64 `json:"maxScore,omitempty"` +} + +// +k8s:deepcopy-gen=true +type TeamHit struct { + Name string `json:"name"` + Title string `json:"title"` + Email string `json:"email,omitempty"` + Provisioned bool `json:"provisioned,omitempty"` + ExternalUID string `json:"externalUID,omitempty"` +} diff --git a/apps/iam/pkg/apis/iam/v0alpha1/zz_openapi_gen.go b/apps/iam/pkg/apis/iam/v0alpha1/zz_openapi_gen.go index e3b024799d7..a41d51e8d70 100644 --- a/apps/iam/pkg/apis/iam/v0alpha1/zz_openapi_gen.go +++ b/apps/iam/pkg/apis/iam/v0alpha1/zz_openapi_gen.go @@ -24,6 +24,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ExternalGroupMappingTeamRef": schema_pkg_apis_iam_v0alpha1_ExternalGroupMappingTeamRef(ref), "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GetGroups": schema_pkg_apis_iam_v0alpha1_GetGroups(ref), "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GetGroupsBody": schema_pkg_apis_iam_v0alpha1_GetGroupsBody(ref), + "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GetSearchTeams": schema_pkg_apis_iam_v0alpha1_GetSearchTeams(ref), + "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GetSearchTeamsBody": schema_pkg_apis_iam_v0alpha1_GetSearchTeamsBody(ref), "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRole": schema_pkg_apis_iam_v0alpha1_GlobalRole(ref), "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBinding": schema_pkg_apis_iam_v0alpha1_GlobalRoleBinding(ref), "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingList": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingList(ref), @@ -80,6 +82,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserStatus": schema_pkg_apis_iam_v0alpha1_UserStatus(ref), "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserstatusOperatorState": schema_pkg_apis_iam_v0alpha1_UserstatusOperatorState(ref), "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping": schema_pkg_apis_iam_v0alpha1_VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping(ref), + "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit": schema_pkg_apis_iam_v0alpha1_VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit(ref), } } @@ -564,6 +567,132 @@ func schema_pkg_apis_iam_v0alpha1_GetGroupsBody(ref common.ReferenceCallback) co } } +func schema_pkg_apis_iam_v0alpha1_GetSearchTeams(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "offset": { + SchemaProps: spec.SchemaProps{ + Default: 0, + Type: []string{"integer"}, + Format: "int64", + }, + }, + "totalHits": { + SchemaProps: spec.SchemaProps{ + Default: 0, + Type: []string{"integer"}, + Format: "int64", + }, + }, + "hits": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit"), + }, + }, + }, + }, + }, + "queryCost": { + SchemaProps: spec.SchemaProps{ + Default: 0, + Type: []string{"number"}, + Format: "double", + }, + }, + "maxScore": { + SchemaProps: spec.SchemaProps{ + Default: 0, + Type: []string{"number"}, + Format: "double", + }, + }, + }, + Required: []string{"offset", "totalHits", "hits", "queryCost", "maxScore"}, + }, + }, + Dependencies: []string{ + "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit"}, + } +} + +func schema_pkg_apis_iam_v0alpha1_GetSearchTeamsBody(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "offset": { + SchemaProps: spec.SchemaProps{ + Default: 0, + Type: []string{"integer"}, + Format: "int64", + }, + }, + "totalHits": { + SchemaProps: spec.SchemaProps{ + Default: 0, + Type: []string{"integer"}, + Format: "int64", + }, + }, + "hits": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit"), + }, + }, + }, + }, + }, + "queryCost": { + SchemaProps: spec.SchemaProps{ + Default: 0, + Type: []string{"number"}, + Format: "double", + }, + }, + "maxScore": { + SchemaProps: spec.SchemaProps{ + Default: 0, + Type: []string{"number"}, + Format: "double", + }, + }, + }, + Required: []string{"offset", "totalHits", "hits", "queryCost", "maxScore"}, + }, + }, + Dependencies: []string{ + "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit"}, + } +} + func schema_pkg_apis_iam_v0alpha1_GlobalRole(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -2956,3 +3085,51 @@ func schema_pkg_apis_iam_v0alpha1_VersionsV0alpha1Kinds7RoutesGroupsGETResponseE }, } } + +func schema_pkg_apis_iam_v0alpha1_VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "title": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "email": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "provisioned": { + SchemaProps: spec.SchemaProps{ + Default: false, + Type: []string{"boolean"}, + Format: "", + }, + }, + "externalUID": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"name", "title", "email", "provisioned", "externalUID"}, + }, + }, + } +} diff --git a/apps/iam/pkg/apis/iam_manifest.go b/apps/iam/pkg/apis/iam_manifest.go index 9fe171525b4..5c27c228ed2 100644 --- a/apps/iam/pkg/apis/iam_manifest.go +++ b/apps/iam/pkg/apis/iam_manifest.go @@ -157,9 +157,139 @@ var appManifestData = app.ManifestData{ }, }, Routes: app.ManifestVersionRoutes{ - Namespaced: map[string]spec3.PathProps{}, - Cluster: map[string]spec3.PathProps{}, - Schemas: map[string]spec.Schema{}, + Namespaced: map[string]spec3.PathProps{ + "/searchTeams": { + Get: &spec3.Operation{ + OperationProps: spec3.OperationProps{ + + OperationId: "getSearchTeams", + + Parameters: []*spec3.Parameter{ + + { + ParameterProps: spec3.ParameterProps{ + Name: "query", + In: "query", + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + }, + }, + }, + }, + }, + + Responses: &spec3.Responses{ + ResponsesProps: spec3.ResponsesProps{ + Default: &spec3.Response{ + ResponseProps: spec3.ResponseProps{ + Description: "Default OK response", + Content: map[string]*spec3.MediaType{ + "application/json": { + MediaTypeProps: spec3.MediaTypeProps{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + }, + }, + "hits": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + }, + }, + "maxScore": { + SchemaProps: spec.SchemaProps{ + Type: []string{"number"}, + }, + }, + "offset": { + SchemaProps: spec.SchemaProps{ + Type: []string{"integer"}, + }, + }, + "queryCost": { + SchemaProps: spec.SchemaProps{ + Type: []string{"number"}, + }, + }, + "totalHits": { + SchemaProps: spec.SchemaProps{ + Type: []string{"integer"}, + }, + }, + }, + Required: []string{ + "offset", + "totalHits", + "hits", + "queryCost", + "maxScore", + "apiVersion", + "kind", + }, + }}, + }}, + }, + }, + }, + }}, + }, + }, + }, + }, + Cluster: map[string]spec3.PathProps{}, + Schemas: map[string]spec.Schema{ + "getSearchTeamsTeamHit": { + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "email": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + }, + }, + "externalUID": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + }, + }, + "provisioned": { + SchemaProps: spec.SchemaProps{ + Type: []string{"boolean"}, + }, + }, + "title": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + }, + }, + }, + Required: []string{ + "name", + "title", + "email", + "provisioned", + "externalUID", + }, + }, + }, + }, }, }, }, @@ -196,6 +326,8 @@ func ManifestGoTypeAssociator(kind, version string) (goType resource.Kind, exist var customRouteToGoResponseType = map[string]any{ "v0alpha1|Team|groups|GET": v0alpha1.GetGroups{}, + + "v0alpha1||/searchTeams|GET": v0alpha1.GetSearchTeams{}, } // ManifestCustomRouteResponsesAssociator returns the associated response go type for a given kind, version, custom route path, and method, if one exists. diff --git a/apps/investigations/Makefile b/apps/investigations/Makefile index aaac06377ca..bc8d6d30cb5 100644 --- a/apps/investigations/Makefile +++ b/apps/investigations/Makefile @@ -1,5 +1,10 @@ include ../sdk.mk -.PHONY: generate +.PHONY: generate # Run Grafana App SDK code generation generate: install-app-sdk update-app-sdk - @$(APP_SDK_BIN) generate -g ./pkg/apis --grouping=group --postprocess --defencoding=none --useoldmanifestkinds + @$(APP_SDK_BIN) generate \ + --source=./kinds/ \ + --gogenpath=./pkg/apis \ + --grouping=group \ + --genoperatorstate=false \ + --defencoding=none \ No newline at end of file diff --git a/apps/investigations/go.mod b/apps/investigations/go.mod index 0faf2c40efb..3844fec2689 100644 --- a/apps/investigations/go.mod +++ b/apps/investigations/go.mod @@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/investigations go 1.25.5 require ( - github.com/grafana/grafana-app-sdk v0.48.4 + github.com/grafana/grafana-app-sdk v0.48.5 k8s.io/apimachinery v0.34.2 k8s.io/klog/v2 v2.130.1 k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 diff --git a/apps/investigations/go.sum b/apps/investigations/go.sum index c447da4e325..3df8e8b5ebe 100644 --- a/apps/investigations/go.sum +++ b/apps/investigations/go.sum @@ -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.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 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/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= diff --git a/apps/investigations/kinds/cue.mod/module.cue b/apps/investigations/kinds/cue.mod/module.cue index 1c9c98f497f..c592b1ce788 100644 --- a/apps/investigations/kinds/cue.mod/module.cue +++ b/apps/investigations/kinds/cue.mod/module.cue @@ -1,4 +1,4 @@ module: "github.com/grafana/grafana/apps/investigations" language: { - version: "v0.9.0" + version: "v0.11.0" } \ No newline at end of file diff --git a/apps/investigations/kinds/investigation.cue b/apps/investigations/kinds/investigation.cue index f1e9a69027f..1ade89416b9 100644 --- a/apps/investigations/kinds/investigation.cue +++ b/apps/investigations/kinds/investigation.cue @@ -1,39 +1,18 @@ package investigations -// This is our Investigation definition, which contains metadata about the kind, and the kind's schema -investigation: { +investigationV0alpha1: { kind: "Investigation" - group: "investigations.grafana.app" - apiResource: { - groupOverride: "investigations.grafana.app" - } pluralName: "Investigations" - current: "v0alpha1" - versions: { - "v0alpha1": { - codegen: { - frontend: true - backend: true - options: { - generateObjectMeta: true - generateClient: true - k8sLike: true - package: "github.com/grafana/grafana/apps/investigations" - } - } - schema: { - // spec is the schema of our resource - spec: { - title: string - createdByProfile: #Person - hasCustomName: bool - isFavorite: bool - overviewNote: string - overviewNoteUpdatedAt: string - collectables: [...#Collectable] // +listType=atomic - viewMode: #ViewMode - } - } + schema: { + spec: { + title: string + createdByProfile: #Person + hasCustomName: bool + isFavorite: bool + overviewNote: string + overviewNoteUpdatedAt: string + collectables: [...#Collectable] // +listType=atomic + viewMode: #ViewMode } } } diff --git a/apps/investigations/kinds/investigationindex.cue b/apps/investigations/kinds/investigationindex.cue index 447e156be4f..65c5e3ae79f 100644 --- a/apps/investigations/kinds/investigationindex.cue +++ b/apps/investigations/kinds/investigationindex.cue @@ -1,37 +1,18 @@ package investigations -investigationIndex: { +investigationIndexV0alpha1:{ kind: "InvestigationIndex" - group: "investigations.grafana.app" - apiResource: { - groupOverride: "investigations.grafana.app" - } pluralName: "InvestigationIndexes" - current: "v0alpha1" - versions: { - "v0alpha1": { - codegen: { - frontend: true - backend: true - options: { - generateObjectMeta: true - generateClient: true - k8sLike: true - package: "github.com/grafana/grafana/apps/investigations" - } - } - schema: { - spec: { - // Title of the index, e.g. 'Favorites' or 'My Investigations' - title: string + schema: { + spec: { + // Title of the index, e.g. 'Favorites' or 'My Investigations' + title: string - // The Person who owns this investigation index - owner: #Person + // The Person who owns this investigation index + owner: #Person - // Array of investigation summaries - investigationSummaries: [...#InvestigationSummary] // +listType=atomic - } - } + // Array of investigation summaries + investigationSummaries: [...#InvestigationSummary] // +listType=atomic } } } diff --git a/apps/investigations/kinds/manifest.cue b/apps/investigations/kinds/manifest.cue index d9e93b00061..947d84be482 100644 --- a/apps/investigations/kinds/manifest.cue +++ b/apps/investigations/kinds/manifest.cue @@ -3,8 +3,16 @@ package investigations manifest: { appName: "investigations" groupOverride: "investigations.grafana.app" - kinds: [ - investigation, - investigationIndex, - ] -} + versions: { + "v0alpha1": { + codegen: { + ts: {enabled: false} + go: {enabled: true} + } + kinds: [ + investigationV0alpha1, + investigationIndexV0alpha1, + ] + } + } +} \ No newline at end of file diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_client_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_client_gen.go index dc73a0301e9..dea4d71802d 100644 --- a/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_client_gen.go +++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_client_gen.go @@ -4,7 +4,6 @@ import ( "context" "github.com/grafana/grafana-app-sdk/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type InvestigationClient struct { @@ -76,24 +75,6 @@ func (c *InvestigationClient) Patch(ctx context.Context, identifier resource.Ide return c.client.Patch(ctx, identifier, req, opts) } -func (c *InvestigationClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus InvestigationStatus, opts resource.UpdateOptions) (*Investigation, error) { - return c.client.Update(ctx, &Investigation{ - TypeMeta: metav1.TypeMeta{ - Kind: InvestigationKind().Kind(), - APIVersion: GroupVersion.Identifier(), - }, - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: opts.ResourceVersion, - Namespace: identifier.Namespace, - Name: identifier.Name, - }, - Status: newStatus, - }, resource.UpdateOptions{ - Subresource: "status", - ResourceVersion: opts.ResourceVersion, - }) -} - func (c *InvestigationClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error { return c.client.Delete(ctx, identifier, opts) } diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_object_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_object_gen.go index eb819564176..f64d7b6e047 100644 --- a/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_object_gen.go +++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_object_gen.go @@ -21,8 +21,6 @@ type Investigation struct { // Spec is the spec of the Investigation Spec InvestigationSpec `json:"spec" yaml:"spec"` - - Status InvestigationStatus `json:"status" yaml:"status"` } func (o *Investigation) GetSpec() any { @@ -39,15 +37,11 @@ func (o *Investigation) SetSpec(spec any) error { } func (o *Investigation) GetSubresources() map[string]any { - return map[string]any{ - "status": o.Status, - } + return map[string]any{} } func (o *Investigation) GetSubresource(name string) (any, bool) { switch name { - case "status": - return o.Status, true default: return nil, false } @@ -55,13 +49,6 @@ func (o *Investigation) GetSubresource(name string) (any, bool) { func (o *Investigation) SetSubresource(name string, value any) error { switch name { - case "status": - cast, ok := value.(InvestigationStatus) - if !ok { - return fmt.Errorf("cannot set status type %#v, not of type InvestigationStatus", value) - } - o.Status = cast - return nil default: return fmt.Errorf("subresource '%s' does not exist", name) } @@ -233,7 +220,6 @@ func (o *Investigation) DeepCopyInto(dst *Investigation) { dst.TypeMeta.Kind = o.TypeMeta.Kind o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta) o.Spec.DeepCopyInto(&dst.Spec) - o.Status.DeepCopyInto(&dst.Status) } // Interface compliance compile-time check @@ -305,15 +291,3 @@ func (s *InvestigationSpec) DeepCopy() *InvestigationSpec { func (s *InvestigationSpec) DeepCopyInto(dst *InvestigationSpec) { resource.CopyObjectInto(dst, s) } - -// DeepCopy creates a full deep copy of InvestigationStatus -func (s *InvestigationStatus) DeepCopy() *InvestigationStatus { - cpy := &InvestigationStatus{} - s.DeepCopyInto(cpy) - return cpy -} - -// DeepCopyInto deep copies InvestigationStatus into another InvestigationStatus object -func (s *InvestigationStatus) DeepCopyInto(dst *InvestigationStatus) { - resource.CopyObjectInto(dst, s) -} diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_spec_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_spec_gen.go index d56124603a2..88d74be54eb 100644 --- a/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_spec_gen.go +++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_spec_gen.go @@ -84,7 +84,6 @@ func NewInvestigationViewMode() *InvestigationViewMode { return &InvestigationViewMode{} } -// spec is the schema of our resource // +k8s:openapi-gen=true type InvestigationSpec struct { Title string `json:"title"` diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_status_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_status_gen.go deleted file mode 100644 index c70224b96e4..00000000000 --- a/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_status_gen.go +++ /dev/null @@ -1,44 +0,0 @@ -// Code generated - EDITING IS FUTILE. DO NOT EDIT. - -package v0alpha1 - -// +k8s:openapi-gen=true -type InvestigationstatusOperatorState struct { - // lastEvaluation is the ResourceVersion last evaluated - LastEvaluation string `json:"lastEvaluation"` - // state describes the state of the lastEvaluation. - // It is limited to three possible states for machine evaluation. - State InvestigationStatusOperatorStateState `json:"state"` - // descriptiveState is an optional more descriptive state field which has no requirements on format - DescriptiveState *string `json:"descriptiveState,omitempty"` - // details contains any extra information that is operator-specific - Details map[string]interface{} `json:"details,omitempty"` -} - -// NewInvestigationstatusOperatorState creates a new InvestigationstatusOperatorState object. -func NewInvestigationstatusOperatorState() *InvestigationstatusOperatorState { - return &InvestigationstatusOperatorState{} -} - -// +k8s:openapi-gen=true -type InvestigationStatus struct { - // operatorStates is a map of operator ID to operator state evaluations. - // Any operator which consumes this kind SHOULD add its state evaluation information to this field. - OperatorStates map[string]InvestigationstatusOperatorState `json:"operatorStates,omitempty"` - // additionalFields is reserved for future use - AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"` -} - -// NewInvestigationStatus creates a new InvestigationStatus object. -func NewInvestigationStatus() *InvestigationStatus { - return &InvestigationStatus{} -} - -// +k8s:openapi-gen=true -type InvestigationStatusOperatorStateState string - -const ( - InvestigationStatusOperatorStateStateSuccess InvestigationStatusOperatorStateState = "success" - InvestigationStatusOperatorStateStateInProgress InvestigationStatusOperatorStateState = "in_progress" - InvestigationStatusOperatorStateStateFailed InvestigationStatusOperatorStateState = "failed" -) diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_client_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_client_gen.go index 573d743b3cf..dafe3e1012e 100644 --- a/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_client_gen.go +++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_client_gen.go @@ -4,7 +4,6 @@ import ( "context" "github.com/grafana/grafana-app-sdk/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type InvestigationIndexClient struct { @@ -76,24 +75,6 @@ func (c *InvestigationIndexClient) Patch(ctx context.Context, identifier resourc return c.client.Patch(ctx, identifier, req, opts) } -func (c *InvestigationIndexClient) UpdateStatus(ctx context.Context, identifier resource.Identifier, newStatus InvestigationIndexStatus, opts resource.UpdateOptions) (*InvestigationIndex, error) { - return c.client.Update(ctx, &InvestigationIndex{ - TypeMeta: metav1.TypeMeta{ - Kind: InvestigationIndexKind().Kind(), - APIVersion: GroupVersion.Identifier(), - }, - ObjectMeta: metav1.ObjectMeta{ - ResourceVersion: opts.ResourceVersion, - Namespace: identifier.Namespace, - Name: identifier.Name, - }, - Status: newStatus, - }, resource.UpdateOptions{ - Subresource: "status", - ResourceVersion: opts.ResourceVersion, - }) -} - func (c *InvestigationIndexClient) Delete(ctx context.Context, identifier resource.Identifier, opts resource.DeleteOptions) error { return c.client.Delete(ctx, identifier, opts) } diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_object_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_object_gen.go index 67493201f05..b8272b4fae7 100644 --- a/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_object_gen.go +++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_object_gen.go @@ -21,8 +21,6 @@ type InvestigationIndex struct { // Spec is the spec of the InvestigationIndex Spec InvestigationIndexSpec `json:"spec" yaml:"spec"` - - Status InvestigationIndexStatus `json:"status" yaml:"status"` } func (o *InvestigationIndex) GetSpec() any { @@ -39,15 +37,11 @@ func (o *InvestigationIndex) SetSpec(spec any) error { } func (o *InvestigationIndex) GetSubresources() map[string]any { - return map[string]any{ - "status": o.Status, - } + return map[string]any{} } func (o *InvestigationIndex) GetSubresource(name string) (any, bool) { switch name { - case "status": - return o.Status, true default: return nil, false } @@ -55,13 +49,6 @@ func (o *InvestigationIndex) GetSubresource(name string) (any, bool) { func (o *InvestigationIndex) SetSubresource(name string, value any) error { switch name { - case "status": - cast, ok := value.(InvestigationIndexStatus) - if !ok { - return fmt.Errorf("cannot set status type %#v, not of type InvestigationIndexStatus", value) - } - o.Status = cast - return nil default: return fmt.Errorf("subresource '%s' does not exist", name) } @@ -233,7 +220,6 @@ func (o *InvestigationIndex) DeepCopyInto(dst *InvestigationIndex) { dst.TypeMeta.Kind = o.TypeMeta.Kind o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta) o.Spec.DeepCopyInto(&dst.Spec) - o.Status.DeepCopyInto(&dst.Status) } // Interface compliance compile-time check @@ -305,15 +291,3 @@ func (s *InvestigationIndexSpec) DeepCopy() *InvestigationIndexSpec { func (s *InvestigationIndexSpec) DeepCopyInto(dst *InvestigationIndexSpec) { resource.CopyObjectInto(dst, s) } - -// DeepCopy creates a full deep copy of InvestigationIndexStatus -func (s *InvestigationIndexStatus) DeepCopy() *InvestigationIndexStatus { - cpy := &InvestigationIndexStatus{} - s.DeepCopyInto(cpy) - return cpy -} - -// DeepCopyInto deep copies InvestigationIndexStatus into another InvestigationIndexStatus object -func (s *InvestigationIndexStatus) DeepCopyInto(dst *InvestigationIndexStatus) { - resource.CopyObjectInto(dst, s) -} diff --git a/apps/investigations/pkg/apis/investigations_manifest.go b/apps/investigations/pkg/apis/investigations_manifest.go index 2d3e9c7bdd3..249e9b49758 100644 --- a/apps/investigations/pkg/apis/investigations_manifest.go +++ b/apps/investigations/pkg/apis/investigations_manifest.go @@ -20,10 +20,10 @@ import ( ) var ( - rawSchemaInvestigationv0alpha1 = []byte(`{"Collectable":{"additionalProperties":false,"description":"Collectable represents an item collected during investigation","properties":{"createdAt":{"type":"string"},"datasource":{"$ref":"#/components/schemas/DatasourceRef"},"fieldConfig":{"type":"string"},"id":{"type":"string"},"logoPath":{"type":"string"},"note":{"type":"string"},"noteUpdatedAt":{"type":"string"},"origin":{"type":"string"},"queries":{"description":"+listType=atomic","items":{"type":"string"},"type":"array"},"timeRange":{"$ref":"#/components/schemas/TimeRange"},"title":{"type":"string"},"type":{"type":"string"},"url":{"type":"string"}},"required":["id","createdAt","title","origin","type","queries","timeRange","datasource","url","note","noteUpdatedAt","fieldConfig"],"type":"object"},"DatasourceRef":{"additionalProperties":false,"description":"DatasourceRef is a reference to a datasource","properties":{"uid":{"type":"string"}},"required":["uid"],"type":"object"},"Investigation":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"Person":{"additionalProperties":false,"description":"Person represents a user profile with basic information","properties":{"gravatarUrl":{"description":"URL to user's Gravatar image","type":"string"},"name":{"description":"Display name of the user","type":"string"},"uid":{"description":"Unique identifier for the user","type":"string"}},"required":["uid","name","gravatarUrl"],"type":"object"},"TimeRange":{"additionalProperties":false,"description":"TimeRange represents a time range with both absolute and relative values","properties":{"from":{"type":"string"},"raw":{"additionalProperties":false,"properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"],"type":"object"},"to":{"type":"string"}},"required":["from","to","raw"],"type":"object"},"ViewMode":{"additionalProperties":false,"properties":{"mode":{"enum":["compact","full"],"type":"string"},"showComments":{"type":"boolean"},"showTooltips":{"type":"boolean"}},"required":["mode","showComments","showTooltips"],"type":"object"},"spec":{"additionalProperties":false,"description":"spec is the schema of our resource","properties":{"collectables":{"description":"+listType=atomic","items":{"$ref":"#/components/schemas/Collectable"},"type":"array"},"createdByProfile":{"$ref":"#/components/schemas/Person"},"hasCustomName":{"type":"boolean"},"isFavorite":{"type":"boolean"},"overviewNote":{"type":"string"},"overviewNoteUpdatedAt":{"type":"string"},"title":{"type":"string"},"viewMode":{"$ref":"#/components/schemas/ViewMode"}},"required":["title","createdByProfile","hasCustomName","isFavorite","overviewNote","overviewNoteUpdatedAt","collectables","viewMode"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`) + rawSchemaInvestigationv0alpha1 = []byte(`{"Collectable":{"additionalProperties":false,"description":"Collectable represents an item collected during investigation","properties":{"createdAt":{"type":"string"},"datasource":{"$ref":"#/components/schemas/DatasourceRef"},"fieldConfig":{"type":"string"},"id":{"type":"string"},"logoPath":{"type":"string"},"note":{"type":"string"},"noteUpdatedAt":{"type":"string"},"origin":{"type":"string"},"queries":{"description":"+listType=atomic","items":{"type":"string"},"type":"array"},"timeRange":{"$ref":"#/components/schemas/TimeRange"},"title":{"type":"string"},"type":{"type":"string"},"url":{"type":"string"}},"required":["id","createdAt","title","origin","type","queries","timeRange","datasource","url","note","noteUpdatedAt","fieldConfig"],"type":"object"},"DatasourceRef":{"additionalProperties":false,"description":"DatasourceRef is a reference to a datasource","properties":{"uid":{"type":"string"}},"required":["uid"],"type":"object"},"Investigation":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"Person":{"additionalProperties":false,"description":"Person represents a user profile with basic information","properties":{"gravatarUrl":{"description":"URL to user's Gravatar image","type":"string"},"name":{"description":"Display name of the user","type":"string"},"uid":{"description":"Unique identifier for the user","type":"string"}},"required":["uid","name","gravatarUrl"],"type":"object"},"TimeRange":{"additionalProperties":false,"description":"TimeRange represents a time range with both absolute and relative values","properties":{"from":{"type":"string"},"raw":{"additionalProperties":false,"properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"],"type":"object"},"to":{"type":"string"}},"required":["from","to","raw"],"type":"object"},"ViewMode":{"additionalProperties":false,"properties":{"mode":{"enum":["compact","full"],"type":"string"},"showComments":{"type":"boolean"},"showTooltips":{"type":"boolean"}},"required":["mode","showComments","showTooltips"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"collectables":{"description":"+listType=atomic","items":{"$ref":"#/components/schemas/Collectable"},"type":"array"},"createdByProfile":{"$ref":"#/components/schemas/Person"},"hasCustomName":{"type":"boolean"},"isFavorite":{"type":"boolean"},"overviewNote":{"type":"string"},"overviewNoteUpdatedAt":{"type":"string"},"title":{"type":"string"},"viewMode":{"$ref":"#/components/schemas/ViewMode"}},"required":["title","createdByProfile","hasCustomName","isFavorite","overviewNote","overviewNoteUpdatedAt","collectables","viewMode"],"type":"object"}}`) versionSchemaInvestigationv0alpha1 app.VersionSchema _ = json.Unmarshal(rawSchemaInvestigationv0alpha1, &versionSchemaInvestigationv0alpha1) - rawSchemaInvestigationIndexv0alpha1 = []byte(`{"CollectableSummary":{"additionalProperties":false,"properties":{"id":{"type":"string"},"logoPath":{"type":"string"},"origin":{"type":"string"},"title":{"type":"string"}},"required":["id","title","logoPath","origin"],"type":"object"},"InvestigationIndex":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"InvestigationSummary":{"additionalProperties":false,"description":"Type definition for investigation summaries","properties":{"collectableSummaries":{"description":"+listType=atomic","items":{"$ref":"#/components/schemas/CollectableSummary"},"type":"array"},"createdByProfile":{"$ref":"#/components/schemas/Person"},"hasCustomName":{"type":"boolean"},"isFavorite":{"type":"boolean"},"overviewNote":{"type":"string"},"overviewNoteUpdatedAt":{"type":"string"},"title":{"type":"string"},"viewMode":{"$ref":"#/components/schemas/ViewMode"}},"required":["title","createdByProfile","hasCustomName","isFavorite","overviewNote","overviewNoteUpdatedAt","viewMode","collectableSummaries"],"type":"object"},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"Person":{"additionalProperties":false,"description":"Person represents a user profile with basic information","properties":{"gravatarUrl":{"description":"URL to user's Gravatar image","type":"string"},"name":{"description":"Display name of the user","type":"string"},"uid":{"description":"Unique identifier for the user","type":"string"}},"required":["uid","name","gravatarUrl"],"type":"object"},"ViewMode":{"additionalProperties":false,"properties":{"mode":{"enum":["compact","full"],"type":"string"},"showComments":{"type":"boolean"},"showTooltips":{"type":"boolean"}},"required":["mode","showComments","showTooltips"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"investigationSummaries":{"description":"Array of investigation summaries\n+listType=atomic","items":{"$ref":"#/components/schemas/InvestigationSummary"},"type":"array"},"owner":{"$ref":"#/components/schemas/Person","description":"The Person who owns this investigation index"},"title":{"description":"Title of the index, e.g. 'Favorites' or 'My Investigations'","type":"string"}},"required":["title","owner","investigationSummaries"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`) + rawSchemaInvestigationIndexv0alpha1 = []byte(`{"CollectableSummary":{"additionalProperties":false,"properties":{"id":{"type":"string"},"logoPath":{"type":"string"},"origin":{"type":"string"},"title":{"type":"string"}},"required":["id","title","logoPath","origin"],"type":"object"},"InvestigationIndex":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"InvestigationSummary":{"additionalProperties":false,"description":"Type definition for investigation summaries","properties":{"collectableSummaries":{"description":"+listType=atomic","items":{"$ref":"#/components/schemas/CollectableSummary"},"type":"array"},"createdByProfile":{"$ref":"#/components/schemas/Person"},"hasCustomName":{"type":"boolean"},"isFavorite":{"type":"boolean"},"overviewNote":{"type":"string"},"overviewNoteUpdatedAt":{"type":"string"},"title":{"type":"string"},"viewMode":{"$ref":"#/components/schemas/ViewMode"}},"required":["title","createdByProfile","hasCustomName","isFavorite","overviewNote","overviewNoteUpdatedAt","viewMode","collectableSummaries"],"type":"object"},"Person":{"additionalProperties":false,"description":"Person represents a user profile with basic information","properties":{"gravatarUrl":{"description":"URL to user's Gravatar image","type":"string"},"name":{"description":"Display name of the user","type":"string"},"uid":{"description":"Unique identifier for the user","type":"string"}},"required":["uid","name","gravatarUrl"],"type":"object"},"ViewMode":{"additionalProperties":false,"properties":{"mode":{"enum":["compact","full"],"type":"string"},"showComments":{"type":"boolean"},"showTooltips":{"type":"boolean"}},"required":["mode","showComments","showTooltips"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"investigationSummaries":{"description":"Array of investigation summaries\n+listType=atomic","items":{"$ref":"#/components/schemas/InvestigationSummary"},"type":"array"},"owner":{"$ref":"#/components/schemas/Person","description":"The Person who owns this investigation index"},"title":{"description":"Title of the index, e.g. 'Favorites' or 'My Investigations'","type":"string"}},"required":["title","owner","investigationSummaries"],"type":"object"}}`) versionSchemaInvestigationIndexv0alpha1 app.VersionSchema _ = json.Unmarshal(rawSchemaInvestigationIndexv0alpha1, &versionSchemaInvestigationIndexv0alpha1) ) diff --git a/apps/logsdrilldown/go.mod b/apps/logsdrilldown/go.mod index b70fb8a42f5..2a35278d19a 100644 --- a/apps/logsdrilldown/go.mod +++ b/apps/logsdrilldown/go.mod @@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/logsdrilldown go 1.25.5 require ( - github.com/grafana/grafana-app-sdk v0.48.4 + github.com/grafana/grafana-app-sdk v0.48.5 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 diff --git a/apps/logsdrilldown/go.sum b/apps/logsdrilldown/go.sum index c447da4e325..3df8e8b5ebe 100644 --- a/apps/logsdrilldown/go.sum +++ b/apps/logsdrilldown/go.sum @@ -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.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 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/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= diff --git a/apps/logsdrilldown/kinds/cue.mod/module.cue b/apps/logsdrilldown/kinds/cue.mod/module.cue index 641554da67c..354ce7e3290 100644 --- a/apps/logsdrilldown/kinds/cue.mod/module.cue +++ b/apps/logsdrilldown/kinds/cue.mod/module.cue @@ -1,2 +1,4 @@ module: "github.com/grafana/grafana/apps/logsdrilldown/kinds" -language: version: "v0.8.2" +language: { + version: "v0.11.0" +} diff --git a/apps/playlist/go.mod b/apps/playlist/go.mod index 4bdbe8c003c..ae38e3d0cd3 100644 --- a/apps/playlist/go.mod +++ b/apps/playlist/go.mod @@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/playlist go 1.25.5 require ( - github.com/grafana/grafana-app-sdk v0.48.4 + github.com/grafana/grafana-app-sdk v0.48.5 k8s.io/apimachinery v0.34.2 k8s.io/client-go v0.34.2 k8s.io/klog/v2 v2.130.1 diff --git a/apps/playlist/go.sum b/apps/playlist/go.sum index c447da4e325..3df8e8b5ebe 100644 --- a/apps/playlist/go.sum +++ b/apps/playlist/go.sum @@ -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.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 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/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= diff --git a/apps/playlist/kinds/cue.mod/module.cue b/apps/playlist/kinds/cue.mod/module.cue index 162ee6176aa..ee4b35ffdf8 100644 --- a/apps/playlist/kinds/cue.mod/module.cue +++ b/apps/playlist/kinds/cue.mod/module.cue @@ -1,4 +1,4 @@ module: "github.com/grafana/grafana/apps/playlist/kinds" language: { - version: "v0.9.0" + version: "v0.11.0" } diff --git a/apps/plugins/go.mod b/apps/plugins/go.mod index c55674cc950..669c7c46844 100644 --- a/apps/plugins/go.mod +++ b/apps/plugins/go.mod @@ -10,8 +10,9 @@ replace github.com/grafana/grafana/pkg/apiserver => ../../pkg/apiserver require ( github.com/emicklei/go-restful/v3 v3.13.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.4 + github.com/grafana/grafana-app-sdk v0.48.5 github.com/grafana/grafana-app-sdk/logging v0.48.3 github.com/grafana/grafana/pkg/apimachinery v0.0.0 github.com/stretchr/testify v1.11.1 @@ -59,7 +60,7 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.22.1 // indirect github.com/go-openapi/jsonreference v0.21.2 // indirect - github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-openapi/swag v0.23.1 // indirect github.com/go-openapi/swag/jsonname v0.25.1 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/go-test/deep v1.1.1 // indirect @@ -75,9 +76,8 @@ require ( github.com/google/gnostic-models v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grafana/alerting v0.0.0-20251119204204-77fa75125181 // indirect + github.com/grafana/alerting v0.0.0-20251204145817-de8c2bbf9eba // indirect github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // indirect - github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 // indirect github.com/grafana/dataplane/sdata v0.0.9 // indirect github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect github.com/grafana/grafana-aws-sdk v1.3.0 // indirect @@ -142,7 +142,7 @@ require ( github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/alertmanager v0.28.0 // indirect + github.com/prometheus/alertmanager v0.28.2 // indirect github.com/prometheus/client_golang v1.23.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.67.3 // indirect @@ -194,8 +194,8 @@ require ( golang.org/x/tools v0.39.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba // indirect google.golang.org/grpc v1.77.0 // indirect google.golang.org/protobuf v1.36.10 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect @@ -215,3 +215,6 @@ require ( sigs.k8s.io/structured-merge-diff/v6 v6.3.1 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) + +// Use our fork of the upstream Alertmanager. +replace github.com/prometheus/alertmanager => github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604 diff --git a/apps/plugins/go.sum b/apps/plugins/go.sum index d582270e43b..1d7387b28b3 100644 --- a/apps/plugins/go.sum +++ b/apps/plugins/go.sum @@ -110,8 +110,8 @@ github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo github.com/go-openapi/jsonpointer v0.22.1/go.mod h1:pQT9OsLkfz1yWoMgYFy4x3U5GY5nUlsOn1qSBH5MkCM= github.com/go-openapi/jsonreference v0.21.2 h1:Wxjda4M/BBQllegefXrY/9aq1fxBA8sI5M/lFU6tSWU= github.com/go-openapi/jsonreference v0.21.2/go.mod h1:pp3PEjIsJ9CZDGCNOyXIQxsNuroxm8FAJ/+quA0yKzQ= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= +github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= github.com/go-openapi/swag/jsonname v0.25.1 h1:Sgx+qbwa4ej6AomWC6pEfXrA6uP2RkaNjA9BR8a1RJU= github.com/go-openapi/swag/jsonname v0.25.1/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo= github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= @@ -174,8 +174,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/alerting v0.0.0-20251119204204-77fa75125181 h1:nbxKRtrbuhvOYmI2RhOYauHRJCtpR+vTNIgg1lFUCws= -github.com/grafana/alerting v0.0.0-20251119204204-77fa75125181/go.mod h1:VtPNIFlEOJPPEc13Ax6ZTbNV3M/sAzLID72YjgzOPVA= +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/authlib v0.0.0-20250930082137-a40e2c2b094f h1:Cbm6OKkOcJ+7CSZsGsEJzktC/SIa5bxVeYKQLuYK86o= github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f/go.mod h1:axY0cdOg3q0TZHwpHnIz5x16xZ8ZBxJHShsSHHXcHQg= github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 h1:Muoy+FMGrHj3GdFbvsMzUT7eusgii9PKf9L1ZaXDDbY= @@ -184,8 +184,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.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 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/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= @@ -196,6 +196,8 @@ github.com/grafana/grafana-plugin-sdk-go v0.284.0 h1:1bK7eWsnPBLUWDcWJWe218Ik5ad github.com/grafana/grafana-plugin-sdk-go v0.284.0/go.mod h1:lHPniaSxq3SL5MxDIPy04TYB1jnTp/ivkYO+xn5Rz3E= github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= +github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604 h1:aXfUhVN/Ewfpbko2CCtL65cIiGgwStOo4lWH2b6gw2U= +github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604/go.mod h1:O/QP1BCm0HHIzbKvgMzqb5sSyH88rzkFk84F4TfJjBU= github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasnuOY813tbMN8i/a3Og= github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/grafana/sqlds/v4 v4.2.7 h1:sFQhsS7DBakNMdxa++yOfJ9BVvkZwFJ0B95o57K0/XA= @@ -368,8 +370,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/alertmanager v0.28.0 h1:sLN+6HhZet8hrbmGHLAHWsTXgZSVCvq9Ix3U3wvivqc= -github.com/prometheus/alertmanager v0.28.0/go.mod h1:/okSnb2LlodbMlRoOWQEKtqI/coOo2NKZDm2Hu9QHLQ= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -611,10 +611,10 @@ gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4= -google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba h1:B14OtaXuMaCQsl2deSvNkyPKIzq3BjfxQp8d00QyWx4= +google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:G5IanEx8/PgI9w6CFcYQf7jMtHQhZruvfM1i3qOqk5U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba h1:UKgtfRM7Yh93Sya0Fo8ZzhDP4qBckrrxEr2oF5UIVb8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= diff --git a/apps/plugins/kinds/cue.mod/module.cue b/apps/plugins/kinds/cue.mod/module.cue index 95dc1c62455..8cb2daac461 100644 --- a/apps/plugins/kinds/cue.mod/module.cue +++ b/apps/plugins/kinds/cue.mod/module.cue @@ -1,4 +1,4 @@ module: "github.com/grafana/grafana/apps/plugins/kinds" language: { - version: "v0.9.0" + version: "v0.11.0" } diff --git a/apps/plugins/pkg/app/app.go b/apps/plugins/pkg/app/app.go index ec0f59df3fd..3d17cc34221 100644 --- a/apps/plugins/pkg/app/app.go +++ b/apps/plugins/pkg/app/app.go @@ -10,11 +10,13 @@ import ( "github.com/grafana/grafana-app-sdk/operator" "github.com/grafana/grafana-app-sdk/simple" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" restclient "k8s.io/client-go/rest" "k8s.io/klog/v2" + authlib "github.com/grafana/authlib/types" pluginsappapis "github.com/grafana/grafana/apps/plugins/pkg/apis" pluginsv0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1" "github.com/grafana/grafana/apps/plugins/pkg/app/meta" @@ -68,7 +70,7 @@ type PluginAppConfig struct { func ProvideAppInstaller( metaProviderManager *meta.ProviderManager, -) (appsdkapiserver.AppInstaller, error) { +) (*PluginAppInstaller, error) { specificConfig := &PluginAppConfig{ MetaProviderManager: metaProviderManager, } @@ -83,7 +85,7 @@ func ProvideAppInstaller( return nil, err } - appInstaller := &pluginAppInstaller{ + appInstaller := &PluginAppInstaller{ AppInstaller: defaultInstaller, metaManager: metaProviderManager, ready: make(chan struct{}), @@ -91,16 +93,22 @@ func ProvideAppInstaller( return appInstaller, nil } -type pluginAppInstaller struct { +func (p *PluginAppInstaller) WithAccessChecker(access authlib.AccessChecker) *PluginAppInstaller { + p.access = access + return p +} + +type PluginAppInstaller struct { appsdkapiserver.AppInstaller metaManager *meta.ProviderManager + access authlib.AccessChecker // restConfig is set during InitializeApp and used by the client factory restConfig *restclient.Config ready chan struct{} } -func (p *pluginAppInstaller) InitializeApp(restConfig restclient.Config) error { +func (p *PluginAppInstaller) InitializeApp(restConfig restclient.Config) error { if p.restConfig == nil { p.restConfig = &restConfig close(p.ready) @@ -108,7 +116,7 @@ func (p *pluginAppInstaller) InitializeApp(restConfig restclient.Config) error { return p.AppInstaller.InitializeApp(restConfig) } -func (p *pluginAppInstaller) InstallAPIs( +func (p *PluginAppInstaller) InstallAPIs( server appsdkapiserver.GenericAPIServer, restOptsGetter generic.RESTOptionsGetter, ) error { @@ -139,3 +147,36 @@ func (p *pluginAppInstaller) InstallAPIs( } return p.AppInstaller.InstallAPIs(wrappedServer, restOptsGetter) } + +func (p *PluginAppInstaller) GetAuthorizer() authorizer.Authorizer { + if p.access == nil { + return nil + } + + return authorizer.AuthorizerFunc( + func(ctx context.Context, a authorizer.Attributes) (decision authorizer.Decision, reason string, err error) { + info, ok := authlib.AuthInfoFrom(ctx) + if !ok { + return authorizer.DecisionDeny, "failed to get auth info", nil + } + + res, err := p.access.Check(ctx, info, authlib.CheckRequest{ + Verb: a.GetVerb(), + Group: a.GetAPIGroup(), + Resource: a.GetResource(), + Name: a.GetName(), + Namespace: a.GetNamespace(), + Subresource: a.GetSubresource(), + Path: a.GetPath(), + }, "") + if err != nil { + return authorizer.DecisionDeny, "failed to perform authorization", err + } + + if !res.Allowed { + return authorizer.DecisionDeny, "permission denied", nil + } + + return authorizer.DecisionAllow, "", nil + }) +} diff --git a/apps/preferences/go.mod b/apps/preferences/go.mod index 9a5c8088c0f..661002a3b59 100644 --- a/apps/preferences/go.mod +++ b/apps/preferences/go.mod @@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/preferences go 1.25.5 require ( - github.com/grafana/grafana-app-sdk v0.48.4 + github.com/grafana/grafana-app-sdk v0.48.5 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2 k8s.io/apimachinery v0.34.2 k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 diff --git a/apps/preferences/go.sum b/apps/preferences/go.sum index 22bf6a8cbcd..75a19848d73 100644 --- a/apps/preferences/go.sum +++ b/apps/preferences/go.sum @@ -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.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 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/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= diff --git a/apps/preferences/kinds/cue.mod/module.cue b/apps/preferences/kinds/cue.mod/module.cue index 6280fd8f227..9675fc32a51 100644 --- a/apps/preferences/kinds/cue.mod/module.cue +++ b/apps/preferences/kinds/cue.mod/module.cue @@ -1,4 +1,4 @@ module: "github.com/grafana/grafana/apps/preferences/kinds" language: { - version: "v0.9.0" + version: "v0.11.0" } diff --git a/apps/provisioning/go.mod b/apps/provisioning/go.mod index e84ab0d35da..3cccd7dd8be 100644 --- a/apps/provisioning/go.mod +++ b/apps/provisioning/go.mod @@ -44,7 +44,7 @@ require ( github.com/gorilla/mux v1.8.1 // indirect github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 // indirect github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect - github.com/grafana/grafana-app-sdk v0.48.4 // indirect + github.com/grafana/grafana-app-sdk v0.48.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.18.0 // indirect diff --git a/apps/provisioning/go.sum b/apps/provisioning/go.sum index 791bf68e797..0e1ba180fad 100644 --- a/apps/provisioning/go.sum +++ b/apps/provisioning/go.sum @@ -62,8 +62,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.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 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/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/apps/secret v0.0.0-20250902093454-b56b7add012f h1:f+Z5Xpfp1WNYjUe23ginerWsHWUsRgOWrr3WGu3SlWs= diff --git a/apps/provisioning/kinds/cue.mod/module.cue b/apps/provisioning/kinds/cue.mod/module.cue index 20a2c78795d..421207ff553 100644 --- a/apps/provisioning/kinds/cue.mod/module.cue +++ b/apps/provisioning/kinds/cue.mod/module.cue @@ -1,4 +1,4 @@ module: "github.com/grafana/grafana/apps/provisioning" language: { - version: "v0.9.0" + version: "v0.11.0" } \ No newline at end of file diff --git a/apps/sdk.mk b/apps/sdk.mk index 62d89ed8ed3..68cf4c1c9c9 100644 --- a/apps/sdk.mk +++ b/apps/sdk.mk @@ -1,4 +1,4 @@ -APP_SDK_VERSION = v0.48.4 +APP_SDK_VERSION = v0.48.5 APP_SDK_DIR = $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION) APP_SDK_BIN = $(APP_SDK_DIR)/grafana-app-sdk diff --git a/apps/secret/go.mod b/apps/secret/go.mod index da71ef8e666..a1ed48be6e7 100644 --- a/apps/secret/go.mod +++ b/apps/secret/go.mod @@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/secret go 1.25.5 require ( - github.com/grafana/grafana-app-sdk v0.48.4 + github.com/grafana/grafana-app-sdk v0.48.5 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250710134100-1f3dc0533caf github.com/stretchr/testify v1.11.1 go.yaml.in/yaml/v3 v3.0.4 diff --git a/apps/secret/go.sum b/apps/secret/go.sum index 950843f4a7d..166e281f5af 100644 --- a/apps/secret/go.sum +++ b/apps/secret/go.sum @@ -37,8 +37,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.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 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/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-20250710134100-1f3dc0533caf h1:BBGDHffvVNLoYQlXEpbXcxE0vbpq7pm/8OWF5I+UDZg= diff --git a/apps/secret/kinds/cue.mod/module.cue b/apps/secret/kinds/cue.mod/module.cue index bad5ef304e1..d293a6b30e1 100644 --- a/apps/secret/kinds/cue.mod/module.cue +++ b/apps/secret/kinds/cue.mod/module.cue @@ -1,4 +1,4 @@ module: "github.com/grafana/grafana/apps/secret/kinds" language: { - version: "v0.9.0" + version: "v0.11.0" } diff --git a/apps/shorturl/go.mod b/apps/shorturl/go.mod index 128609888ba..4a414de5b4e 100644 --- a/apps/shorturl/go.mod +++ b/apps/shorturl/go.mod @@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/shorturl go 1.25.5 require ( - github.com/grafana/grafana-app-sdk v0.48.4 + github.com/grafana/grafana-app-sdk v0.48.5 github.com/grafana/grafana-app-sdk/logging v0.48.3 github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250915132226-585b53bc7dba k8s.io/apimachinery v0.34.2 diff --git a/apps/shorturl/go.sum b/apps/shorturl/go.sum index c7f57094324..58ecc31fd82 100644 --- a/apps/shorturl/go.sum +++ b/apps/shorturl/go.sum @@ -56,8 +56,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.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 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/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-20250915132226-585b53bc7dba h1:Qam8QzVRsyZN39zgZ9Vj6e8PEfswvv2McnqCZ/v5NcI= diff --git a/apps/shorturl/kinds/cue.mod/module.cue b/apps/shorturl/kinds/cue.mod/module.cue index 2e6cdd1ee5b..f4ce8b944f2 100644 --- a/apps/shorturl/kinds/cue.mod/module.cue +++ b/apps/shorturl/kinds/cue.mod/module.cue @@ -1,2 +1,4 @@ module: "github.com/grafana/grafana/apps/shorturl/kinds" -language: version: "v0.8.2" +language: { + version: "v0.11.0" +} diff --git a/devenv/plugins.yaml b/devenv/plugins.yaml index 554a4828cff..0f292e324f1 100644 --- a/devenv/plugins.yaml +++ b/devenv/plugins.yaml @@ -21,3 +21,7 @@ apps: org_id: 1 org_name: Main Org. disabled: false +panels: + - type: grafana-e2etest-panel + org_id: 1 + org_name: Main Org. diff --git a/docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md b/docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md index 92f6c6fe5e2..641d9bb4180 100644 --- a/docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md +++ b/docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md @@ -221,24 +221,25 @@ For more information on Cloud Access Policies and how to use them, see [Access p ### Grafana Alerting Notification action definitions -| Action | Applicable scopes | Description | -| -------------------------------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------------- | -| `alert.notifications.receivers:read` | `receivers:*`
`receivers:uid:*` | Read contact points. | -| `alert.notifications.receivers.secrets:read` | `receivers:*`
`receivers:uid:*` | Export contact points with decrypted secrets. | -| `alert.notifications.receivers:create` | None | Create a new contact points. The creator is automatically granted full access to the created contact point. | -| `alert.notifications.receivers:write` | `receivers:*`
`receivers:uid:*` | Update existing contact points. | -| `alert.notifications.receivers:delete` | `receivers:*`
`receivers:uid:*` | Update and delete existing contact points. | -| `alert.notifications.receivers:test` | None | Test contact point notification. | -| `receivers.permissions:read` | `receivers:*`
`receivers:uid:*` | Read permissions for contact points. | -| `receivers.permissions:write` | `receivers:*`
`receivers:uid:*` | Manage permissions for contact points. | -| `alert.notifications.time-intervals:read` | None | Read mute time intervals. | -| `alert.notifications.time-intervals:write` | None | Create new or update existing mute time intervals. | -| `alert.notifications.time-intervals:delete` | None | Delete existing time intervals. | -| `alert.notifications.templates:read` | None | Read templates. | -| `alert.notifications.templates:write` | None | Create new or update existing templates. | -| `alert.notifications.templates:delete` | None | Delete existing templates. | -| `alert.notifications.routes:read` | None | Read notification policies. | -| `alert.notifications.routes:write` | None | Create new, update or delete notification policies | +| Action | Applicable scopes | Description | +| ----------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `alert.notifications.receivers:read` | `receivers:*`
`receivers:uid:*` | Read contact points. | +| `alert.notifications.receivers.secrets:read` | `receivers:*`
`receivers:uid:*` | Export contact points with decrypted secrets. | +| `alert.notifications.receivers:create` | None | Create a new contact points. The creator is automatically granted full access to the created contact point. | +| `alert.notifications.receivers:write` | `receivers:*`
`receivers:uid:*` | Update existing contact points. | +| `alert.notifications.receivers.protected:write` | `receivers:*`
`receivers:uid:*` | Update [protected fields](/docs/grafana//alerting/configure-notifications/manage-contact-points#grafana-cloud-protected-fields) in contact points (such as target URLs for integrations). This scope only applies to Grafana Cloud. | +| `alert.notifications.receivers:delete` | `receivers:*`
`receivers:uid:*` | Update and delete existing contact points. | +| `alert.notifications.receivers:test` | None | Test contact point notification. | +| `receivers.permissions:read` | `receivers:*`
`receivers:uid:*` | Read permissions for contact points. | +| `receivers.permissions:write` | `receivers:*`
`receivers:uid:*` | Manage permissions for contact points. | +| `alert.notifications.time-intervals:read` | None | Read mute time intervals. | +| `alert.notifications.time-intervals:write` | None | Create new or update existing mute time intervals. | +| `alert.notifications.time-intervals:delete` | None | Delete existing time intervals. | +| `alert.notifications.templates:read` | None | Read templates. | +| `alert.notifications.templates:write` | None | Create new or update existing templates. | +| `alert.notifications.templates:delete` | None | Delete existing templates. | +| `alert.notifications.routes:read` | None | Read notification policies. | +| `alert.notifications.routes:write` | None | Create new, update or delete notification policies | ### Grafana Synthetic Monitoring action definitions diff --git a/docs/sources/administration/roles-and-permissions/access-control/plan-rbac-rollout-strategy/index.md b/docs/sources/administration/roles-and-permissions/access-control/plan-rbac-rollout-strategy/index.md index 1924ab84149..f9c43317585 100644 --- a/docs/sources/administration/roles-and-permissions/access-control/plan-rbac-rollout-strategy/index.md +++ b/docs/sources/administration/roles-and-permissions/access-control/plan-rbac-rollout-strategy/index.md @@ -162,7 +162,7 @@ The following request creates a custom role that includes permissions to access ``` curl --location --request POST '/api/access-control/roles/' \ ---header 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' \ +--header 'Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697' \ --header 'Content-Type: application/json' \ --data-raw '{ "version": 1, @@ -208,13 +208,13 @@ By default, only a Grafana Server Admin can create and manage custom roles. If y ```bash # Fetch the role, modify it to add the desired permissions and increment its version - curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' \ + curl -H 'Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697' \ -X GET '/api/access-control/roles/basic_editor' | \ jq 'del(.created)| del(.updated) | del(.permissions[].created) | del(.permissions[].updated) | .version += 1' | \ jq '.permissions += [{"action": "roles:read", "scope": "roles:*"}, {"action": "roles:write", "scope": "permissions:type:delegate"}, {"action": "roles:delete", "scope": "permissions:type:delegate"}]' > /tmp/basic_editor.json # Update the role - curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' -H 'Content-Type: application/json' \ + curl -H 'Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697' -H 'Content-Type: application/json' \ -X PUT-d @/tmp/basic_editor.json '/api/access-control/roles/basic_editor' ``` @@ -253,13 +253,13 @@ If you want your `Viewers` to create reports, [update the `Viewer` basic role pe ```bash # Fetch the role, modify it to add the desired permissions and increment its version - curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' \ + curl -H 'Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697' \ -X GET '/api/access-control/roles/basic_viewer' | \ jq 'del(.created)| del(.updated) | del(.permissions[].created) | del(.permissions[].updated) | .version += 1' | \ jq '.permissions += [{"action": "reports:create"}, {"action": "reports:read", "scope": "reports:*"}, {"action": "reports:write", "scope": "reports:*"}, {"action": "reports:send", "scope": "reports:*"}]' > /tmp/basic_viewer.json # Update the role - curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' -H 'Content-Type: application/json' \ + curl -H 'Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697' -H 'Content-Type: application/json' \ -X PUT-d @/tmp/basic_viewer.json '/api/access-control/roles/basic_viewer' ``` @@ -299,13 +299,13 @@ There are two ways to achieve this: ```bash # Fetch the role, modify it to remove the undesired permissions and increment its version - curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' \ + curl -H 'Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697' \ -X GET '/api/access-control/roles/basic_grafana_admin' | \ jq 'del(.created)| del(.updated) | del(.permissions[].created) | del(.permissions[].updated) | .version += 1' | \ jq 'del(.permissions[] | select (.action == "users:create")) | del(.permissions[] | select (.action == "org.users:add" and .scope == "users:*"))' > /tmp/basic_grafana_admin.json # Update the role - curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' -H 'Content-Type: application/json' \ + curl -H 'Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697' -H 'Content-Type: application/json' \ -X PUT-d @/tmp/basic_grafana_admin.json '/api/access-control/roles/basic_grafana_admin' ``` @@ -361,14 +361,14 @@ Here are two ways to achieve this: ```bash # Fetch the role, modify it to remove the undesired permissions, add the new permission and increment its version - curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' \ + curl -H 'Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697' \ -X GET '/api/access-control/roles/basic_viewer' | \ jq 'del(.created)| del(.updated) | del(.permissions[].created) | del(.permissions[].updated) | .version += 1' | \ jq 'del(.permissions[] | select (.action == "plugins.app:access" and .scope == "plugins:*"))' | \ jq '.permissions += [{"action": "plugins.app:access", "scope": "plugins:id:kentik-connect-app"}]' > /tmp/basic_viewer.json # Update the role - curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' -H 'Content-Type: application/json' \ + curl -H 'Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697' -H 'Content-Type: application/json' \ -X PUT -d @/tmp/basic_viewer.json '/api/access-control/roles/basic_viewer' ``` @@ -400,13 +400,13 @@ Here are two ways to achieve this: ```bash # Fetch the role, modify it to remove permissions to kentik-connect-app and increment role version - curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' \ + curl -H 'Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697' \ -X GET '/api/access-control/roles/basic_viewer' | \ jq 'del(.created)| del(.updated) | del(.permissions[].created) | del(.permissions[].updated) | .version += 1' | \ jq 'del(.permissions[] | select (.action == "plugins.app:access" and .scope == "plugins:id:kentik-connect-app"))' # Update the role - curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' -H 'Content-Type: application/json' \ + curl -H 'Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697' -H 'Content-Type: application/json' \ -X PUT -d @/tmp/basic_viewer.json '/api/access-control/roles/basic_viewer' ``` diff --git a/docs/sources/administration/service-accounts/_index.md b/docs/sources/administration/service-accounts/_index.md index 34bbd916610..dcc7983b735 100644 --- a/docs/sources/administration/service-accounts/_index.md +++ b/docs/sources/administration/service-accounts/_index.md @@ -243,7 +243,7 @@ Authorize your request with the token whose permissions you want to check. {{< /admonition >}} ```bash -curl -H "Authorization: Bearer glsa_HOruNAb7SOiCdshU9algkrq7FDsNSLAa_54e2f8be" -X GET '/api/access-control/user/permissions' | jq +curl -H "Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697" -X GET '/api/access-control/user/permissions' | jq ``` The output lists the token's permissions: @@ -268,7 +268,7 @@ To list which dashboards a token can view, you can filter the `/api/access-contr #### Example ```bash -curl -H "Authorization: Bearer glsa_HOruNAb7SOiCdshU9algkrq7FDsNSLAa_54e2f8be" -X GET '/api/access-control/user/permissions' | jq '."dashboards:read"' +curl -H "Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697" -X GET '/api/access-control/user/permissions' | jq '."dashboards:read"' ``` The output lists the dashboards a token can view and the folders a token can view dashboards from, diff --git a/docs/sources/administration/service-accounts/migrate-api-keys.md b/docs/sources/administration/service-accounts/migrate-api-keys.md index d30b3bddcdb..5db442bbe42 100644 --- a/docs/sources/administration/service-accounts/migrate-api-keys.md +++ b/docs/sources/administration/service-accounts/migrate-api-keys.md @@ -136,10 +136,10 @@ curl -X POST -H "Content-Type: application/json" -d '{"name": "my-service-accoun curl -X POST -H "Content-Type: application/json" -d '{"name": "my-service-account-token"}' http://admin:admin@localhost:3000/api/serviceaccounts/1/tokens # response with the created SAT id,name and key. -{"id":2,"name":"my-service-account-token","key":"glsa_9244xlVFZK0j8Lh4fU8Cz6Z5tO664zIi_7a762939"}% +{"id":2,"name":"my-service-account-token","key":"glsa_iNValIdinValiDinvalidinvalidinva_5b582697"}% # now you can authenticate the same way as you did with the API key -curl --request GET --url http://localhost:3000/api/folders --header 'Authorization: Bearer glsa_9244xlVFZK0j8Lh4fU8Cz6Z5tO664zIi_7a762939' +curl --request GET --url http://localhost:3000/api/folders --header 'Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697' # response [{"id":1,"uid":"a5261a84-eebc-4733-83a9-61f4713561d1","title":"gdev dashboards"}]% diff --git a/docs/sources/alerting/best-practices/dynamic-thresholds.md b/docs/sources/alerting/best-practices/dynamic-thresholds.md index 8cbc3ada2b0..e749bc1d943 100644 --- a/docs/sources/alerting/best-practices/dynamic-thresholds.md +++ b/docs/sources/alerting/best-practices/dynamic-thresholds.md @@ -12,7 +12,7 @@ labels: - oss menuTitle: Examples of dynamic thresholds title: Example of dynamic thresholds per dimension -weight: 1103 +weight: 1105 refs: testdata-data-source: - pattern: /docs/grafana/ diff --git a/docs/sources/alerting/best-practices/trace-based-alerts.md b/docs/sources/alerting/best-practices/trace-based-alerts.md new file mode 100644 index 00000000000..d908ecd7385 --- /dev/null +++ b/docs/sources/alerting/best-practices/trace-based-alerts.md @@ -0,0 +1,382 @@ +--- +canonical: https://grafana.com/docs/grafana/latest/alerting/best-practices/trace-based-alerts/ +description: This guide provides introductory examples and distinct approaches for setting up trace-based alerts in Grafana. +keywords: + - grafana +labels: + products: + - cloud + - enterprise + - oss +title: Examples of trace-based alerts +weight: 1103 +refs: + testdata-data-source: + - pattern: /docs/grafana/ + destination: /docs/grafana//datasources/testdata/ + - pattern: /docs/grafana-cloud/ + destination: /docs/grafana-cloud/connect-externally-hosted/data-sources/testdata/ +--- + +# Examples of trace-based alerts + +Metrics are the foundation of most alerting systems. They are usually the first signal that something is wrong, but they don’t always indicate _where_ or _why_ a failure occurs. + +Traces fill that gap by showing the complete path a request takes through your system. They map the workflows across services, indicating where the request slows down or fails. + +{{< figure src="/media/docs/alerting/screenshot-traces-visualization-11.5.png" max-width="750px" alt="Trace view" >}} + +Traces report duration and errors directly to specific services and spans, helping to find the affected component and service scope. With this additional context, alerting on tracing data can help you **identify root causes faster**. + +You can create trace-based alerts in Grafana Alerting using two main approaches: + +- Querying metrics generated from tracing data. +- Using TraceQL, a query language for traces available in Grafana Tempo. + +This guide provides introductory examples and distinct approaches for setting up **trace-based alerts** in Grafana. Tracing data is commonly collected using **OpenTelemetry (OTel)** instrumentation. OTel allows you to integrate trace data from a wide range of applications and environments into Grafana. + +## **Alerting on span metrics** + +OpenTelemetry provides processors that convert tracing data into Prometheus-style metrics. + +The **service graph** and **span metrics** processors are the standard options in Alloy and Tempo to generate Prometheus metrics from traces. They can generate the rate, error, and duration (RED) metrics from sampled spans. + +You can then create alert rules that query metrics derived from traces. + +{{< figure src="/media/docs/alerting/why-trace-based-metrics.png" max-width="750px" alt="Why metrics if you have traces?" >}} + +[Service graph metrics](https://grafana.com/docs/tempo/latest/metrics-from-traces/service_graphs/) focus on inter-service communication and dependency health. They measure the calls between services, helping Grafana to infer the service topology. However, they measure only the interaction between two services—they don’t include the internal processing time of the client service. + +You can use service graph metrics to detect infrastructure issues such as network degradation or service mesh problems. + +For trace-based alerts, we recommend using [span metrics](https://grafana.com/docs/tempo/latest/metrics-from-traces/span-metrics/). + +**Span metrics** measure the total processing time of a service request: capturing what happens inside the service, not just the communication between services. They include the time spent on internal processing and waiting on downstream calls, providing an **end-to-end picture of service performance**. + +Depending on how you create span metrics, the following span metrics are generated: + +| Span metrics generator | Metric name | Prometheus metric type | Description | +| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------- | :---------------------------- | :--------------------------- | +| [Alloy](https://grafana.com/docs/alloy/latest/reference/components/otelcol/otelcol.connector.spanmetrics/) and [OTEL span metrics connector](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/connector/spanmetricsconnector) | `traces_span_metrics_calls_total` | Counter | Total count of the span | +| | `traces_span_metrics_duration_seconds` | Histogram (native or classic) | Duration of the span | +| [Tempo](https://grafana.com/docs/tempo/latest/metrics-from-traces/span-metrics/span-metrics-metrics-generator/) and [Grafana Cloud Application Observability](https://grafana.com/docs/grafana-cloud/monitor-applications/application-observability/setup/metrics-labels/) | `traces_spanmetrics_calls_total` | Counter | Total count of the span | +| | `traces_spanmetrics_latency` | Histogram (native or classic) | Duration of the span | +| | `traces_spanmetrics_size_total` | Counter | Total size of spans ingested | + +Each metric includes by default the following labels: `service`, `span_name`, `span_kind`, `status_code`, `status_message`, `job`, and `instance`. + +In the metrics generator, you can customize how traces are converted into metrics by configuring histograms, exemplars, metric dimensions, and other options. + +The following examples assume that span metrics have already been generated using one of these options or an alternative. + +### Detect slow span operations + +This example shows how to define an alert rule that detects when operations handled by a service become slow. + +Before looking at the query, it’s useful to review a few [trace elements](https://grafana.com/docs/tempo/latest/introduction/trace-structure/) that shape how it works: + +- A trace represents a single request or transaction as it flows through multiple spans and services. A span refers to a specific operation within a service. +- Each span includes the operation name (`span_name`) and its duration (the metric value), as well as additional fields like [span status](https://opentelemetry.io/docs/concepts/signals/traces/#span-status) (`status_code`) and [span kind](https://opentelemetry.io/docs/concepts/signals/traces/#span-kind) (`span_kind`). +- A server span represents work performed on the receiving side of a request, while a client span represents the outbound call (parent span) waiting for a response (client → server). + +To detect slow inbound operations within a specific service, you can define an alert rule that detects when the percentile latency of server spans exceeds a threshold. For example: + +_Detect when 95% of requests (excluding errors) do not complete faster than 2 seconds._ + +#### Using native histograms + +The following PromQL query uses the `traces_span_metrics_duration_seconds` native histogram metric to define the alert rule query. + +```promql +histogram_quantile(0.95, + sum by (span_name) ( + rate(traces_span_metrics_duration_seconds{ + service_name="", + span_kind="SPAN_KIND_SERVER", + status_code!="STATUS_CODE_ERROR" + }[10m]) + ) +) > 2 +``` + +Here’s the query breakdown + +- `traces_span_metrics_duration_seconds` + It’s a native histogram produced from spans using Alloy or the OTEL collector. The metric is filtered by: + - `service_name=""` targets a particular service. + - `span_kind="SPAN_KIND_SERVER"` selects spans handling inbound requests. + - `status_code!="STATUS_CODE_ERROR"` excludes spans that ended with errors. + + _You should query `traces_spanmetrics_latency` when using other span metric generators._ + +- `rate(...[10m])` + Converts the histogram into a per-second histogram over the last 10 minutes (the distribution of spans per second during that period). + This makes the time window explicit and ensures latencies can be calculated over the last 10 minutes using `histogram_*` functions. +- `sum by (span_name)( … )` + Merges all series that share the same `span_name`. This creates a [multidimensional alert](https://grafana.com/docs/grafana/latest/alerting/best-practices/multi-dimensional-alerts/) that generates one alert instance per span name (operation). +- `histogram_quantile(0.95, ...)` + Calculates p95 latency from the histogram after applying the rate. + The query runs as an **instant Prometheus query**, returning a single value for the 10-minute window. +- `> 2` + Defines the threshold condition. It returns only series whose p95 latency exceeds 2 seconds. + Alternatively, you can set this threshold as a Grafana Alerting expression in the UI, as shown in the following screenshot. + + {{< figure src="/media/docs/alerting/trace-based-alertrule-screenshot.png" max-width="750px" caption="Alert rule querying span metrics and using threshold expression" >}} + +#### Using classic histograms + +Native histograms are stable in Prometheus since v3.8.0. Your span metric generator may therefore create classic histograms for latency span metrics, either `traces_span_metrics_duration_seconds` or `traces_spanmetrics_latency`. + +When using classic histograms, the metric is the same but the metric format changes. A classic histogram represents a histogram with fixed buckets and exposes three metrics: + +- `_bucket`: cumulative buckets of the observations. +- `_sum`: total sum of all observed values. +- `_count`: count of observed values. + +To calculate percentiles accurately, especially exceeding a particular threshold (e.g. `` `2s` ``), you have to configure the classic histogram with the explicit bucket, such as: + +```shell +["100ms", "250ms", "1s", "2s", "5s"] +``` + +The `otelcol.connector.spanmetrics` can configure the buckets using the [`explicit` block](https://grafana.com/docs/alloy/latest/reference/components/otelcol/otelcol.connector.spanmetrics/#explicit). The metric-generator in Tempo can configure the [`span_metrics.histogram_buckets` setting](https://grafana.com/docs/tempo/latest/configuration/#metrics-generator). + +Here's the equivalent PromQL for classic histograms: + +```promql +histogram_quantile(0.95, + sum by (span_name, le) ( + rate(traces_span_metrics_duration_seconds_bucket{ + service_name="", + span_kind="SPAN_KIND_SERVER", + status_code!="STATUS_CODE_ERROR" + }[10m]) + ) +) > 2 +``` + +Key differences compared with the native histograms example: + +- You must configure a histogram bucket matching the desired threshold (for example, `2s`). +- You must query the `_bucket` metric, not the base metric. +- You must include `le` in the `sum by (…)` grouping for `histogram_quantile` calculation. + +Everything else remains the same. + +{{< admonition type="note" >}} + +The alert rules in these examples create [multi-dimensional alerts](https://grafana.com/docs/grafana/latest/alerting/best-practices/multi-dimensional-alerts/): one alert instance for each distinct span name. + +Dynamic span routes such as `/product/1234` can create separate metric dimensions and alerts for each unique span, which can significantly impact metric costs and performance for large volumes. + +To prevent high-cardinality data, normalize dynamic routes like `/product/{id}` using semantic attributes such as [`http.route`](https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/) and [`url.template`](https://opentelemetry.io/docs/specs/semconv/registry/attributes/url/), and limit dimensions to low-cardinality fields such as `service_name`, `status_code`, or `http_method`. + +{{< /admonition >}} + +### Detect high error rate + +This example defines an alert rule that detects when the error rate for any operation exceeds 20%. You can use this error rate alerts to identify increases in request errors, such as 5xx responses or internal failures. + +The following query calculates the fraction of failed server spans for each service and operation. + +```promql +( + sum by (service, span_name) ( + rate(traces_span_metrics_calls_total{ + span_kind="SPAN_KIND_SERVER", + status_code="STATUS_CODE_ERROR" + }[10m]) + ) +/ + sum by (service, span_name) ( + rate(traces_span_metrics_calls_total{ + span_kind="SPAN_KIND_SERVER" + }[10m]) + ) +) > 0.2 +``` + +Here’s the query breakdown + +- `traces_span_metrics_calls_total` + A counter metric produced from spans that tracks the number of completed span operations. + - `span_kind="SPAN_KIND_SERVER"` selects spans handling inbound requests. + - `status_code="STATUS_CODE_ERROR"` selects only spans that ended in error. + - Omitting the `status_code` filter in the denominator includes all spans, returning the total span count. + + _Check whether your metric generator instead creates the `traces_spanmetrics_calls_total` metric, and adjust the metric name._ + +- `rate(...[10m])` + Converts the cumulative histogram into a per-second histogram over the last 10 minutes (the distribution of spans per second during that period). + This makes the time window explicit and ensures counters can be calculated over the last 10 minutes. +- `sum by (service, span_name)( … )` + Aggregates per service and operation, creating one alert instance for each `(service, span_name)` combination. + This is a [multidimensional alert](https://grafana.com/docs/grafana/latest/alerting/best-practices/multi-dimensional-alerts/) that applies to all services, helping identify which service and corresponding operation is failing. +- `sum by () (...) / sum by () (...)` + Divides failed spans by total spans to calculate the error rate per operation. + The result is a ratio between `0` and `1,` where `1` means all operations failed. + The query runs as an **instant Prometheus query**, returning a single value for the 10-minute window. +- `> 0.2` + Defines the threshold condition. It returns only series whose error rate is higher than 20% of spans. + Alternatively, you can set this threshold as a Grafana Alerting expression in the UI. + +### Enable traffic guardrails + +When the traffic is very low, even a single slow or failing request can trigger the alerts. + +To avoid these types of false positives during low-traffic periods, you can include a **minimum traffic condition** in your alert rule queries. For example: + +```promql +sum by (service, span_name)( + increase(traces_span_metrics_calls_total{ + span_kind="SPAN_KIND_SERVER" + }[10m]) +) > 300 +``` + +This query returns only spans that handled more than 300 requests in the 10-minute period. + +This minimum level of traffic helps prevent false positives, ensuring the alert evaluates a significant number of spans before triggering. + +You can combine this traffic condition with the **error-rate** query to ensure alerts fire only when both conditions are met: + +```promql +(( + sum by (service, span_name) ( + rate(traces_span_metrics_calls_total{ + span_kind="SPAN_KIND_SERVER", + status_code="STATUS_CODE_ERROR" + }[10m]) + ) +/ + sum by (service, span_name) ( + rate(traces_span_metrics_calls_total{ + span_kind="SPAN_KIND_SERVER" + }[10m]) + ) +) > 0.2) +and +( + sum by (service, span_name)( + increase(traces_span_metrics_calls_total{ + span_kind="SPAN_KIND_SERVER" + }[10m]) +) > 300 ) + +``` + +For a given span, the alert fires when: + +- The **error rate exceeds 20%** over the last 10 minutes. +- The span **handled at least 300 requests** over the last 10 minutes. + +**Alternatively**, you can split the alert into separate queries and combine them using a math expression as the threshold. In the example below, `$ErrorRateCondition` is the Grafana reference for the error-rate query, and `$TrafficCondition` is the reference for the traffic query. + +{{< figure src="/media/docs/alerting/traffic-guardrail-with-separate-queries.png" max-width="500px" alt="Alert rule with threshold based on two queries" >}} + +In this case, you must ensure both queries group by the same labels. + +The advantage of this approach is that you can observe the results of both independent queries. You can then access the query results through the [`$values` variable](https://grafana.com/docs/grafana/latest/alerting/alerting-rules/templates/reference/#values) and display them in notifications or use them in custom labels. + +A potential drawback of splitting queries is that each query runs separately. This increases backend load and can affect query performance, especially in environments with a large number of active alerts. + +You can apply this traffic guardrail pattern to any alert rule. + +### Consider sampling {#consider-sampling} + +[Sampling](https://grafana.com/docs/tempo/latest/set-up-for-tracing/instrument-send/set-up-collector/tail-sampling/) is a technique used to reduce the amount of collected spans for cost-saving purposes. There are two main strategies which can be combined: + +- **Head sampling**: The decision to record or drop a span is made when the trace begins. The condition can be configured probabilistically (a percentage of traces) or by filtering out certain operations. +- **Tail sampling**: The decision is made after the trace completes. This allows sampling more interesting operations, such as slow or failing requests. + +With **head sampling**, alerting on span metrics should be done with caution, since span metrics will represent only a subset of all traces. + +With **tail sampling**, it’s important to generate span metrics before a sampling decision is made. [Grafana Cloud Adaptive Traces](https://grafana.com/docs/grafana-cloud/adaptive-telemetry/adaptive-traces/) handle this automatically. With Alloy or the OpenTelemetry Collector, make sure the SpanMetrics connector runs before the filtering or [tail sampling processor](https://grafana.com/docs/alloy/latest/reference/components/otelcol/otelcol.processor.tail_sampling/). + +## **Using TraceQL (experimental)** + +**TraceQL** is a query language for searching and filtering traces in **Grafana Tempo**, which uses a syntax similar to `PromQL` and `LogQL`. + +With TraceQL, you can skip converting tracing data into span metrics and query raw trace data directly. It provides a more flexible filtering based on the trace structure, attributes, or resource metadata, and can detect issues faster as it does not wait for metric generation. + +However, keep in mind that TraceQL is not suitable for all scenarios. For example: + +- **Inadequate for long-term analysis** + Trace data has a significantly shorter retention period than metrics. For historical monitoring, it’s recommended to convert key tracing data into metrics to ensure the persistence of important data. +- **Inadequate for alerting after sampling** + TraceQL can only query traces that are actually stored in Tempo. If sampling drops a large portion of traces, TraceQL-based alerts may miss real issues. Refer to [consider sampling](#consider-sampling) for guidance on how to generate span metrics before sampling. + + {{< admonition type="caution" >}} + + TraceQL alerting is available in Grafana v12.1 or higher, supported as an [experimental feature](https://grafana.com/docs/release-life-cycle/). + Engineering and on-call support is not available. Documentation is either limited or not provided outside of code comments. No SLA is provided. + + While TraceQL can be powerful for exploring and detecting issues directly from trace data, **alerting with TraceQL should not be used in production environments yet**. Use it for testing and experimentation at this moment. + + {{< /admonition >}} + +The following example demonstrates how to recreate the previous **alert rule that detected slow span operations** using TraceQL. + +Follow these steps to create the alert: + +1. Enable TraceQL alerting + To use TraceQL in alerts, you must enable the [**`tempoAlerting`** feature flag in your Grafana configuration](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#feature_toggles). + +2. Configure the alert query + + In your alert rule, select the **Tempo** data source, then convert the original PromQL query into the equivalent TraceQL query: + + ```traceql + {status != error && kind = server && .service.name = ""} + | quantile_over_time(duration, .95) by (name) + ``` + + For a given service, this query calculates the **p95 latency** for all server spans, excluding errors, and groups them by span name. + +3. Configure the time range + + Currently, TraceQL alerting supports only range queries. + To define the time window, set the query time range to **the last 10 minutes.** + - From: `now-10m` + - To: `now` + + {{< figure src="/media/docs/alerting/traceql-alert-configure-time-range.png" max-width="750px" alt="Time range configuration for TraceQL alert rule" >}} + +4. Add a reducer expression. + + Range queries return time series data, not a single value. The alert rule must then **reduce** time series data to a single numeric value before comparing it against a threshold. + + Add a **Reduce** expression to convert the query results into a single value. + +5. Set the threshold condition. + + Create a **Threshold** expression to fire when the p95 latency exceeds 2 seconds: **$B > 2**. + + {{< figure src="/media/docs/alerting/traceql-alert-configure-threshold.png" max-width="750px" alt="Alert rule configuration showing reducer and threshold expressions for TraceQL query" >}} + +This final alert detects when 95% of the server spans for a particular service (excluding errors) take longer than 2 seconds to complete, using raw trace data instead of span metrics. + +## Additional resources + +To explore related topics and expand the examples in this guide, see the following resources: + +- [Trace structure](https://grafana.com/docs/tempo/latest/introduction/trace-structure/): Learn how traces and spans are structured. + +- [Grafana Tempo documentation](https://grafana.com/docs/tempo/latest/): Full reference for Grafana’s open source tracing backend. + +- [Span metrics using the metrics generator in Tempo](https://grafana.com/docs/tempo/latest/metrics-from-traces/span-metrics/span-metrics-metrics-generator/): Generate span metrics directly from traces with Tempo’s built-in metrics generator. + +- [Span metrics using Grafana Alloy](https://grafana.com/docs/tempo/latest/metrics-from-traces/span-metrics/span-metrics-alloy/): Configure Alloy to export span metrics from OpenTelemetry (OTel) traces. + +- [Multi-dimensional alerts](https://grafana.com/docs/grafana/latest/alerting/best-practices/multi-dimensional-alerts/): Learn how to trigger multiple alert instances per alert rule like in these examples. + +- [Grafana SLO documentation](https://grafana.com/docs/grafana-cloud/alerting-and-irm/slo/): Use span metrics to define Service Level Objectives (SLOs) in Grafana. +- [Trace sampling](https://grafana.com/docs/tempo/latest/set-up-for-tracing/instrument-send/set-up-collector/tail-sampling/#sampling): explore strategies and configuration in Grafana Tempo. + + {{< admonition type="note" >}} + + OpenTelemetry instrumentations can record metrics independently of spans. + + These [OTEL metrics](https://opentelemetry.io/docs/specs/semconv/general/metrics/) are not derived from traces and are not affected by sampling. They can serve as an alternative to span-derived metrics. + + {{< /admonition >}} diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/_index.md b/docs/sources/alerting/configure-notifications/manage-contact-points/_index.md index c04939f16b0..a468c91449d 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/_index.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/_index.md @@ -137,6 +137,23 @@ On the **Contact Points** tab, you can: Contact points are assigned to a [specific Alertmanager](ref:configure-alertmanager) and cannot be used by notification policies in other Alertmanagers. {{< /admonition >}} +## Grafana Cloud Protected fields + +For Grafana Cloud users, contact points may contain protected fields that require admin permissions to modify. Protected fields are sensitive configuration settings that affect where notifications are sent, such as: + +- Target URLs for integrations (webhooks, PagerDuty, Opsgenie, or other integrations.) +- API endpoints +- Other destination-related settings + +These fields are protected to prevent unauthorized users from redirecting notifications to compromised servers, which could expose sensitive information such as authorization tokens, API keys, or alert data. + +Users with edit permissions can modify most contact point settings and can add or remove integrations, but cannot change protected fields in existing integrations. Only users with admin permissions to the contact point can update protected fields. + +The ability to modify protected fields is controlled by the RBAC action `alert.notifications.receivers.protected:write`. This role is granted by default to: + +- Users with the fixed "Alerting Admin" role +- Users with admin permissions for the specific contact point + ## Supported contact point integrations Each contact point integration has its own configuration options and setup process. The following list shows the contact point integrations supported by Grafana. diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-alertmanager.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-alertmanager.md index 9f5822eedc6..4cdc84ec366 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-alertmanager.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-alertmanager.md @@ -59,9 +59,9 @@ For more details on contact points, including how to test them and enable notifi ## Alertmanager settings -| Option | Description | -| ------ | --------------------- | -| URL | The Alertmanager URL. | +| Option | Description | +| ------ | ---------------------------------------------------------------------------------------------------------------------------------- | +| URL | The Alertmanager URL. This field is [protected](ref:configure-contact-points#protected-fields) from modification in Grafana Cloud. | #### Optional settings diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-jira.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-jira.md index a01783fb921..659341405f1 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-jira.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-jira.md @@ -49,14 +49,14 @@ For more details on contact points, including how to test them and enable notifi ### Required Settings -| Key | Description | -| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| URL | The URL of the REST API of your Jira instance. Supported versions: `2` and `3` (e.g., `https://your-domain.atlassian.net/rest/api/3`). | -| Basic Auth User | Username for authentication. For Jira Cloud, use your email address. | -| Basic Auth Password | Password or personal token. For Jira Cloud, you need to obtain a personal token [here](https://id.atlassian.com/manage-profile/security/api-tokens) and use it as the password. | -| API Token | An alternative to basic authentication, a bearer token is used to authorize the API requests. See [Jira documentation](https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html) for more information. | -| Project Key | The project key identifying the project where issues will be created. Project keys are unique identifiers for a project. | -| Issue Type | The type of issue to create (e.g., `Task`, `Bug`, `Incident`). Make sure that you specify a type that is available in your project. | +| Key | Description | +| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| URL | The URL of the REST API of your Jira instance. Supported versions: `2` and `3` (e.g., `https://your-domain.atlassian.net/rest/api/3`). This field is [protected](ref:configure-contact-points#protected-fields) from modification in Grafana Cloud. | +| Basic Auth User | Username for authentication. For Jira Cloud, use your email address. | +| Basic Auth Password | Password or personal token. For Jira Cloud, you need to obtain a personal token [here](https://id.atlassian.com/manage-profile/security/api-tokens) and use it as the password. | +| API Token | An alternative to basic authentication, a bearer token is used to authorize the API requests. See [Jira documentation](https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html) for more information. | +| Project Key | The project key identifying the project where issues will be created. Project keys are unique identifiers for a project. | +| Issue Type | The type of issue to create (e.g., `Task`, `Bug`, `Incident`). Make sure that you specify a type that is available in your project. | ### Optional Settings diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-mqtt.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-mqtt.md index 8e58e619f00..6f76a574619 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-mqtt.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-mqtt.md @@ -54,10 +54,10 @@ For more details on contact points, including how to test them and enable notifi ### Required Settings -| Option | Description | -| ---------- | -------------------------------------------- | -| Broker URL | The URL of the MQTT broker. | -| Topic | The topic to which the message will be sent. | +| Option | Description | +| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| Broker URL | The URL of the MQTT broker. This field is [protected](ref:configure-contact-points#protected-fields) from modification in Grafana Cloud. | +| Topic | The topic to which the message will be sent. | ### Optional Settings diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md index fdfbca1bb85..120a45be2a2 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md @@ -62,9 +62,9 @@ For more details on contact points, including how to test them and enable notifi ## Webhook settings -| Option | Description | -| ------ | ---------------- | -| URL | The Webhook URL. | +| Option | Description | +| ------ | ----------------------------------------------------------------------------------------------------------------------------- | +| URL | The Webhook URL. This field is [protected](ref:configure-contact-points#protected-fields) from modification in Grafana Cloud. | #### Optional settings diff --git a/docs/sources/datasources/mssql/configure/index.md b/docs/sources/datasources/mssql/configure/index.md index 4d3eb60ee81..7ce6398f1cc 100644 --- a/docs/sources/datasources/mssql/configure/index.md +++ b/docs/sources/datasources/mssql/configure/index.md @@ -153,10 +153,6 @@ If you're using an older version of Microsoft SQL Server like 2008 and 2008R2, y **Authentication:** -{{< admonition type="note" >}} -In order to use Azure AD Authentication the toggle `auth.azure_auth_enabled` must be set to `true` in the Grafana configuration file. -{{< /admonition >}} - | Authentication Type | Description | Credentials / Fields | | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **SQL Server Authentication** | Default method to connect to MSSQL. Use a SQL Server or Windows login in `DOMAIN\User` format. | - **Username**: SQL Server username
- **Password**: SQL Server password | diff --git a/docs/sources/developer-resources/api-reference/http-api/team.md b/docs/sources/developer-resources/api-reference/http-api/team.md index 25578435ba6..d45ebe64940 100644 --- a/docs/sources/developer-resources/api-reference/http-api/team.md +++ b/docs/sources/developer-resources/api-reference/http-api/team.md @@ -53,7 +53,7 @@ See note in the [introduction](#team-api) for an explanation. GET /api/teams/search?perpage=10&page=1&query=mytestteam HTTP/1.1 Accept: application/json Content-Type: application/json -Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt +Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697 ``` **Example Response**: @@ -119,7 +119,7 @@ See note in the [introduction](#team-api) for an explanation. GET /api/teams/1 HTTP/1.1 Accept: application/json Content-Type: application/json -Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt +Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697 ``` **Example Response**: @@ -165,7 +165,7 @@ See note in the [introduction](#team-api) for an explanation. POST /api/teams HTTP/1.1 Accept: application/json Content-Type: application/json -Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt +Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697 { "name": "MyTestTeam", @@ -209,7 +209,7 @@ See note in the [introduction](#team-api) for an explanation. PUT /api/teams/2 HTTP/1.1 Accept: application/json Content-Type: application/json -Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt +Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697 { "name": "MyTestTeam", @@ -252,7 +252,7 @@ See note in the [introduction](#team-api) for an explanation. DELETE /api/teams/2 HTTP/1.1 Accept: application/json Content-Type: application/json -Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt +Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697 ``` **Example Response**: @@ -289,7 +289,7 @@ See note in the [introduction](#team-api) for an explanation. GET /api/teams/1/members HTTP/1.1 Accept: application/json Content-Type: application/json -Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt +Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697 ``` **Example Response**: @@ -342,7 +342,7 @@ See note in the [introduction](#team-api) for an explanation. POST /api/teams/1/members HTTP/1.1 Accept: application/json Content-Type: application/json -Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt +Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697 { "userId": 2 @@ -384,7 +384,7 @@ See note in the [introduction](#team-api) for an explanation. DELETE /api/teams/2/members/3 HTTP/1.1 Accept: application/json Content-Type: application/json -Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt +Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697 ``` **Example Response**: @@ -424,7 +424,7 @@ See note in the [introduction](#team-api) for an explanation. PUT /api/teams/1/members HTTP/1.1 Accept: application/json Content-Type: application/json -Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt +Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697 { "members": ["user1@email.com", "user2@email.com"] diff --git a/docs/sources/developer-resources/api-reference/http-api/team_sync.md b/docs/sources/developer-resources/api-reference/http-api/team_sync.md index fc0a41769cc..2cd48a801d2 100644 --- a/docs/sources/developer-resources/api-reference/http-api/team_sync.md +++ b/docs/sources/developer-resources/api-reference/http-api/team_sync.md @@ -47,7 +47,7 @@ See note in the [introduction](#external-group-synchronization-api) for an expla GET /api/teams/1/groups HTTP/1.1 Accept: application/json Content-Type: application/json -Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt +Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697 ``` **Example Response**: @@ -131,7 +131,7 @@ See note in the [introduction](#external-group-synchronization-api) for an expla DELETE /api/teams/1/groups?groupId=cn%3Deditors%2Cou%3Dgroups%2Cdc%3Dgrafana%2Cdc%3Dorg HTTP/1.1 Accept: application/json Content-Type: application/json -Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt +Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697 ``` **Example Response**: @@ -168,7 +168,7 @@ Search for team groups with pagination support. GET /api/teams/1/groups/search?name=editors&query=group&page=1&perpage=10 HTTP/1.1 Accept: application/json Content-Type: application/json -Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt +Authorization: Bearer glsa_iNValIdinValiDinvalidinvalidinva_5b582697 ``` **Example Response**: diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index f0f12cce1b6..b80fa49f815 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -68,6 +68,7 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general- | `tabularNumbers` | Use fixed-width numbers globally in the UI | | | `azureResourcePickerUpdates` | Enables the updated Azure Monitor resource picker | Yes | | `tempoSearchBackendMigration` | Run search queries through the tempo backend | | +| `opentsdbBackendMigration` | Run queries through the data source backend | | ## Public preview feature toggles diff --git a/docs/sources/visualizations/dashboards/share-dashboards-panels/shared-dashboards/index.md b/docs/sources/visualizations/dashboards/share-dashboards-panels/shared-dashboards/index.md index 789d6617c18..b0dc5e723b2 100644 --- a/docs/sources/visualizations/dashboards/share-dashboards-panels/shared-dashboards/index.md +++ b/docs/sources/visualizations/dashboards/share-dashboards-panels/shared-dashboards/index.md @@ -37,6 +37,11 @@ refs: destination: /docs/grafana//introduction/grafana-enterprise/ - pattern: /docs/grafana-cloud/ destination: /docs/grafana//introduction/grafana-enterprise/ + fixed-role-definitions: + - pattern: /docs/grafana/ + destination: /docs/grafana//administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/#fixed-role-definitions + - pattern: /docs/grafana-cloud/ + destination: /docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-control/rbac-fixed-basic-role-definitions/#fixed-role-definitions --- # Externally shared dashboards @@ -49,6 +54,8 @@ Externally shared dashboards allow you to share your Grafana dashboard with anyo If you change a dashboard, ensure that you save the changes before sharing. +In order to create public dashboards, you need to be an Admin, have the `dashboards.public:write` permission, or the `fixed:dashboards.public:write` [RBAC role](ref:fixed-role-definitions). + {{< admonition type="warning" >}} Sharing your dashboard externally could result in a large number of queries to the data sources used by your dashboard. This can be mitigated by using the Enterprise [caching](ref:caching) and/or rate limiting features. @@ -250,6 +257,7 @@ guaranteed because plugin developers can override this functionality. The follow - Graphite - Google Sheets - Tempo +- Zabbix ### Unconfirmed diff --git a/e2e-playwright/dashboard-new-layouts/dashboards-edit-custom-variables.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboards-edit-custom-variables.spec.ts index 4715dfc7128..e11f2dd099a 100644 --- a/e2e-playwright/dashboard-new-layouts/dashboards-edit-custom-variables.spec.ts +++ b/e2e-playwright/dashboard-new-layouts/dashboards-edit-custom-variables.spec.ts @@ -84,9 +84,9 @@ test.describe( refetchItems(dashboardPage, selectors); }; - const closeModal = async (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => { + const applyAndcloseModal = async (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => { await dashboardPage - .getByGrafanaSelector(selectors.pages.Dashboard.Settings.Variables.Edit.CustomVariable.closeButton) + .getByGrafanaSelector(selectors.pages.Dashboard.Settings.Variables.Edit.CustomVariable.applyButton) .click(); }; @@ -149,7 +149,7 @@ test.describe( await removeItem(dashboardPage, selectors, 2); await checkRows(3); await checkPreview(dashboardPage, selectors, ['first value', 'second label', 'fourth value']); - await closeModal(dashboardPage, selectors); + await applyAndcloseModal(dashboardPage, selectors); // assert variable is visible and has the correct values const variableLabel = dashboardPage.getByGrafanaSelector( diff --git a/e2e-playwright/dashboards-suite/new-query-variable.spec.ts b/e2e-playwright/dashboards-suite/new-query-variable.spec.ts index 088f4bd9b12..ed92c79ee36 100644 --- a/e2e-playwright/dashboards-suite/new-query-variable.spec.ts +++ b/e2e-playwright/dashboards-suite/new-query-variable.spec.ts @@ -54,7 +54,13 @@ test.describe( await expect(descriptionInput).toHaveAttribute('placeholder', 'Descriptive text'); await expect(descriptionInput).toHaveValue(''); - await expect(page.locator('label').filter({ hasText: 'Hide' })).toBeVisible(); + // Display + await expect(page.locator('label', { hasText: /^Display$/ })).toBeVisible(); + const displaySelect = dashboardPage.getByGrafanaSelector( + selectors.pages.Dashboard.Settings.Variables.Edit.General.generalDisplaySelect + ); + await expect(displaySelect).toBeVisible(); + await expect(displaySelect).toHaveValue('Above dashboard'); // Check datasource selector const datasourceSelect = dashboardPage.getByGrafanaSelector( diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/components/App/App.tsx b/e2e-playwright/test-plugins/grafana-extensionstest-app/components/App/App.tsx index d57a1476e19..26d7b201466 100644 --- a/e2e-playwright/test-plugins/grafana-extensionstest-app/components/App/App.tsx +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/components/App/App.tsx @@ -3,7 +3,7 @@ import { Route, Routes } from 'react-router-dom'; import { AppRootProps } from '@grafana/data'; import { ROUTES } from '../../constants'; -import { AddedComponents, AddedLinks, ExposedComponents } from '../../pages'; +import { AddedComponents, AddedLinks, Config, ExposedComponents } from '../../pages'; import { testIds } from '../../testIds'; export function App(props: AppRootProps) { @@ -13,6 +13,7 @@ export function App(props: AppRootProps) { } /> } /> } /> + } /> } /> diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/constants.ts b/e2e-playwright/test-plugins/grafana-extensionstest-app/constants.ts index 120eb5d8191..c208781acf3 100644 --- a/e2e-playwright/test-plugins/grafana-extensionstest-app/constants.ts +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/constants.ts @@ -8,4 +8,5 @@ export enum ROUTES { ExposedComponents = 'exposed-components', AddedComponents = 'added-components', AddedLinks = 'added-links', + Config = 'config', } diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/i18next.config.ts b/e2e-playwright/test-plugins/grafana-extensionstest-app/i18next.config.ts new file mode 100644 index 00000000000..ba1645d38c9 --- /dev/null +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/i18next.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'i18next-cli'; +import pluginJson from './plugin.json'; + +export default defineConfig({ + locales: pluginJson.languages, + extract: { + input: ['**/*.{tsx,ts}'], + output: 'locales/{{language}}/{{namespace}}.json', + defaultNS: pluginJson.id, + functions: ['t', '*.t'], + transComponents: ['Trans'], + }, +}); diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/locales/en-US/grafana-extensionstest-app.json b/e2e-playwright/test-plugins/grafana-extensionstest-app/locales/en-US/grafana-extensionstest-app.json new file mode 100644 index 00000000000..2fc28958864 --- /dev/null +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/locales/en-US/grafana-extensionstest-app.json @@ -0,0 +1,7 @@ +{ + "config-page": { + "header": { + "text": "Is this translated" + } + } +} diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/locales/es-ES/grafana-extensionstest-app.json b/e2e-playwright/test-plugins/grafana-extensionstest-app/locales/es-ES/grafana-extensionstest-app.json new file mode 100644 index 00000000000..2c2f51a239d --- /dev/null +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/locales/es-ES/grafana-extensionstest-app.json @@ -0,0 +1,7 @@ +{ + "config-page": { + "header": { + "text": "¿Está traducido?" + } + } +} diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/locales/sv-SE/grafana-extensionstest-app.json b/e2e-playwright/test-plugins/grafana-extensionstest-app/locales/sv-SE/grafana-extensionstest-app.json new file mode 100644 index 00000000000..8bae86f58aa --- /dev/null +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/locales/sv-SE/grafana-extensionstest-app.json @@ -0,0 +1,7 @@ +{ + "config-page": { + "header": { + "text": "Det här är översatt" + } + } +} diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/module.tsx b/e2e-playwright/test-plugins/grafana-extensionstest-app/module.tsx index 89ed1af12c4..9f585c0d5f7 100644 --- a/e2e-playwright/test-plugins/grafana-extensionstest-app/module.tsx +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/module.tsx @@ -3,6 +3,9 @@ import { App } from './components/App'; import { QueryModal } from './components/QueryModal'; import { selectQuery } from './utils/utils'; import pluginJson from './plugin.json'; +import { initPluginTranslations } from '@grafana/i18n'; + +await initPluginTranslations(pluginJson.id); export const plugin = new AppPlugin<{}>() .setRootPage(App) diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/package.json b/e2e-playwright/test-plugins/grafana-extensionstest-app/package.json index f89721aaac9..7f094c82b9b 100644 --- a/e2e-playwright/test-plugins/grafana-extensionstest-app/package.json +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/package.json @@ -6,7 +6,8 @@ "build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production", "dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development", "typecheck": "tsc --noEmit", - "lint": "eslint --cache --ignore-path ./.gitignore --ext .js,.jsx,.ts,.tsx ." + "lint": "eslint --cache --ignore-path ./.gitignore --ext .js,.jsx,.ts,.tsx .", + "i18n-extract": "i18next-cli extract --sync-primary" }, "author": "Grafana Labs", "license": "Apache-2.0", @@ -20,17 +21,19 @@ "@types/semver": "7.5.8", "@types/uuid": "9.0.8", "glob": "10.5.0", + "i18next-cli": "^1.24.22", "ts-node": "10.9.2", "typescript": "5.5.4", "webpack": "5.95.0", "webpack-merge": "5.10.0" }, "engines": { - "node": ">=20" + "node": ">= 22 <25" }, "dependencies": { "@emotion/css": "11.11.2", "@grafana/data": "workspace:*", + "@grafana/i18n": "workspace:*", "@grafana/runtime": "workspace:*", "@grafana/schema": "workspace:*", "@grafana/ui": "workspace:*", @@ -42,5 +45,6 @@ }, "peerDependencies": { "@grafana/runtime": "*" - } + }, + "packageManager": "yarn@4.11.0" } diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/pages/Config.tsx b/e2e-playwright/test-plugins/grafana-extensionstest-app/pages/Config.tsx new file mode 100644 index 00000000000..8b31e490242 --- /dev/null +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/pages/Config.tsx @@ -0,0 +1,17 @@ +import { Trans } from '@grafana/i18n'; +import { PluginPage } from '@grafana/runtime'; +import { Stack } from '@grafana/ui'; + +export function Config() { + return ( + + +
+

+ Is this translated +

+
+
+
+ ); +} diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/pages/index.tsx b/e2e-playwright/test-plugins/grafana-extensionstest-app/pages/index.tsx index 1326d3c7bdf..84ddfc8e6ea 100644 --- a/e2e-playwright/test-plugins/grafana-extensionstest-app/pages/index.tsx +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/pages/index.tsx @@ -1,3 +1,4 @@ export { ExposedComponents } from './ExposedComponents'; export { AddedComponents } from './AddedComponents'; export { AddedLinks } from './AddedLinks'; +export { Config } from './Config'; diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/plugin.json b/e2e-playwright/test-plugins/grafana-extensionstest-app/plugin.json index 3f5adfa215a..c5ce29f2dc4 100644 --- a/e2e-playwright/test-plugins/grafana-extensionstest-app/plugin.json +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/plugin.json @@ -82,10 +82,11 @@ ] }, "dependencies": { - "grafanaDependency": ">=10.4.0", + "grafanaDependency": ">=12.0.0", "plugins": [], "extensions": { "exposedComponents": ["grafana-extensionexample1-app/reusable-component/v1", "grafana/add-to-dashboard-form/v1"] } - } + }, + "languages": ["en-US", "es-ES", "sv-SE"] } diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/tests/translations/french.spec.ts b/e2e-playwright/test-plugins/grafana-extensionstest-app/tests/translations/french.spec.ts new file mode 100644 index 00000000000..a991453b0cc --- /dev/null +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/tests/translations/french.spec.ts @@ -0,0 +1,12 @@ +import { FRENCH_FRANCE } from '@grafana/i18n'; +import { expect, test } from '@grafana/plugin-e2e'; +import pluginJson from '../../plugin.json'; +import { ROUTES } from '../../constants'; + +test.use({ userPreferences: { language: FRENCH_FRANCE } }); + +test('should display default translation (en-US)', async ({ gotoAppPage }) => { + const configPage = await gotoAppPage({ pluginId: pluginJson.id, path: ROUTES.Config }); + + await expect(configPage.ctx.page.getByText('Is this translated')).toBeVisible(); +}); diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/tests/translations/swedish.spec.ts b/e2e-playwright/test-plugins/grafana-extensionstest-app/tests/translations/swedish.spec.ts new file mode 100644 index 00000000000..404f5053948 --- /dev/null +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/tests/translations/swedish.spec.ts @@ -0,0 +1,12 @@ +import { SWEDISH_SWEDEN } from '@grafana/i18n'; +import { expect, test } from '@grafana/plugin-e2e'; +import pluginJson from '../../plugin.json'; +import { ROUTES } from '../../constants'; + +test.use({ userPreferences: { language: SWEDISH_SWEDEN } }); + +test('should display correct translation', async ({ gotoAppPage }) => { + const configPage = await gotoAppPage({ pluginId: pluginJson.id, path: ROUTES.Config }); + + await expect(configPage.ctx.page.getByText('Det här är översatt')).toBeVisible(); +}); diff --git a/e2e-playwright/test-plugins/grafana-extensionstest-app/webpack.config.ts b/e2e-playwright/test-plugins/grafana-extensionstest-app/webpack.config.ts index 564555396a5..ceff913dbba 100644 --- a/e2e-playwright/test-plugins/grafana-extensionstest-app/webpack.config.ts +++ b/e2e-playwright/test-plugins/grafana-extensionstest-app/webpack.config.ts @@ -34,6 +34,7 @@ const config = async (env: Env): Promise => { ], }), ], + externals: [...(baseConfig.externals as any), 'i18next'], }; return mergeWithCustomize({ diff --git a/e2e-playwright/test-plugins/grafana-test-datasource/components/ConfigEditor.tsx b/e2e-playwright/test-plugins/grafana-test-datasource/components/ConfigEditor.tsx index 2c46992a5d9..06101e6e050 100644 --- a/e2e-playwright/test-plugins/grafana-test-datasource/components/ConfigEditor.tsx +++ b/e2e-playwright/test-plugins/grafana-test-datasource/components/ConfigEditor.tsx @@ -1,6 +1,7 @@ import { ChangeEvent } from 'react'; import { Checkbox, InlineField, InlineSwitch, Input, SecretInput, Select } from '@grafana/ui'; import { DataSourcePluginOptionsEditorProps, SelectableValue, toOption } from '@grafana/data'; +import { t } from '@grafana/i18n'; import { MyDataSourceOptions, MySecureJsonData } from '../types'; interface Props extends DataSourcePluginOptionsEditorProps {} @@ -45,36 +46,46 @@ export function ConfigEditor(props: Props) { return ( <> - + ) => onJsonDataChange('path', e.target.value)} value={jsonData.path} - placeholder="Enter the path, e.g. /api/v1" + placeholder={t('config-editor.path.placeholder', 'Enter the path, e.g. /api/v1')} width={40} /> - + ) => onSecureJsonDataChange('path', e.target.value)} /> - + ) => onJsonDataChange('switchEnabled', e.target.checked)} /> - + ) => onJsonDataChange('checkboxEnabled', e.target.checked)} /> - + - - - - - {!ds?.meta.annotations && ( - - - The selected data source does not support annotations. Please select a different data source. - - - )} - - - - - - - - - - - - - <> - - {panelFilter !== PanelFilterType.AllPanels && ( - annotation.filter?.ids.includes(panel.value!))} - onChange={onAddFilterPanelID} - isClearable={true} - placeholder={t('dashboard-scene.annotation-settings-edit.placeholder-choose-panels', 'Choose panels')} - width={100} - closeMenuOnSelect={false} - className={styles.select} - data-testid={selectors.components.Annotations.annotationsChoosePanelInput} - /> + + + {/* Data source */} + + + + {!ds?.meta.annotations && ( + + + The selected data source does not support annotations. Please select a different data source. + + + )} + + {/* Enabled */} + - + > + + + + {/* Color */} + + + + + + + {/* Annotation controls display */} + + + + + {/* Show in */} + + <> + - - - + + + {/* Type */} + + - - - - - - + + + {/* Tooltip */} + + + + + {/* Icon */} + + - + + render={({ field: { ref, value, onChange, ...field } }) => ( + {inputs.dataSources && inputs.dataSources.map((input: DataSourceInput) => { if (input.pluginId === ExpressionDatasourceRef.type) { @@ -102,6 +100,7 @@ export const ImportDashboardFormV2 = ({ key={input.pluginId} invalid={!!errors[dataSourceOption]} error={errors[dataSourceOption] ? 'Please select a data source' : undefined} + noMargin > name={dataSourceOption} @@ -133,7 +132,7 @@ export const ImportDashboardFormV2 = ({ ); })} - + - + ); }; diff --git a/public/app/features/dashboard-scene/v2schema/ImportDashboardOverviewV2.tsx b/public/app/features/dashboard-scene/v2schema/ImportDashboardOverviewV2.tsx index 9f87a602d3f..e71b419b8e4 100644 --- a/public/app/features/dashboard-scene/v2schema/ImportDashboardOverviewV2.tsx +++ b/public/app/features/dashboard-scene/v2schema/ImportDashboardOverviewV2.tsx @@ -1,5 +1,3 @@ -import { useState } from 'react'; - import { locationUtil } from '@grafana/data'; import { locationService, reportInteraction } from '@grafana/runtime'; import { @@ -20,7 +18,6 @@ const IMPORT_FINISHED_EVENT_NAME = 'dashboard_import_imported'; type FormData = SaveDashboardCommand & { [key: `datasource-${string}`]: string }; export function ImportDashboardOverviewV2() { - const [uidReset, setUidReset] = useState(false); const dispatch = useDispatch(); // Get state from Redux store @@ -29,10 +26,6 @@ export function ImportDashboardOverviewV2() { const inputs = useSelector((state: StoreState) => state.importDashboard.inputs); const folder = searchObj.folderUid ? { uid: String(searchObj.folderUid) } : { uid: '' }; - function onUidReset() { - setUidReset(true); - } - function onCancel() { dispatch(clearLoadedDashboard()); } @@ -180,7 +173,7 @@ export function ImportDashboardOverviewV2() { <> onSubmit={onSubmit} - defaultValues={{ dashboard, k8s: { annotations: { 'grafana.app/folder': folder.uid } } }} + defaultValues={{ dashboard, folderUid: folder.uid, k8s: { annotations: { 'grafana.app/folder': folder.uid } } }} validateOnMount validateOn="onChange" > @@ -191,9 +184,7 @@ export function ImportDashboardOverviewV2() { errors={errors} control={control} getValues={getValues} - uidReset={uidReset} onCancel={onCancel} - onUidReset={onUidReset} onSubmit={onSubmit} watch={watch} /> diff --git a/public/app/features/dashboard/api/ResponseTransformers.ts b/public/app/features/dashboard/api/ResponseTransformers.ts index a892baf283e..867d5bb8ea5 100644 --- a/public/app/features/dashboard/api/ResponseTransformers.ts +++ b/public/app/features/dashboard/api/ResponseTransformers.ts @@ -499,7 +499,11 @@ export function getDefaultDatasource(): DataSourceRef { export function getPanelQueries(targets: DataQuery[], panelDatasource: DataSourceRef): PanelQueryKind[] | undefined { return targets.map((t) => { const { refId, hide, datasource, ...query } = t; - const ds = t.datasource || panelDatasource; + // Check if target datasource is empty object {} (no keys), treat it as missing + // and fall through to use panel datasource (matches backend behavior) + const targetDs = t.datasource; + const isEmptyDatasourceObject = targetDs && typeof targetDs === 'object' && Object.keys(targetDs).length === 0; + const ds = isEmptyDatasourceObject ? panelDatasource : targetDs || panelDatasource; const q: PanelQueryKind = { kind: 'PanelQuery', spec: { @@ -525,7 +529,8 @@ export function getPanelQueries(targets: DataQuery[], panelDatasource: DataSourc } export function buildPanelKind(p: Panel): PanelKind { - const queries = getPanelQueries((p.targets as unknown as DataQuery[]) || [], p.datasource ?? { type: '', uid: '' }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions + const queries = getPanelQueries((p.targets as any) || [], p.datasource ?? { type: '', uid: '' }); const transformations = getPanelTransformations(p.transformations || []); @@ -541,10 +546,13 @@ export function buildPanelKind(p: Panel): PanelKind { } // match backend conversion behavior + // Only set first threshold step value to null if it's explicitly null or undefined + // Preserve 0 values (0 is falsy but should be kept as 0, not converted to null) if ( fieldConfig.defaults.thresholds?.steps && fieldConfig.defaults.thresholds.steps.length > 0 && - !fieldConfig.defaults.thresholds.steps[0]?.value + (fieldConfig.defaults.thresholds.steps[0]?.value === null || + fieldConfig.defaults.thresholds.steps[0]?.value === undefined) ) { fieldConfig.defaults.thresholds.steps[0]!.value = null; } diff --git a/public/app/features/dashboard/api/v1.ts b/public/app/features/dashboard/api/v1.ts index c69093258cb..e43b8944079 100644 --- a/public/app/features/dashboard/api/v1.ts +++ b/public/app/features/dashboard/api/v1.ts @@ -139,6 +139,13 @@ export class K8sDashboardAPI implements DashboardAPI { version: dash.metadata.generation, created: dash.metadata.creationTimestamp, publicDashboardEnabled: dash.access.isPublic, + conversionStatus: dash.status?.conversion + ? { + storedVersion: dash.status.conversion.storedVersion, + failed: dash.status.conversion.failed, + error: dash.status.conversion.error, + } + : undefined, }, dashboard: { ...dash.spec, diff --git a/public/app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor.tsx b/public/app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor.tsx index 570461c3921..14de02d3c68 100644 --- a/public/app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor.tsx @@ -16,7 +16,7 @@ export interface OptionsPaneItemInfo { value?: any; description?: string; popularRank?: number; - render: (descriptor: OptionsPaneItemDescriptor) => React.ReactElement; + render: (descriptor: OptionsPaneItemDescriptor) => React.ReactElement>; skipField?: boolean; showIf?: () => boolean; /** Hook for controlling visibility */ diff --git a/public/app/features/dashboard/containers/DashboardPage.test.tsx b/public/app/features/dashboard/containers/DashboardPage.test.tsx index 9a51d8c4cd9..b1ae5811f24 100644 --- a/public/app/features/dashboard/containers/DashboardPage.test.tsx +++ b/public/app/features/dashboard/containers/DashboardPage.test.tsx @@ -85,7 +85,7 @@ const mockCleanUpDashboardAndVariables = jest.fn(); function setup(propOverrides?: Partial) { config.bootData.navTree = [ { text: 'Dashboards', id: 'dashboards/browse' }, - { text: 'Home', id: HOME_NAV_ID }, + { text: 'Home', id: HOME_NAV_ID, url: '/' }, { text: 'Help', id: 'help', @@ -101,9 +101,9 @@ function setup(propOverrides?: Partial) { 'dashboards/browse': { text: 'Dashboards', id: 'dashboards/browse', - parentItem: { text: 'Home', id: HOME_NAV_ID }, + parentItem: { text: 'Home', id: HOME_NAV_ID, url: '/' }, }, - [HOME_NAV_ID]: { text: 'Home', id: HOME_NAV_ID }, + [HOME_NAV_ID]: { text: 'Home', id: HOME_NAV_ID, url: '/' }, }, initPhase: DashboardInitPhase.NotStarted, initError: null, diff --git a/public/app/features/dashboard/containers/DashboardPageProxy.test.tsx b/public/app/features/dashboard/containers/DashboardPageProxy.test.tsx index e26b1099d2d..5083affcf22 100644 --- a/public/app/features/dashboard/containers/DashboardPageProxy.test.tsx +++ b/public/app/features/dashboard/containers/DashboardPageProxy.test.tsx @@ -1,4 +1,4 @@ -import { act, screen, waitFor } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; import { useParams } from 'react-router-dom-v5-compat'; import { Props } from 'react-virtualized-auto-sizer'; import { render } from 'test/test-utils'; @@ -120,10 +120,8 @@ describe('DashboardPageProxy', () => { it('home dashboard', async () => { getDashboardScenePageStateManager().setDashboardCache(HOME_DASHBOARD_CACHE_KEY, dashMock); - act(() => { - setup({ - route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' }, - }); + setup({ + route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' }, }); await waitFor(() => { @@ -134,11 +132,9 @@ describe('DashboardPageProxy', () => { it('uid dashboard', async () => { getDashboardScenePageStateManager().setDashboardCache('abc-def', dashMock); - act(() => { - setup({ - route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' }, - uid: 'abc-def', - }); + setup({ + route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' }, + uid: 'abc-def', }); await waitFor(() => { @@ -156,11 +152,9 @@ describe('DashboardPageProxy', () => { describe('when user can edit a dashboard ', () => { it('should not render DashboardScenePage if route is Home', async () => { getDashboardScenePageStateManager().setDashboardCache(HOME_DASHBOARD_CACHE_KEY, homeMockEditable); - act(() => { - setup({ - route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' }, - uid: '', - }); + setup({ + route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' }, + uid: '', }); await waitFor(() => { @@ -170,11 +164,9 @@ describe('DashboardPageProxy', () => { it('should not render DashboardScenePage if route is Normal and has uid', async () => { getDashboardScenePageStateManager().setDashboardCache('abc-def', dashMockEditable); - act(() => { - setup({ - route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' }, - uid: 'abc-def', - }); + setup({ + route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' }, + uid: 'abc-def', }); await waitFor(() => { expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(0); @@ -185,11 +177,9 @@ describe('DashboardPageProxy', () => { describe('when user can only view a dashboard ', () => { it('should render DashboardScenePage if route is Home', async () => { getDashboardScenePageStateManager().setDashboardCache(HOME_DASHBOARD_CACHE_KEY, homeMock); - act(() => { - setup({ - route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' }, - uid: '', - }); + setup({ + route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' }, + uid: '', }); await waitFor(() => { @@ -199,11 +189,9 @@ describe('DashboardPageProxy', () => { it('should render DashboardScenePage if route is Normal and has uid', async () => { getDashboardScenePageStateManager().setDashboardCache('uid', dashMock); - act(() => { - setup({ - route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' }, - uid: 'uid', - }); + setup({ + route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' }, + uid: 'uid', }); await waitFor(() => { expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(1); @@ -212,11 +200,9 @@ describe('DashboardPageProxy', () => { it('should render not DashboardScenePage if dashboard UID does not match route UID', async () => { getDashboardScenePageStateManager().setDashboardCache('uid', dashMock); - act(() => { - setup({ - route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' }, - uid: 'wrongUID', - }); + setup({ + route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' }, + uid: 'wrongUID', }); await waitFor(() => { expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(0); diff --git a/public/app/features/dashboard/containers/PublicDashboardPageProxy.test.tsx b/public/app/features/dashboard/containers/PublicDashboardPageProxy.test.tsx index 0bb44738440..495532e5951 100644 --- a/public/app/features/dashboard/containers/PublicDashboardPageProxy.test.tsx +++ b/public/app/features/dashboard/containers/PublicDashboardPageProxy.test.tsx @@ -5,7 +5,7 @@ import { render } from 'test/test-utils'; import { selectors as e2eSelectors } from '@grafana/e2e-selectors'; import { config, locationService } from '@grafana/runtime'; import { backendSrv } from 'app/core/services/backend_srv'; -import { DashboardRoutes } from 'app/types/dashboard'; +import { DashboardDTO, DashboardRoutes } from 'app/types/dashboard'; import PublicDashboardPageProxy, { PublicDashboardPageProxyProps } from './PublicDashboardPageProxy'; @@ -56,8 +56,7 @@ describe('PublicDashboardPageProxy', () => { // Mock the dashboard UID response so we don't get any refused connection errors // from this test (as the fetch polyfill means this logic would actually try and call the API) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - jest.spyOn(backendSrv, 'getPublicDashboardByUid').mockResolvedValue({ dashboard: {}, meta: {} } as any); + jest.spyOn(backendSrv, 'getPublicDashboardByUid').mockResolvedValue({ dashboard: {}, meta: {} } as DashboardDTO); }); describe('when scene feature enabled', () => { diff --git a/public/app/features/dashboard/services/DashboardAnalyticsAggregator.ts b/public/app/features/dashboard/services/DashboardAnalyticsAggregator.ts index 8671c2b13e5..a36e42c702c 100644 --- a/public/app/features/dashboard/services/DashboardAnalyticsAggregator.ts +++ b/public/app/features/dashboard/services/DashboardAnalyticsAggregator.ts @@ -196,6 +196,39 @@ export class DashboardAnalyticsAggregator implements performanceUtils.ScenePerfo return panel; } + /** + * Send panel_render interactions for each panel with aggregated metrics + */ + private sendPanelRenderInteractions(data: performanceUtils.DashboardInteractionCompleteData): void { + const panelMetrics = this.getPanelMetrics(); + + panelMetrics.forEach((panel) => { + const totalPanelTime = + panel.totalQueryTime + + panel.totalTransformationTime + + panel.totalRenderTime + + panel.totalFieldConfigTime + + panel.pluginLoadTime; + + // logMeasurement requires numeric values in second parameter, metadata in third + const measurementValues = { + totalTime: Math.round(totalPanelTime * 10) / 10, + queryCount: panel.queryOperations.length, + transformCount: panel.transformationOperations.length, + renderCount: panel.renderOperations.length, + fieldConfigCount: panel.fieldConfigOperations.length, + pluginLoadCount: panel.pluginLoadTime > 0 ? 1 : 0, + }; + + logMeasurement('panel_render', measurementValues, { + panelKey: panel.panelKey, + pluginId: panel.pluginId, + panelId: panel.panelId, + operationId: data.operationId, // Shared operationId for correlating with dashboard_render + }); + }); + } + /** * Send analytics report for dashboard interactions */ @@ -218,6 +251,7 @@ export class DashboardAnalyticsAggregator implements performanceUtils.ScenePerfo reportInteraction('dashboard_render', { interactionType: data.interactionType, uid: this.dashboardUID, + operationId: data.operationId, // OperationId for correlating with panel_render interactions ...payload, }); @@ -225,7 +259,11 @@ export class DashboardAnalyticsAggregator implements performanceUtils.ScenePerfo interactionType: data.interactionType, dashboard: this.dashboardUID, title: this.dashboardTitle, + operationId: data.operationId, // OperationId for correlating with panel_render interactions }); + + // Send individual panel_render interactions + this.sendPanelRenderInteractions(data); } /** @@ -351,6 +389,37 @@ export class DashboardAnalyticsAggregator implements performanceUtils.ScenePerfo }); } + // Panel render interactions summary + if (panelMetrics && panelMetrics.length > 0) { + writePerformanceGroupStart('DAA', `📤 Panel render interactions: ${panelMetrics.length} panels reported`); + + panelMetrics.forEach((panel) => { + const totalPanelTime = + panel.totalQueryTime + + panel.totalTransformationTime + + panel.totalRenderTime + + panel.totalFieldConfigTime + + panel.pluginLoadTime; + + const isSlowPanel = totalPanelTime > SLOW_OPERATION_THRESHOLD_MS; + + writePerformanceGroupLog('DAA', `🎨 ${panel.pluginId}-${panel.panelId}:`, { + totalTime: Math.round(totalPanelTime * 10) / 10, + operations: { + queries: panel.queryOperations.length, + transforms: panel.transformationOperations.length, + renders: panel.renderOperations.length, + fieldConfigs: panel.fieldConfigOperations.length, + pluginLoads: panel.pluginLoadTime > 0 ? 1 : 0, + }, + isSlowPanel: isSlowPanel, + ...(isSlowPanel && { warning: 'SLOW' }), + }); + }); + + writePerformanceGroupEnd(); + } + writePerformanceGroupEnd(); } } diff --git a/public/app/features/dashboard/services/dashboard-render-performance-profiling.md b/public/app/features/dashboard/services/dashboard-render-performance-profiling.md index cbef48d7411..c34fb109e39 100644 --- a/public/app/features/dashboard/services/dashboard-render-performance-profiling.md +++ b/public/app/features/dashboard/services/dashboard-render-performance-profiling.md @@ -109,10 +109,16 @@ const payload = { reportInteraction('dashboard_render', { interactionType: e.origin, uid, + operationId: e.operationId, // Shared operationId for correlating with panel_render measurements ...payload, }); -logMeasurement(`dashboard_render`, payload, { interactionType: e.origin, dashboard: uid, title: title }); +logMeasurement('dashboard_render', payload, { + interactionType: e.origin, + dashboard: uid, + title: title, + operationId: e.operationId, // Shared operationId for correlating with panel_render measurements +}); ``` ### Interaction Origin Mapping @@ -301,6 +307,7 @@ Aggregates panel-level performance metrics for analytics reporting: - Tracks operation counts and total time spent per panel - Sends comprehensive analytics reports via `reportInteraction` and `logMeasurement` - Provides detailed panel breakdowns including slow panel detection +- Sends individual `panel_render` measurements for each panel with aggregated metrics via `logMeasurement` #### ScenePerformanceLogger @@ -344,6 +351,7 @@ Reported for each interaction via `reportInteraction` and `logMeasurement`: { interactionType: string, // Type of interaction uid: string, // Dashboard UID + operationId: string, // Unique operationId for correlating with panel_render measurements duration: number, // Total duration networkDuration: number, // Network time processingTime: number, // Client-side processing time @@ -358,6 +366,8 @@ Reported for each interaction via `reportInteraction` and `logMeasurement`: } ``` +**Correlation**: The `operationId` field is shared between `dashboard_render` and all associated `panel_render` measurements, enabling correlation of panel metrics with their parent dashboard interaction. + #### Panel-Level Metrics Aggregated by `DashboardAnalyticsAggregator` for each panel with detailed operation tracking: @@ -406,6 +416,44 @@ Aggregated by `DashboardAnalyticsAggregator` for each panel with detailed operat } ``` +#### Panel Render Measurements + +For each dashboard interaction, individual `panel_render` measurements are sent separately from `dashboard_render` via `logMeasurement`. These measurements are sent for all panels with collected metrics (even if all times are 0), providing granular panel-level analytics. + +**When sent**: After `dashboard_render` interaction, one `panel_render` measurement per panel + +**Correlation**: All `panel_render` measurements share the same `operationId` as their parent `dashboard_render` interaction, enabling correlation between dashboard and panel-level metrics. + +**Measurement values** (via `logMeasurement`): + +```typescript +{ + totalTime: number, // Sum of all operation times + queryCount: number, // Number of query operations + transformCount: number, // Number of transformation operations + renderCount: number, // Number of render operations + fieldConfigCount: number, // Number of field config operations + pluginLoadCount: number // Number of plugin load operations (0 or 1) +} +``` + +**Measurement metadata** (via `logMeasurement` context): + +```typescript +{ + panelKey: string, // Panel key identifier + pluginId: string, // Panel plugin identifier + panelId: string, // Panel identifier + operationId: string // Shared operationId for correlating with dashboard_render +} +``` + +**Note**: `dashboard`, `title`, and `interactionType` are not included in `panel_render` metadata since they can be obtained by correlating with the parent `dashboard_render` interaction using `operationId`. + +**Correlating panel_render with dashboard_render**: + +All `panel_render` measurements share the same `operationId` as their parent `dashboard_render` interaction. + ## Debugging and Development ### Enable Performance Debug Logging @@ -500,7 +548,6 @@ DAA: [ANALYTICS] dashboard_view | 4 panels analyzed | 1 slow panels ⚠️ transform: 12.3, render: 23.8, fieldConfig: 5.0, - pluginLoad: 39.0 } } DAA: 📊 Queries: { @@ -526,6 +573,59 @@ DAA: [ANALYTICS] dashboard_view | 4 panels analyzed | 1 slow panels ⚠️ **Note**: The indentation shows the **console group hierarchy**. In the browser console, each panel creates a collapsible group that can be expanded to see detailed operation breakdowns. The main dashboard analytics group contains nested panel groups for organized analysis. +#### Panel Render Measurements Summary + +After the detailed panel breakdown, a summary of all `panel_render` measurements sent is displayed: + +``` +DAA: 📤 Panel render interactions: 4 panels reported + DAA: 🎨 timeseries-panel-1: { + totalTime: 125.3, + operations: { + queries: 2, + transforms: 1, + renders: 1, + fieldConfigs: 1, + pluginLoads: 1 + }, + isSlowPanel: true, + warning: "SLOW" + } + DAA: 🎨 stat-panel-2: { + totalTime: 45.2, + operations: { + queries: 1, + transforms: 0, + renders: 1, + fieldConfigs: 1, + pluginLoads: 0 + }, + isSlowPanel: false + } + DAA: 🎨 table-panel-3: { + totalTime: 89.7, + operations: { + queries: 1, + transforms: 2, + renders: 1, + fieldConfigs: 1 + }, + isSlowPanel: false + } + DAA: 🎨 graph-panel-4: { + totalTime: 234.1, + operations: { + queries: 3, + transforms: 1, + renders: 2, + fieldConfigs: 1 + }, + isSlowPanel: false + } +``` + +This summary provides a quick overview of all panels that had `panel_render` measurements sent, showing total time, operation counts, and slow panel warnings. + ### Enable Echo Service Debug Logging To observe Echo events in the browser console: diff --git a/public/app/features/dashboard/state/DashboardMigrator.ts b/public/app/features/dashboard/state/DashboardMigrator.ts index b6e9634da87..7355f7575b7 100644 --- a/public/app/features/dashboard/state/DashboardMigrator.ts +++ b/public/app/features/dashboard/state/DashboardMigrator.ts @@ -49,7 +49,8 @@ import { } from 'app/features/transformers/timeSeriesTable/timeSeriesTableTransformer'; import { isConstant, isMulti } from 'app/features/variables/guard'; import { alignCurrentWithMulti } from 'app/features/variables/shared/multiOptions'; -import { CloudWatchMetricsQuery, LegacyAnnotationQuery } from 'app/plugins/datasource/cloudwatch/types'; +import { CloudWatchMetricsQuery } from 'app/plugins/datasource/cloudwatch/dataquery.gen'; +import { LegacyAnnotationQuery } from 'app/plugins/datasource/cloudwatch/types'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; import { diff --git a/public/app/features/datasources/components/CloudInfoBox.tsx b/public/app/features/datasources/components/CloudInfoBox.tsx index 9982973f4d4..3fa29d4a7bc 100644 --- a/public/app/features/datasources/components/CloudInfoBox.tsx +++ b/public/app/features/datasources/components/CloudInfoBox.tsx @@ -10,8 +10,7 @@ export interface Props { } export function CloudInfoBox({ dataSource }: Props) { - let mainDS = ''; - let extraDS = ''; + let dsName = ''; // don't show for already configured data sources or provisioned data sources if (dataSource.readOnly || (dataSource.version ?? 0) > 2) { @@ -25,12 +24,16 @@ export function CloudInfoBox({ dataSource }: Props) { switch (dataSource.type) { case 'prometheus': - mainDS = 'Prometheus'; - extraDS = 'Loki'; + dsName = 'Prometheus'; break; case 'loki': - mainDS = 'Loki'; - extraDS = 'Prometheus'; + dsName = 'Loki'; + break; + case 'tempo': + dsName = 'Tempo'; + break; + case 'grafana-pyroscope-datasource': + dsName = 'Pyroscope'; break; default: return null; @@ -44,8 +47,8 @@ export function CloudInfoBox({ dataSource }: Props) { } return ( - Or skip the effort and get {{ mainDS }} (and {{ extraDS }}) as fully-managed, scalable, and hosted data - sources from Grafana Labs with the{' '} + Or skip the effort and get {{ dsName }} as fully-managed, scalable, and hosted data source from Grafana + Labs with the{' '} - {`${ds.meta.name} + {`${ds.meta.name} ); diff --git a/public/app/features/datasources/components/picker/DataSourceLogo.tsx b/public/app/features/datasources/components/picker/DataSourceLogo.tsx index c8bfcc4601d..69c43bc2898 100644 --- a/public/app/features/datasources/components/picker/DataSourceLogo.tsx +++ b/public/app/features/datasources/components/picker/DataSourceLogo.tsx @@ -20,7 +20,7 @@ export function DataSourceLogo(props: DataSourceLogoProps) { {`${dataSource.meta.name} ); } diff --git a/public/app/features/explore/Explore.tsx b/public/app/features/explore/Explore.tsx index 39c5b09dc6c..9aa7bc1904b 100644 --- a/public/app/features/explore/Explore.tsx +++ b/public/app/features/explore/Explore.tsx @@ -410,7 +410,7 @@ export class Explore extends PureComponent { } renderTablePanel(width: number) { - const { exploreId, timeZone } = this.props; + const { exploreId, timeZone, eventBus } = this.props; return ( { onCellFilterAdded={this.onCellFilterAdded} timeZone={timeZone} splitOpenFn={this.onSplitOpen('table')} + eventBus={eventBus} /> ); diff --git a/public/app/features/explore/Logs/Logs.test.tsx b/public/app/features/explore/Logs/Logs.test.tsx index 93836280762..d00412560ee 100644 --- a/public/app/features/explore/Logs/Logs.test.tsx +++ b/public/app/features/explore/Logs/Logs.test.tsx @@ -75,6 +75,7 @@ describe('Logs', () => { Object.defineProperty(window, 'location', { value: { href: 'http://localhost:3000/explore?test', + search: '?test', }, writable: true, }); diff --git a/public/app/features/explore/Logs/Logs.tsx b/public/app/features/explore/Logs/Logs.tsx index 7fed4aa6cf2..84470d73a61 100644 --- a/public/app/features/explore/Logs/Logs.tsx +++ b/public/app/features/explore/Logs/Logs.tsx @@ -83,6 +83,7 @@ import LogsNavigation from './LogsNavigation'; import { LogsTableWrap, getLogsTableHeight } from './LogsTableWrap'; import { LogsVolumePanelList } from './LogsVolumePanelList'; import { SETTING_KEY_ROOT, SETTINGS_KEYS, visualisationTypeKey } from './utils/logs'; +import { getExploreBaseUrl } from './utils/url'; interface Props extends Themeable2 { width: number; @@ -308,6 +309,8 @@ const UnthemedLogs: React.FunctionComponent = (props: Props) => { refId: undefined, displayedFields: undefined, sortOrder: undefined, + tableSortBy: undefined, + tableSortDir: undefined, }) ); }); @@ -324,6 +327,8 @@ const UnthemedLogs: React.FunctionComponent = (props: Props) => { labelFieldName: logsPanelState.labelFieldName, refId: logsPanelState.refId ?? panelState?.logs?.refId, displayedFields: logsPanelState.displayedFields ?? panelState?.logs?.displayedFields, + tableSortBy: logsPanelState.tableSortBy ?? panelState?.logs?.tableSortBy, + tableSortDir: logsPanelState.tableSortDir ?? panelState?.logs?.tableSortDir, }) ); } @@ -334,6 +339,8 @@ const UnthemedLogs: React.FunctionComponent = (props: Props) => { panelState?.logs?.columns, panelState?.logs?.displayedFields, panelState?.logs?.refId, + panelState?.logs?.tableSortBy, + panelState?.logs?.tableSortDir, visualisationType, ] ); @@ -611,7 +618,7 @@ const UnthemedLogs: React.FunctionComponent = (props: Props) => { // append changed urlState to baseUrl const serializedState = serializeStateToUrlParam(urlState); - const baseUrl = /.*(?=\/explore)/.exec(`${window.location.href}`)![0]; + const baseUrl = getExploreBaseUrl(); const url = urlUtil.renderUrl(`${baseUrl}/explore`, { left: serializedState }); await createAndCopyShortLink(url); @@ -996,6 +1003,10 @@ const UnthemedLogs: React.FunctionComponent = (props: Props) => { panelState={panelState?.logs} updatePanelState={updatePanelState} datasourceType={props.datasourceType} + displayedFields={displayedFields} + exploreId={props.exploreId} + absoluteRange={props.absoluteRange} + logRows={props.logRows} /> )} @@ -1050,6 +1061,8 @@ const UnthemedLogs: React.FunctionComponent = (props: Props) => { onLogOptionsChange={onLogOptionsChange} filterLevels={filterLevels} timeRange={props.range} + exploreId={props.exploreId} + absoluteRange={props.absoluteRange} /> )} diff --git a/public/app/features/explore/Logs/LogsTable.test.tsx b/public/app/features/explore/Logs/LogsTable.test.tsx index 2c9cdedb95a..cb38e9062de 100644 --- a/public/app/features/explore/Logs/LogsTable.test.tsx +++ b/public/app/features/explore/Logs/LogsTable.test.tsx @@ -1,7 +1,7 @@ -import { render, screen, waitFor } from '@testing-library/react'; +import { render, screen, waitFor, fireEvent } from '@testing-library/react'; import { ComponentProps } from 'react'; -import { DataFrame, FieldType, LogsSortOrder, toUtc } from '@grafana/data'; +import { DataFrame, FieldType, LogsSortOrder, toUtc, urlUtil } from '@grafana/data'; import { mockTransformationsRegistry, organizeFieldsTransformer } from '@grafana/data/internal'; import { config } from '@grafana/runtime'; import { extractFieldsTransformer } from 'app/features/transformers/extractFields/extractFields'; @@ -301,4 +301,141 @@ describe('LogsTable', () => { }); }); }); + + describe('Sort persistence', () => { + it('should update URL with sort parameters when sort changes', async () => { + // Mock onSortByChange to update URL (simulating parent Explore component behavior) + const onSortByChange = jest.fn((sortBy) => { + const mockUrl = new URL(window.location.href); + if (sortBy && sortBy.length > 0) { + mockUrl.searchParams.set('tableSortBy', sortBy[0].displayName); + mockUrl.searchParams.set('tableSortDir', sortBy[0].desc ? 'desc' : 'asc'); + } else { + // Remove sort params if no sort is applied + mockUrl.searchParams.delete('tableSortBy'); + mockUrl.searchParams.delete('tableSortDir'); + } + window.history.replaceState({}, '', mockUrl.toString()); + }); + + setup({ + tableSortBy: 'Time', + tableSortDir: 'desc', + onSortByChange, + columnsWithMeta: { + Time: { active: true, percentOfLinesWithLabel: 3, index: 0 }, + line: { active: true, percentOfLinesWithLabel: 3, index: 1 }, + }, + }); + + await waitFor(() => { + const rows = screen.getAllByRole('row'); + expect(rows.length).toBe(4); + }); + + // Verify the Time column has the sort indicator (arrow down for descending) + const timeColumnHeader = screen.getByRole('columnheader', { name: /Time/i }); + const sortButton = timeColumnHeader.querySelector('button[title="Toggle SortBy"]'); + expect(sortButton).toBeTruthy(); + + // Click to toggle sort (desc -> asc) + if (sortButton) { + fireEvent.click(sortButton); + } + + await waitFor(() => { + expect(onSortByChange).toHaveBeenCalled(); + }); + + // Verify URL was updated (callback was called and URL reflects the new sort state) + const currentUrl = new URL(window.location.href); + const tableSortBy = currentUrl.searchParams.get('tableSortBy'); + const tableSortDir = currentUrl.searchParams.get('tableSortDir'); + + expect(onSortByChange).toHaveBeenCalled(); + + // Verify sort parameters are in URL after clicking + // The mock simulates parent component updating URL with sort state + if (tableSortBy && tableSortDir) { + expect(tableSortBy).toBe('Time'); + expect(tableSortDir).toBe('desc'); + } + }); + }); + + describe('Selected log line', () => { + it('should handle selected log line from URL parameter', async () => { + // Use getMockLokiFrame which has proper structure with id field + const testFrame = getMockLokiFrame(); + const logsFrame = parseLogsFrame(testFrame); + + // Get the second ID from the parsed frame to test selection of non-first row + const secondId = logsFrame?.idField?.values[1]; + + // Mock URL search params to include selectedLine + const mockGetSearchParams = jest.spyOn(urlUtil, 'getUrlSearchParams'); + mockGetSearchParams.mockReturnValue({ + selectedLine: JSON.stringify({ id: secondId, row: 1 }), + }); + + // Verify selectedLine is in the mocked URL params + const params = urlUtil.getUrlSearchParams(); + expect(params.selectedLine).toBeDefined(); + expect(params.selectedLine).toContain(secondId); + }); + + it('should clear selectedLine URL parameter after render', async () => { + // Mock locationService.partial instead of window.history.replaceState + const partialSpy = jest.spyOn(require('@grafana/runtime').locationService, 'partial'); + + // Use getMockLokiFrame which has proper structure + const testFrame = getMockLokiFrame(); + const logsFrame = parseLogsFrame(testFrame); + + // Get the first ID from the parsed frame + const firstId = logsFrame?.idField?.values[0]; + + // Mock URL search params with matching id + const mockGetSearchParams = jest.spyOn(urlUtil, 'getUrlSearchParams'); + mockGetSearchParams.mockReturnValue({ + selectedLine: JSON.stringify({ id: firstId, row: 0 }), + }); + + setup({ logsFrame }, testFrame); + + await waitFor(() => { + expect(partialSpy).toHaveBeenCalled(); + // Verify that selectedLine is set to undefined + const callArgs = partialSpy.mock.calls[0]; + expect(callArgs[0]).toEqual({ selectedLine: undefined }); + expect(callArgs[1]).toBe(true); // replace parameter + }); + }); + }); + + describe('Table action buttons', () => { + it('should render action buttons in first column when exploreId is provided', async () => { + setup({ + exploreId: 'test-explore', + }); + + await waitFor(() => { + const rows = screen.getAllByRole('row'); + expect(rows.length).toBeGreaterThan(1); // header + data rows + }); + + // Verify buttons are in the first column + const rows = screen.getAllByRole('row'); + const dataRows = rows.filter((row) => row.getAttribute('role') === 'row' && !row.getAttribute('aria-label')); + + dataRows.forEach((row) => { + const cells = row.querySelectorAll('[role="cell"]'); + const firstCell = cells[0]; + + // First cell should contain both action buttons + expect(firstCell.querySelector('button[aria-label="View log line"]')).toBeTruthy(); + expect(firstCell.querySelector('button[aria-label="Copy link to log line"]')).toBeTruthy(); + }); + }); + }); }); diff --git a/public/app/features/explore/Logs/LogsTable.tsx b/public/app/features/explore/Logs/LogsTable.tsx index 7583a3c9b0b..96165ca03be 100644 --- a/public/app/features/explore/Logs/LogsTable.tsx +++ b/public/app/features/explore/Logs/LogsTable.tsx @@ -1,7 +1,9 @@ -import { useCallback, useEffect, useState } from 'react'; +import { css } from '@emotion/css'; +import { useCallback, useEffect, useState, useMemo } from 'react'; import { lastValueFrom } from 'rxjs'; import { + urlUtil, applyFieldOverrides, CustomTransformOperator, DataFrame, @@ -16,14 +18,26 @@ import { TimeRange, transformDataFrame, ValueLinkConfig, + ExploreLogsPanelState, + AbsoluteTimeRange, + LogRowModel, + GrafanaTheme2, } from '@grafana/data'; -import { config } from '@grafana/runtime'; -import { AdHocFilterItem, Table } from '@grafana/ui'; +import { config, locationService } from '@grafana/runtime'; +import { + AdHocFilterItem, + CustomCellRendererProps, + TableSortByFieldState, + Table, + TableCellDisplayMode, + useStyles2, +} from '@grafana/ui'; import { FILTER_FOR_OPERATOR, FILTER_OUT_OPERATOR } from '@grafana/ui/internal'; import { LogsFrame } from 'app/features/logs/logsFrame'; import { getFieldLinksForExplore } from '../utils/links'; +import { LogsTableActionButtons } from './LogsTableActionButtons'; import { FieldNameMeta } from './LogsTableWrap'; interface Props { @@ -38,12 +52,86 @@ interface Props { onClickFilterLabel?: (key: string, value: string, frame?: DataFrame) => void; onClickFilterOutLabel?: (key: string, value: string, frame?: DataFrame) => void; logsFrame: LogsFrame | null; + tableSortBy?: string; + tableSortDir?: 'asc' | 'desc'; + onSortByChange?: (sortBy: TableSortByFieldState[]) => void; + displayedFields?: string[]; + exploreId?: string; + panelState?: ExploreLogsPanelState; + absoluteRange?: AbsoluteTimeRange; + logRows?: LogRowModel[]; } export function LogsTable(props: Props) { - const { timeZone, splitOpen, range, logsSortOrder, width, dataFrame, columnsWithMeta, logsFrame } = props; + const { + timeZone, + splitOpen, + range, + logsSortOrder, + width, + dataFrame, + columnsWithMeta, + logsFrame, + tableSortBy, + tableSortDir, + onSortByChange, + } = props; const [tableFrame, setTableFrame] = useState(undefined); + const [columnWidthMap, setColumnWidthMap] = useState>({}); const timeIndex = logsFrame?.timeField.index; + const styles = useStyles2(getStyles); + + // Extract selected log ID from URL parameter + const selectedLogInfo = useMemo(() => { + const { selectedLine } = urlUtil.getUrlSearchParams(); + + const param = Array.isArray(selectedLine) ? selectedLine[0] : selectedLine; + + if (typeof param !== 'string') { + return undefined; + } + + try { + const { id, row } = JSON.parse(param); + return { id, row }; + } catch (error) { + return undefined; + } + }, []); + + // Set the initial row index based on the selected log ID if selectedLine is present in the URL + const initialRowIndex = useMemo(() => { + if (!selectedLogInfo || !tableFrame || !selectedLogInfo.id) { + return undefined; + } + + // Search through all fields in tableFrame to find the one containing the ID + for (const field of tableFrame.fields) { + const lineIndex = field.values.findIndex((v: unknown) => v === selectedLogInfo.id); + if (lineIndex !== -1) { + return lineIndex; + } + } + + return undefined; + }, [selectedLogInfo, tableFrame]); + + // Clear the selectedLine URL parameter after table loads + useEffect(() => { + if (initialRowIndex !== undefined && tableFrame) { + // Remove selectedLine from URL using locationService (proper Grafana way) + locationService.partial({ selectedLine: undefined }, true); + } + }, [initialRowIndex, tableFrame]); + + const onColumnResize = useCallback((fieldDisplayName: string, width: number) => { + if (width > 0) { + setColumnWidthMap((prev) => ({ + ...prev, + [fieldDisplayName]: width, + })); + } + }, []); const prepareTableFrame = useCallback( (frame: DataFrame): DataFrame => { @@ -66,7 +154,21 @@ export function LogsTable(props: Props) { }, }); // `getLinks` and `applyFieldOverrides` are taken from TableContainer.tsx - for (const field of frameWithOverrides.fields) { + for (const [index, field] of frameWithOverrides.fields.entries()) { + // Hide ID field from visualization (it's only needed for row matching) + if (logsFrame?.idField && (field.name === logsFrame.idField.name || field.name === 'id')) { + field.config = { + ...field.config, + custom: { + ...field.config.custom, + hideFrom: { + ...field.config.custom?.hideFrom, + viz: true, + }, + }, + }; + } + field.getLinks = (config: ValueLinkConfig) => { return getFieldLinksForExplore({ field, @@ -76,13 +178,44 @@ export function LogsTable(props: Props) { dataFrame: sortedFrame!, }); }; + + // For the first field (time), wrap the cell to include action buttons + const isFirstField = index === 0; + field.config = { ...field.config, custom: { inspect: true, filterable: true, // This sets the columns to be filterable - width: getInitialFieldWidth(field), + width: columnWidthMap[field.name] ?? getInitialFieldWidth(field), ...field.config.custom, + cellOptions: isFirstField + ? { + type: TableCellDisplayMode.Custom, + cellComponent: (cellProps: CustomCellRendererProps) => ( + <> + + + {cellProps.field.display?.(cellProps.value).text ?? String(cellProps.value)} + + + ), + } + : field.config.custom?.cellOptions, + headerComponent: isFirstField + ? (headerProps: { defaultContent: React.ReactNode }) => ( +
{headerProps.defaultContent}
+ ) + : field.config.custom?.headerComponent, }, // This sets the individual field value as filterable filterable: isFieldFilterable(field, logsFrame?.bodyField.name ?? '', logsFrame?.timeField.name ?? ''), @@ -94,7 +227,22 @@ export function LogsTable(props: Props) { return frameWithOverrides; }, - [logsSortOrder, timeZone, splitOpen, range, logsFrame?.bodyField.name, logsFrame?.timeField.name, timeIndex] + [ + logsSortOrder, + timeZone, + splitOpen, + range, + columnWidthMap, + logsFrame, + timeIndex, + styles.firstColumnCell, + styles.firstColumnHeader, + props.displayedFields, + props.exploreId, + props.panelState, + props.absoluteRange, + props.logRows, + ] ); useEffect(() => { @@ -112,9 +260,24 @@ export function LogsTable(props: Props) { // Add the label filters to the transformations const transform = getLabelFiltersTransform(labelFilters); if (transform) { + // Ensure ID field is always included for row matching + if (logsFrame?.idField?.name) { + transform.options.includeByName = { + ...transform.options.includeByName, + [logsFrame.idField.name]: true, + }; + } transformations.push(transform); } else { // If no fields are filtered, filter the default fields, so we don't render all columns + // Always include ID field for row matching + const includeByName: Record = { + [logsFrame.bodyField.name]: true, + [logsFrame.timeField.name]: true, + }; + if (logsFrame?.idField?.name) { + includeByName[logsFrame.idField.name] = true; + } transformations.push({ id: 'organize', options: { @@ -122,10 +285,7 @@ export function LogsTable(props: Props) { [logsFrame.bodyField.name]: 0, [logsFrame.timeField.name]: 1, }, - includeByName: { - [logsFrame.bodyField.name]: true, - [logsFrame.timeField.name]: true, - }, + includeByName, }, }); } @@ -146,6 +306,7 @@ export function LogsTable(props: Props) { prepareTableFrame, logsFrame?.bodyField.name, logsFrame?.timeField.name, + logsFrame?.idField?.name, ]); if (!tableFrame) { @@ -167,16 +328,24 @@ export function LogsTable(props: Props) { } }; + // Use persisted sortBy if available, otherwise default to time field based on logsSortOrder + const defaultSortBy: TableSortByFieldState[] = [ + { displayName: logsFrame?.timeField.name || '', desc: logsSortOrder === LogsSortOrder.Descending }, + ]; + const initialSortBy: TableSortByFieldState[] = + tableSortBy && tableSortDir ? [{ displayName: tableSortBy, desc: tableSortDir === 'desc' }] : defaultSortBy; + return ( ); } @@ -263,7 +432,19 @@ function getLabelFiltersTransform(labelFilters: Record) { function getInitialFieldWidth(field: Field): number | undefined { if (field.type === FieldType.time) { - return 200; + return 230; } return undefined; } + +const getStyles = (theme: GrafanaTheme2) => ({ + firstColumnHeader: css({ + display: 'flex', + label: 'wrapper', + marginLeft: theme.spacing(7), + width: '100%', + }), + firstColumnCell: css({ + paddingLeft: theme.spacing(7), + }), +}); diff --git a/public/app/features/explore/Logs/LogsTableActionButtons.tsx b/public/app/features/explore/Logs/LogsTableActionButtons.tsx new file mode 100644 index 00000000000..88e3c1db4ed --- /dev/null +++ b/public/app/features/explore/Logs/LogsTableActionButtons.tsx @@ -0,0 +1,190 @@ +import { css } from '@emotion/css'; +import { useCallback, useState } from 'react'; + +import { + AbsoluteTimeRange, + ExploreLogsPanelState, + GrafanaTheme2, + LogRowModel, + serializeStateToUrlParam, + urlUtil, +} from '@grafana/data'; +import { t } from '@grafana/i18n'; +import { ClipboardButton, CustomCellRendererProps, IconButton, Modal, useTheme2 } from '@grafana/ui'; +import { getLogsPermalinkRange } from 'app/core/utils/shortLinks'; +import { getUrlStateFromPaneState } from 'app/features/explore/hooks/useStateSync'; +import { LogsFrame } from 'app/features/logs/logsFrame'; +import { getState } from 'app/store/store'; + +import { getExploreBaseUrl } from './utils/url'; +interface Props extends CustomCellRendererProps { + logId?: string; + logsFrame?: LogsFrame; + exploreId?: string; + panelState?: ExploreLogsPanelState; + displayedFields?: string[]; + absoluteRange?: AbsoluteTimeRange; + logRows?: LogRowModel[]; + index?: number; +} + +export function LogsTableActionButtons(props: Props) { + const { exploreId, absoluteRange, logRows, rowIndex, panelState, displayedFields, logsFrame, frame } = props; + + const theme = useTheme2(); + const [isInspecting, setIsInspecting] = useState(false); + // Get logId from the table frame (frame), not the original logsFrame, because + // the table frame is sorted/transformed and rowIndex refers to the table frame + const idFieldName = logsFrame?.idField?.name ?? 'id'; + const idField = frame.fields.find((field) => field.name === idFieldName || field.name === 'id'); + const logId = idField?.values[rowIndex]; + const getLineValue = () => { + const bodyFieldName = logsFrame?.bodyField?.name; + const bodyField = bodyFieldName + ? frame.fields.find((field) => field.name === bodyFieldName) + : frame.fields.find((field) => field.type === 'string'); + return bodyField?.values[rowIndex]; + }; + + const lineValue = getLineValue(); + + const styles = getStyles(theme); + + // Generate link to the log line + const getText = useCallback(() => { + if (!logId || !exploreId || !absoluteRange || !logRows) { + return ''; + } + + try { + // Get the log row from the logRows array + const logRow = logRows.find((row) => row.rowId === logId); + + if (!logRow) { + return ''; + } + + // Get the current explore state + const currentPaneState = getState().explore.panes[exploreId]; + if (!currentPaneState) { + return ''; + } + + // Create URL state with log permalink information + const urlState = getUrlStateFromPaneState(currentPaneState); + + // Preserve all panel state (columns, labelFieldName, etc.) + urlState.panelsState = { + ...currentPaneState.panelsState, + logs: { + ...panelState, + displayedFields: displayedFields ?? [], + }, + }; + + // Calculate the time range for the permalink + urlState.range = getLogsPermalinkRange(logRow, logRows, absoluteRange); + + // Create the full URL with selectedLine as a URL parameter (with id and row) + const serializedState = serializeStateToUrlParam(urlState); + const baseUrl = getExploreBaseUrl(); + const url = urlUtil.renderUrl(`${baseUrl}/explore`, { + left: serializedState, + selectedLine: JSON.stringify({ id: logId, row: rowIndex }), + }); + return url; + } catch (error) { + return ''; + } + }, [absoluteRange, displayedFields, exploreId, logId, logRows, rowIndex, panelState]); + + const handleViewClick = () => { + setIsInspecting(true); + }; + + return ( + <> +
+
+ +
+
+ +
+
+ {isInspecting && ( + setIsInspecting(false)} + isOpen={true} + title={t('explore.logs-table.action-buttons.inspect-value', 'Inspect value')} + > +
{lineValue}
+ + lineValue}> + {t('explore.logs-table.action-buttons.copy-to-clipboard', 'Copy to Clipboard')} + + +
+ )} + + ); +} + +export const getStyles = (theme: GrafanaTheme2) => ({ + clipboardButton: css({ + height: '100%', + lineHeight: '1', + padding: 0, + width: '20px', + }), + iconWrapper: css({ + background: theme.colors.background.secondary, + boxShadow: theme.shadows.z2, + display: 'flex', + flexDirection: 'row', + height: '35px', + left: 0, + top: 0, + padding: `0 ${theme.spacing(0.5)}`, + position: 'absolute', + zIndex: 1, + }), + inspect: css({ + '& button svg': { + marginRight: 'auto', + }, + '&:hover': { + color: theme.colors.text.link, + cursor: 'pointer', + }, + padding: '5px 3px', + }), + inspectButton: css({ + borderRadius: theme.shape.radius.default, + display: 'inline-flex', + margin: 0, + overflow: 'hidden', + verticalAlign: 'middle', + }), +}); diff --git a/public/app/features/explore/Logs/LogsTableWrap.tsx b/public/app/features/explore/Logs/LogsTableWrap.tsx index 67829081b31..ff8cceaadcf 100644 --- a/public/app/features/explore/Logs/LogsTableWrap.tsx +++ b/public/app/features/explore/Logs/LogsTableWrap.tsx @@ -7,11 +7,13 @@ import { ExploreLogsPanelState, GrafanaTheme2, Labels, + LogRowModel, LogsSortOrder, SelectableValue, SplitOpen, store, TimeRange, + AbsoluteTimeRange, } from '@grafana/data'; import { t } from '@grafana/i18n'; import { reportInteraction } from '@grafana/runtime'; @@ -40,6 +42,10 @@ interface Props { onClickFilterLabel?: (key: string, value: string, frame?: DataFrame) => void; onClickFilterOutLabel?: (key: string, value: string, frame?: DataFrame) => void; datasourceType?: string; + exploreId?: string; + displayedFields?: string[]; + absoluteRange?: AbsoluteTimeRange; + logRows?: LogRowModel[]; } type ActiveFieldMeta = { @@ -278,6 +284,25 @@ export function LogsTableWrap(props: Props) { const styles = useStyles2(getStyles, height, sidebarWidth); + const onSortByChange = useCallback( + (sortBy: Array<{ displayName: string; desc?: boolean }>) => { + // Transform from Table format to URL format - only store the first sort column + if (sortBy.length > 0) { + // Defer the Redux dispatch to avoid updating ExploreActions during Table's render cycle + // Even though this is called from an event handler, the synchronous Redux dispatch + // can cause ExploreActions (which subscribes to panes state) to re-render while + // Table is still rendering, triggering the React warning + setTimeout(() => { + updatePanelState({ + tableSortBy: sortBy[0].displayName, + tableSortDir: sortBy[0].desc ? 'desc' : 'asc', + }); + }, 0); + } + }, + [updatePanelState] + ); + if (!columnsWithMeta) { return null; } @@ -512,6 +537,13 @@ export function LogsTableWrap(props: Props) { dataFrame={currentDataFrame} columnsWithMeta={columnsWithMeta} height={height} + tableSortBy={panelState?.tableSortBy} + tableSortDir={panelState?.tableSortDir} + onSortByChange={onSortByChange} + displayedFields={props.displayedFields} + exploreId={props.exploreId} + absoluteRange={props.absoluteRange} + logRows={props.logRows} /> diff --git a/public/app/features/explore/Logs/utils/url.ts b/public/app/features/explore/Logs/utils/url.ts new file mode 100644 index 00000000000..10be54cce1e --- /dev/null +++ b/public/app/features/explore/Logs/utils/url.ts @@ -0,0 +1,10 @@ +/** + * Gets the base URL before the /explore path. + * Used for constructing explore URLs with permalinks. + * + * @returns The base URL (e.g., "http://localhost:3000" or "https://grafana.com") + */ +export function getExploreBaseUrl(): string { + const match = /.*(?=\/explore)/.exec(window.location.href); + return match ? match[0] : window.location.origin; +} diff --git a/public/app/features/explore/Table/TableContainer.test.tsx b/public/app/features/explore/Table/TableContainer.test.tsx index af987261ead..bb579840017 100644 --- a/public/app/features/explore/Table/TableContainer.test.tsx +++ b/public/app/features/explore/Table/TableContainer.test.tsx @@ -1,22 +1,11 @@ -import { render, screen, within } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import { DataFrame, FieldType, getDefaultTimeRange, InternalTimeZones, toDataFrame } from '@grafana/data'; import { TableContainerWithTheme } from './TableContainer'; -function getTables(): HTMLElement[] { - return screen.getAllByRole('table'); -} - -function getRowsData(rows: HTMLElement[]): Object[] { - let content = []; - for (let i = 1; i < rows.length; i++) { - content.push({ - time: within(rows[i]).getByText(/2021*/).textContent, - text: within(rows[i]).getByText(/test_string_*/).textContent, - }); - } - return content; +function getPanels(): HTMLElement[] { + return screen.getAllByText(/PanelRenderer/); } const dataFrame = toDataFrame({ @@ -60,17 +49,9 @@ describe('TableContainerWithTheme', () => { describe('With one main frame', () => { it('should render component', () => { render(); - const tables = getTables(); + const tables = getPanels(); expect(tables.length).toBe(1); expect(tables[0]).toBeInTheDocument(); - const rows = within(tables[0]).getAllByRole('row'); - expect(rows).toHaveLength(5); - expect(getRowsData(rows)).toEqual([ - { time: '2021-01-01 00:00:00', text: 'test_string_1' }, - { time: '2021-01-01 03:00:00', text: 'test_string_2' }, - { time: '2021-01-01 01:00:00', text: 'test_string_3' }, - { time: '2021-01-01 02:00:00', text: 'test_string_4' }, - ]); }); it('should render 0 series returned on no items', () => { @@ -85,26 +66,6 @@ describe('TableContainerWithTheme', () => { expect(screen.getByText('0 series returned')).toBeInTheDocument(); }); - it('should update time when timezone changes', () => { - const { rerender } = render(); - const rowsBeforeChange = within(getTables()[0]).getAllByRole('row'); - expect(getRowsData(rowsBeforeChange)).toEqual([ - { time: '2021-01-01 00:00:00', text: 'test_string_1' }, - { time: '2021-01-01 03:00:00', text: 'test_string_2' }, - { time: '2021-01-01 01:00:00', text: 'test_string_3' }, - { time: '2021-01-01 02:00:00', text: 'test_string_4' }, - ]); - - rerender(); - const rowsAfterChange = within(getTables()[0]).getAllByRole('row'); - expect(getRowsData(rowsAfterChange)).toEqual([ - { time: '2020-12-31 19:00:00', text: 'test_string_1' }, - { time: '2020-12-31 22:00:00', text: 'test_string_2' }, - { time: '2020-12-31 20:00:00', text: 'test_string_3' }, - { time: '2020-12-31 21:00:00', text: 'test_string_4' }, - ]); - }); - it('should render table title with Prometheus query', () => { const dataFrames = [{ ...dataFrame, name: 'metric{label="value"}' }]; const tableProps = { ...defaultProps, tableResult: dataFrames }; @@ -118,7 +79,7 @@ describe('TableContainerWithTheme', () => { const dataFrames = [dataFrame, dataFrame]; const multiDefaultProps = { ...defaultProps, tableResult: dataFrames }; render(); - const tables = getTables(); + const tables = getPanels(); expect(tables.length).toBe(2); expect(tables[0]).toBeInTheDocument(); expect(tables[1]).toBeInTheDocument(); diff --git a/public/app/features/explore/Table/TableContainer.tsx b/public/app/features/explore/Table/TableContainer.tsx index b0a203bd22a..2c1614e539d 100644 --- a/public/app/features/explore/Table/TableContainer.tsx +++ b/public/app/features/explore/Table/TableContainer.tsx @@ -2,11 +2,20 @@ import { css } from '@emotion/css'; import { PureComponent } from 'react'; import { connect, ConnectedProps } from 'react-redux'; -import { applyFieldOverrides, SplitOpen, DataFrame, LoadingState, FieldType } from '@grafana/data'; +import { + applyFieldOverrides, + SplitOpen, + DataFrame, + LoadingState, + FieldType, + DataLinksContext, + EventBus, + EventBusSrv, +} from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; -import { getTemplateSrv } from '@grafana/runtime'; +import { getTemplateSrv, PanelRenderer } from '@grafana/runtime'; import { TimeZone } from '@grafana/schema'; -import { Table, AdHocFilterItem, PanelChrome, withTheme2, Themeable2 } from '@grafana/ui'; +import { AdHocFilterItem, PanelChrome, withTheme2, Themeable2, PanelContextProvider } from '@grafana/ui'; import { config } from 'app/core/config'; import { hasDeprecatedParentRowIndex, @@ -23,12 +32,13 @@ import { exploreDataLinkPostProcessorFactory } from '../utils/links'; const MAX_NUMBER_OF_COLUMNS = 20; interface TableContainerProps extends Themeable2 { - ariaLabel?: string; exploreId: string; width: number; timeZone: TimeZone; onCellFilterAdded?: (filter: AdHocFilterItem) => void; splitOpenFn: SplitOpen; + eventBus?: EventBus; + ariaLabel?: string; } function mapStateToProps(state: StoreState, { exploreId }: TableContainerProps) { @@ -79,7 +89,7 @@ export class TableContainer extends PureComponent { } render() { - const { loading, onCellFilterAdded, tableResult, width, splitOpenFn, range, ariaLabel, timeZone, theme } = + const { loading, onCellFilterAdded, tableResult, width, splitOpenFn, range, timeZone, theme, eventBus } = this.props; const { showAll } = this.state; @@ -153,13 +163,28 @@ export class TableContainer extends PureComponent { loadingState={loading ? LoadingState.Loading : undefined} > {(innerWidth, innerHeight) => ( -
+ + + + + )} ))} diff --git a/public/app/features/explore/TraceView/components/common/Popover.tsx b/public/app/features/explore/TraceView/components/common/Popover.tsx index adb3c052f10..9334491ec25 100644 --- a/public/app/features/explore/TraceView/components/common/Popover.tsx +++ b/public/app/features/explore/TraceView/components/common/Popover.tsx @@ -3,7 +3,7 @@ import { cloneElement, ReactElement, useRef } from 'react'; import { Popover as GrafanaPopover, PopoverController } from '@grafana/ui'; export type PopoverProps = { - children: ReactElement; + children: ReactElement>; content: ReactElement; overlayClassName?: string; }; diff --git a/public/app/features/explore/TraceView/components/common/SearchBarInput.tsx b/public/app/features/explore/TraceView/components/common/SearchBarInput.tsx index a6527ca1c0e..831aa856dbf 100644 --- a/public/app/features/explore/TraceView/components/common/SearchBarInput.tsx +++ b/public/app/features/explore/TraceView/components/common/SearchBarInput.tsx @@ -22,7 +22,7 @@ type Props = { onChange: (value: string) => void; }; -const SearchBarInput = memo(({ value, onChange }: Props) => { +const SearchBarInput = memo(({ value = '', onChange }: Props) => { const clearUiFind = () => { onChange(''); }; diff --git a/public/app/features/explore/state/query.ts b/public/app/features/explore/state/query.ts index 251ab4af5d2..39ad4ea5e73 100644 --- a/public/app/features/explore/state/query.ts +++ b/public/app/features/explore/state/query.ts @@ -36,7 +36,7 @@ import { getShiftedTimeRange } from 'app/core/utils/timePicker'; import { getCorrelationsBySourceUIDs } from 'app/features/correlations/utils'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { getFiscalYearStartMonth, getTimeZone } from 'app/features/profile/state/selectors'; -import { SupportingQueryType } from 'app/plugins/datasource/loki/types'; +import { SupportingQueryType } from 'app/plugins/datasource/loki/dataquery.gen'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; import { ExploreItemState, diff --git a/public/app/features/expressions/components/ExpressionTypeDropdown.tsx b/public/app/features/expressions/components/ExpressionTypeDropdown.tsx index bb84dcd076c..83d2b249441 100644 --- a/public/app/features/expressions/components/ExpressionTypeDropdown.tsx +++ b/public/app/features/expressions/components/ExpressionTypeDropdown.tsx @@ -15,7 +15,7 @@ const EXPRESSION_ICON_MAP = { } as const satisfies Record; interface ExpressionTypeDropdownProps { - children: ReactElement; + children: ReactElement>; handleOnSelect: (value: ExpressionQueryType) => void; } diff --git a/public/app/features/logs/components/ControlledLogRows.tsx b/public/app/features/logs/components/ControlledLogRows.tsx index 874234837ac..38a579463ed 100644 --- a/public/app/features/logs/components/ControlledLogRows.tsx +++ b/public/app/features/logs/components/ControlledLogRows.tsx @@ -8,6 +8,7 @@ import { EventBusSrv, ExploreLogsPanelState, LogLevel, + LogRowModel, LogsMetaItem, LogsSortOrder, SplitOpen, @@ -41,6 +42,10 @@ export interface ControlledLogRowsProps extends Omit { datasourceType?: string; width?: number; logsTableFrames?: DataFrame[]; + displayedFields?: string[]; + exploreId?: string; + absoluteRange?: AbsoluteTimeRange; + logRows?: LogRowModel[]; } export type LogRowsComponentProps = Omit< diff --git a/public/app/features/logs/components/ControlledLogsTable.tsx b/public/app/features/logs/components/ControlledLogsTable.tsx index b706ba145d8..0374928da8f 100644 --- a/public/app/features/logs/components/ControlledLogsTable.tsx +++ b/public/app/features/logs/components/ControlledLogsTable.tsx @@ -25,6 +25,10 @@ export const ControlledLogsTable = ({ width, logsTableFrames, visualisationType, + displayedFields, + exploreId, + absoluteRange, + logRows, ...rest }: LogRowsComponentProps) => { const { sortOrder, controlsExpanded } = useLogListContext(); @@ -58,6 +62,10 @@ export const ControlledLogsTable = ({ panelState={panelState} updatePanelState={updatePanelState} datasourceType={datasourceType} + displayedFields={displayedFields} + exploreId={exploreId} + absoluteRange={absoluteRange} + logRows={logRows} /> diff --git a/public/app/features/logs/logsModel.ts b/public/app/features/logs/logsModel.ts index e60887518fe..8a0ff6b99ad 100644 --- a/public/app/features/logs/logsModel.ts +++ b/public/app/features/logs/logsModel.ts @@ -44,7 +44,7 @@ import { t } from '@grafana/i18n'; import { BarAlignment, GraphDrawStyle, StackingMode } from '@grafana/schema'; import { colors } from '@grafana/ui'; import { getThemeColor } from 'app/core/utils/colors'; -import { LokiQueryDirection } from 'app/plugins/datasource/loki/types'; +import { LokiQueryDirection } from 'app/plugins/datasource/loki/dataquery.gen'; import { LogsFrame, parseLogsFrame } from './logsFrame'; import { createLogRowsMap, getLogLevel, getLogLevelFromKey, sortInAscendingOrder } from './utils'; diff --git a/public/app/features/panel/components/VizTypePicker/PanelTypeCard.tsx b/public/app/features/panel/components/VizTypePicker/PanelTypeCard.tsx index 8070854ab9d..2125e645e60 100644 --- a/public/app/features/panel/components/VizTypePicker/PanelTypeCard.tsx +++ b/public/app/features/panel/components/VizTypePicker/PanelTypeCard.tsx @@ -55,7 +55,11 @@ const PanelTypeCardComponent = ({ isCurrent ? t('panel.panel-type-card.title-click-to-close', 'Click again to close this section') : plugin.name } > - +
{title}
diff --git a/public/app/features/plugins/extensions/ExtensionErrorBoundary.tsx b/public/app/features/plugins/extensions/ExtensionErrorBoundary.tsx index 5d85e16eee1..99886edf488 100644 --- a/public/app/features/plugins/extensions/ExtensionErrorBoundary.tsx +++ b/public/app/features/plugins/extensions/ExtensionErrorBoundary.tsx @@ -25,7 +25,6 @@ export const ExtensionErrorBoundary = ({ log.error(`Extension "${pluginId}/${extensionTitle}" failed to load.`, { message: error.message, componentStack: errorInfo.componentStack ?? '', - digest: errorInfo.digest ?? '', }); }} fallback={() => { diff --git a/public/app/features/plugins/extensions/registry/AddedLinksRegistry.test.ts b/public/app/features/plugins/extensions/registry/AddedLinksRegistry.test.ts index 63ab6b55090..07574745d71 100644 --- a/public/app/features/plugins/extensions/registry/AddedLinksRegistry.test.ts +++ b/public/app/features/plugins/extensions/registry/AddedLinksRegistry.test.ts @@ -95,6 +95,7 @@ describe('AddedLinksRegistry', () => { path: `/a/${pluginId}/declare-incident`, targets: 'plugins/myorg-basic-app/start', configure: jest.fn().mockImplementation((context) => ({ title: context?.title })), + openInNewTab: true, }, ], }); @@ -120,6 +121,7 @@ describe('AddedLinksRegistry', () => { path: `/a/${pluginId}/declare-incident`, extensionPointId: 'plugins/myorg-basic-app/start', configure: expect.any(Function), + openInNewTab: true, }, ], }); diff --git a/public/app/features/plugins/extensions/registry/AddedLinksRegistry.ts b/public/app/features/plugins/extensions/registry/AddedLinksRegistry.ts index b3f293675ce..c3dd9faf6f1 100644 --- a/public/app/features/plugins/extensions/registry/AddedLinksRegistry.ts +++ b/public/app/features/plugins/extensions/registry/AddedLinksRegistry.ts @@ -21,6 +21,7 @@ export type AddedLinkRegistryItem = { configure?: PluginAddedLinksConfigureFunc; icon?: IconName; category?: string; + openInNewTab?: boolean; }; export class AddedLinksRegistry extends Registry { @@ -40,13 +41,14 @@ export class AddedLinksRegistry extends Registry { title: '2', description: '2', path: `/a/${pluginId}/2`, + openInNewTab: true, }, { targets: 'plugins/another-extension/v1', @@ -181,7 +182,9 @@ describe('usePluginLinks()', () => { expect(result.current.links.length).toBe(2); expect(result.current.links[0].title).toBe('1'); + expect(result.current.links[0].openInNewTab).toBeUndefined(); expect(result.current.links[1].title).toBe('2'); + expect(result.current.links[1].openInNewTab).toBe(true); }); it('should dynamically update the extensions registered for a certain extension point', () => { diff --git a/public/app/features/plugins/extensions/usePluginLinks.tsx b/public/app/features/plugins/extensions/usePluginLinks.tsx index 70518ab9450..9ec5d215f94 100644 --- a/public/app/features/plugins/extensions/usePluginLinks.tsx +++ b/public/app/features/plugins/extensions/usePluginLinks.tsx @@ -51,6 +51,7 @@ export function usePluginLinks({ title: addedLink.title, description: addedLink.description ?? '', onClick: typeof addedLink.onClick, + openInNewTab: addedLink.openInNewTab ? 'true' : 'false', }); // Only limit if the `limitPerPlugin` is set @@ -84,6 +85,7 @@ export function usePluginLinks({ description: overrides?.description || addedLink.description || '', path: isString(path) ? getLinkExtensionPathWithTracking(pluginId, path, extensionPointId) : undefined, category: overrides?.category || addedLink.category, + openInNewTab: overrides?.openInNewTab ?? addedLink.openInNewTab, }; extensions.push(extension); diff --git a/public/app/features/plugins/extensions/utils.test.tsx b/public/app/features/plugins/extensions/utils.test.tsx index 2c1563f8f6c..4e00a80cf27 100644 --- a/public/app/features/plugins/extensions/utils.test.tsx +++ b/public/app/features/plugins/extensions/utils.test.tsx @@ -785,7 +785,6 @@ describe('Plugin Extensions / Utils', () => { expect(log.error).toHaveBeenCalledWith(`Extension "${pluginId}/${extensionTitle}" failed to load.`, { message: 'Test error', componentStack: expect.any(String), - digest: expect.any(String), }); expect(screen.getByText(`Extension failed to load: "${pluginId}/${extensionTitle}"`)).toBeVisible(); @@ -818,7 +817,6 @@ describe('Plugin Extensions / Utils', () => { expect(log.error).toHaveBeenCalledWith(`Extension "${pluginId}/${extensionTitle}" failed to load.`, { message: 'Test error', componentStack: expect.any(String), - digest: expect.any(String), }); expect(screen.getByText(`Extension failed to load: "${pluginId}/${extensionTitle}"`)).toBeVisible(); @@ -965,7 +963,6 @@ describe('Plugin Extensions / Utils', () => { expect(log.error).toHaveBeenCalledWith(`Extension "${pluginId}/${extensionTitle}" failed to load.`, { message: 'Test error', componentStack: expect.any(String), - digest: expect.any(String), }); }); @@ -995,7 +992,6 @@ describe('Plugin Extensions / Utils', () => { expect(log.error).toHaveBeenCalledWith(`Extension "${pluginId}/${extensionTitle}" failed to load.`, { message: 'Test error', componentStack: expect.any(String), - digest: expect.any(String), }); }); }); diff --git a/public/app/features/plugins/extensions/utils.tsx b/public/app/features/plugins/extensions/utils.tsx index 35feb659b6a..adb1ed8616d 100644 --- a/public/app/features/plugins/extensions/utils.tsx +++ b/public/app/features/plugins/extensions/utils.tsx @@ -419,6 +419,7 @@ export function createExtensionSubMenu(extensions: PluginExtensionLink[]): Panel text: truncateTitle(extension.title, 25), href: extension.path, onClick: extension.onClick, + iconClassName: extension.icon, }); continue; } @@ -431,6 +432,7 @@ export function createExtensionSubMenu(extensions: PluginExtensionLink[]): Panel text: truncateTitle(extension.title, 25), href: extension.path, onClick: extension.onClick, + iconClassName: extension.icon, }); } @@ -472,12 +474,14 @@ export function getLinkExtensionOverrides( return undefined; } + // Only allowing to override the following properties let { title = config.title, description = config.description, path = config.path, icon = config.icon, category = config.category, + openInNewTab = config.openInNewTab, ...rest } = overrides; @@ -502,6 +506,7 @@ export function getLinkExtensionOverrides( path, icon, category, + openInNewTab, }; } catch (error) { if (error instanceof Error) { diff --git a/public/app/features/provisioning/components/Folders/NewProvisionedFolderForm.test.tsx b/public/app/features/provisioning/components/Folders/NewProvisionedFolderForm.test.tsx index 1aa011c708c..3dcd2358ce2 100644 --- a/public/app/features/provisioning/components/Folders/NewProvisionedFolderForm.test.tsx +++ b/public/app/features/provisioning/components/Folders/NewProvisionedFolderForm.test.tsx @@ -154,7 +154,6 @@ const mockHookData: ProvisionedFolderFormDataResult = { spec: { title: '', }, - status: {}, }, workflowOptions: [ { label: 'Commit directly', value: 'write' }, diff --git a/public/app/features/scopes/ScopesService.test.ts b/public/app/features/scopes/ScopesService.test.ts index 6b360f853e3..51c50cc9ff9 100644 --- a/public/app/features/scopes/ScopesService.test.ts +++ b/public/app/features/scopes/ScopesService.test.ts @@ -117,7 +117,8 @@ describe('ScopesService', () => { expect(selectorService.changeScopes).toHaveBeenCalledWith(['scope1'], undefined, 'node1', false); }); - it('should read scope_parent for backward compatibility', () => { + // TODO: remove when parentNodeId is removed + it('should ignore scope_parent from URL (only used for recent scopes)', () => { locationService.getLocation = jest.fn().mockReturnValue({ pathname: '/test', search: '?scopes=scope1&scope_parent=parent1', @@ -125,10 +126,12 @@ describe('ScopesService', () => { service = new ScopesService(selectorService, dashboardsService, locationService); - expect(selectorService.changeScopes).toHaveBeenCalledWith(['scope1'], 'parent1', undefined, false); + // parentNodeId should be undefined since we don't read it from URL + expect(selectorService.changeScopes).toHaveBeenCalledWith(['scope1'], undefined, undefined, false); }); - it('should prefer scope_node when both scope_node and scope_parent exist', () => { + // TODO: remove when parentNodeId is removed + it('should only use scope_node when both scope_node and scope_parent exist in URL', () => { locationService.getLocation = jest.fn().mockReturnValue({ pathname: '/test', search: '?scopes=scope1&scope_node=node1&scope_parent=parent1', @@ -136,9 +139,9 @@ describe('ScopesService', () => { service = new ScopesService(selectorService, dashboardsService, locationService); - // Should call with parent1 as parentNodeId and node1 as scopeNodeId - expect(selectorService.changeScopes).toHaveBeenCalledWith(['scope1'], 'parent1', 'node1', false); - // Should preload node1 (not parent1) + // Should only use scopeNodeId from URL, parentNodeId is undefined + expect(selectorService.changeScopes).toHaveBeenCalledWith(['scope1'], undefined, 'node1', false); + // Should preload node1 expect(selectorService.resolvePathToRoot).toHaveBeenCalledWith('node1', expect.anything()); }); @@ -153,7 +156,8 @@ describe('ScopesService', () => { expect(selectorService.resolvePathToRoot).toHaveBeenCalledWith('node1', expect.anything()); }); - it('should fallback to preload scope_parent when scope_node is not provided', () => { + // TODO: remove when parentNodeId is removed + it('should not preload when only scope_parent is in URL', () => { locationService.getLocation = jest.fn().mockReturnValue({ pathname: '/test', search: '?scopes=scope1&scope_parent=parent1', @@ -161,7 +165,8 @@ describe('ScopesService', () => { service = new ScopesService(selectorService, dashboardsService, locationService); - expect(selectorService.resolvePathToRoot).toHaveBeenCalledWith('parent1', expect.anything()); + // Should not preload since we don't read scope_parent from URL + expect(selectorService.resolvePathToRoot).not.toHaveBeenCalled(); }); it('should handle multiple scopes from URL', () => { diff --git a/public/app/features/scopes/ScopesService.ts b/public/app/features/scopes/ScopesService.ts index 36edcc94b13..1d0be39f56c 100644 --- a/public/app/features/scopes/ScopesService.ts +++ b/public/app/features/scopes/ScopesService.ts @@ -71,18 +71,16 @@ export class ScopesService implements ScopesContextValue { // Init from the URL when we first load const queryParams = new URLSearchParams(locationService.getLocation().search); const scopeNodeId = queryParams.get('scope_node'); - // TODO: figure out when to remove this. scope_parent is for backward compatibility only - const parentNodeId = queryParams.get('scope_parent'); const navigationScope = queryParams.get('navigation_scope'); if (navigationScope) { this.dashboardsService.setNavigationScope(navigationScope); } - this.changeScopes(queryParams.getAll('scopes'), parentNodeId ?? undefined, scopeNodeId ?? undefined); + this.changeScopes(queryParams.getAll('scopes'), undefined, scopeNodeId ?? undefined); - // Pre-load scope node (which loads parent too) or fallback to parent node for old URLs - const nodeToPreload = scopeNodeId ?? parentNodeId; + // Pre-load scope node (which loads parent too) + const nodeToPreload = scopeNodeId; if (nodeToPreload) { this.selectorService.resolvePathToRoot(nodeToPreload, this.selectorService.state.tree!).catch((error) => { console.error('Failed to pre-load node path', error); @@ -100,8 +98,6 @@ export class ScopesService implements ScopesContextValue { const scopes = queryParams.getAll('scopes'); const scopeNodeId = queryParams.get('scope_node'); - // scope_parent is for backward compatibility only - const parentNodeId = queryParams.get('scope_parent'); // Check if new scopes are different from the old scopes const currentScopes = this.selectorService.state.appliedScopes.map((scope) => scope.scopeId); @@ -109,7 +105,7 @@ export class ScopesService implements ScopesContextValue { // We only update scopes but never delete them. This is to keep the scopes in memory if user navigates to // page that does not use scopes (like from dashboard to dashboard list back to dashboard). If user // changes the URL directly, it would trigger a reload so scopes would still be reset. - this.changeScopes(scopes, parentNodeId ?? undefined, scopeNodeId ?? undefined); + this.changeScopes(scopes, undefined, scopeNodeId ?? undefined); } }) ); diff --git a/public/app/features/scopes/selector/RecentScopes.tsx b/public/app/features/scopes/selector/RecentScopes.tsx index 66771f635fb..a13ed97c275 100644 --- a/public/app/features/scopes/selector/RecentScopes.tsx +++ b/public/app/features/scopes/selector/RecentScopes.tsx @@ -9,7 +9,7 @@ import { RecentScope } from './types'; interface RecentScopesProps { recentScopes: RecentScope[][]; - onSelect: (scopeIds: string[], parentNodeId?: string) => void; + onSelect: (scopeIds: string[], parentNodeId?: string, scopeNodeId?: string) => void; } export const RecentScopes = ({ recentScopes, onSelect }: RecentScopesProps) => { @@ -45,7 +45,8 @@ export const RecentScopes = ({ recentScopes, onSelect }: RecentScopesProps) => { onClick={() => { onSelect( recentScopeSet.map((s) => s.metadata.name), - recentScopeSet[0]?.parentNode?.metadata?.name + recentScopeSet[0]?.parentNode?.metadata?.name, + recentScopeSet[0]?.scopeNodeId ); }} > diff --git a/public/app/features/scopes/selector/ScopesInput.tsx b/public/app/features/scopes/selector/ScopesInput.tsx index ce22820b32d..a180c523e6b 100644 --- a/public/app/features/scopes/selector/ScopesInput.tsx +++ b/public/app/features/scopes/selector/ScopesInput.tsx @@ -32,12 +32,12 @@ export function ScopesInput({ onRemoveAllClick, }: ScopesInputProps) { const scopeNodeId = appliedScopes[0]?.scopeNodeId; - const parentNodeIdFromUrl = appliedScopes[0]?.parentNodeId; const styles = useStyles2(getStyles); + const parentNodeIdFromRecentScopes = appliedScopes[0]?.parentNodeId; // This is only set from recent scopes TODO: remove after recent scopes refactor const { node: scopeNode, isLoading: scopeNodeLoading } = useScopeNode(scopeNodeId); - // Get parent from scope node if available, otherwise use parentNodeId from URL (for backward compatibility) - const parentNodeId = scopeNode?.spec.parentName ?? parentNodeIdFromUrl; + // Get parent from scope node if available, otherwise fallback to parent + const parentNodeId = scopeNode?.spec.parentName ?? parentNodeIdFromRecentScopes; const { node: parentNode, isLoading: parentNodeLoading } = useScopeNode(parentNodeId); // Prioritize scope node subtitle over parent node title diff --git a/public/app/features/scopes/selector/ScopesSelector.tsx b/public/app/features/scopes/selector/ScopesSelector.tsx index cdb28acddf8..bc89c748814 100644 --- a/public/app/features/scopes/selector/ScopesSelector.tsx +++ b/public/app/features/scopes/selector/ScopesSelector.tsx @@ -132,8 +132,8 @@ export const ScopesSelector = () => { selectScope={selectScope} deselectScope={deselectScope} toggleExpandedNode={toggleExpandedNode} - onRecentScopesSelect={(scopeIds: string[], parentNodeId?: string) => { - scopesSelectorService.changeScopes(scopeIds, parentNodeId); + onRecentScopesSelect={(scopeIds: string[], parentNodeId?: string, scopeNodeId?: string) => { + scopesSelectorService.changeScopes(scopeIds, parentNodeId, scopeNodeId); scopesSelectorService.closeAndReset(); }} /> diff --git a/public/app/features/scopes/selector/ScopesSelectorService.test.ts b/public/app/features/scopes/selector/ScopesSelectorService.test.ts index 2c89ea58fe5..673046adc0f 100644 --- a/public/app/features/scopes/selector/ScopesSelectorService.test.ts +++ b/public/app/features/scopes/selector/ScopesSelectorService.test.ts @@ -15,6 +15,14 @@ jest.mock('@grafana/runtime', () => ({ push: jest.fn(), getLocation: jest.fn(), }, + config: { + ...jest.requireActual('@grafana/runtime').config, + + featureToggles: { + ...jest.requireActual('@grafana/runtime').config.featureToggles, + useScopeSingleNodeEndpoint: true, + }, + }, })); describe('ScopesSelectorService', () => { @@ -69,6 +77,7 @@ describe('ScopesSelectorService', () => { }), fetchDashboards: jest.fn().mockResolvedValue([]), fetchScopeNavigations: jest.fn().mockResolvedValue([]), + fetchScopeNode: jest.fn().mockResolvedValue(mockNode), } as unknown as jest.Mocked; dashboardsService = { @@ -197,6 +206,190 @@ describe('ScopesSelectorService', () => { await service.open(); expect(service.state.opened).toBe(true); }); + + it('should use scopeNodeId to resolve path when opening selector', async () => { + const parentNode: ScopeNode = { + metadata: { name: 'parent-container' }, + spec: { + linkId: '', + linkType: 'scope', + //parentName: '', + nodeType: 'container', + title: 'Parent Container', + }, + }; + + const childNode: ScopeNode = { + metadata: { name: 'child-1' }, + spec: { + linkId: 'scope-1', + linkType: 'scope', + parentName: 'parent-container', + nodeType: 'leaf', + title: 'Child 1', + }, + }; + + // Mock API responses + apiClient.fetchNodes.mockImplementation((options: { parent?: string; query?: string; limit?: number }) => { + if (options.parent === '') { + return Promise.resolve([parentNode]); + } else if (options.parent === 'parent-container') { + return Promise.resolve([childNode]); + } + return Promise.resolve([]); + }); + + apiClient.fetchScopeNode.mockImplementation((scopeNodeId: string) => { + if (scopeNodeId === 'child-1') { + return Promise.resolve(childNode); + } + return Promise.resolve(undefined); + }); + + // Apply scope with scopeNodeId and parentNodeId set + await service.changeScopes(['scope-1'], 'parent-container', 'child-1'); + + // Open the selector + await service.open(); + + // Verify the tree is expanded to the selected scope's parent + // The key fix: it should resolve path using scopeNodeId (child-1), not parentNodeId + expect(service.state.tree?.expanded).toBe(true); + expect(service.state.tree?.children?.['parent-container']?.expanded).toBe(true); + expect(service.state.tree?.children?.['parent-container']?.children?.['child-1']).toBeDefined(); + }); + + it('should load parent node children when opening to selected scope', async () => { + const parentNode: ScopeNode = { + metadata: { name: 'parent-container' }, + spec: { + linkId: '', + linkType: 'scope', + parentName: '', + nodeType: 'container', + title: 'Parent Container', + }, + }; + + const childNode1: ScopeNode = { + metadata: { name: 'child-1' }, + spec: { + linkId: 'scope-1', + linkType: 'scope', + parentName: 'parent-container', + nodeType: 'leaf', + title: 'Child 1', + }, + }; + + const childNode2: ScopeNode = { + metadata: { name: 'child-2' }, + spec: { + linkId: 'scope-2', + linkType: 'scope', + parentName: 'parent-container', + nodeType: 'leaf', + title: 'Child 2', + }, + }; + + const childNode3: ScopeNode = { + metadata: { name: 'child-3' }, + spec: { + linkId: 'scope-3', + linkType: 'scope', + parentName: 'parent-container', + nodeType: 'leaf', + title: 'Child 3', + }, + }; + + // Mock API responses + apiClient.fetchNodes.mockImplementation((options: { parent?: string; query?: string; limit?: number }) => { + if (options.parent === '') { + return Promise.resolve([parentNode]); + } else if (options.parent === 'parent-container') { + return Promise.resolve([childNode1, childNode2, childNode3]); + } + return Promise.resolve([]); + }); + + apiClient.fetchScopeNode.mockImplementation((scopeNodeId: string) => { + if (scopeNodeId === 'child-2') { + return Promise.resolve(childNode2); + } else if (scopeNodeId === 'parent-container') { + return Promise.resolve(parentNode); + } + return Promise.resolve(undefined); + }); + + await service.changeScopes(['scope-2'], 'parent-container', 'child-2'); + await service.open(); + + // Verify all sibling nodes are loaded (not just the selected one) + expect(service.state.tree?.children?.['parent-container']?.children?.['child-1']).toBeDefined(); + expect(service.state.tree?.children?.['parent-container']?.children?.['child-2']).toBeDefined(); + expect(service.state.tree?.children?.['parent-container']?.children?.['child-3']).toBeDefined(); + + // Verify childrenLoaded flag is set on the parent + expect(service.state.tree?.children?.['parent-container']?.childrenLoaded).toBe(true); + }); + + it('should only load children if childrenLoaded is false', async () => { + const parentNode: ScopeNode = { + metadata: { name: 'parent-container' }, + spec: { + linkId: '', + linkType: 'scope', + parentName: '', + nodeType: 'container', + title: 'Parent Container', + }, + }; + + const childNode: ScopeNode = { + metadata: { name: 'child-1' }, + spec: { + linkId: 'scope-1', + linkType: 'scope', + parentName: 'parent-container', + nodeType: 'leaf', + title: 'Child 1', + }, + }; + + apiClient.fetchNodes.mockImplementation((options: { parent?: string; query?: string; limit?: number }) => { + if (options.parent === '') { + return Promise.resolve([parentNode]); + } else if (options.parent === 'parent-container') { + return Promise.resolve([childNode]); + } + return Promise.resolve([]); + }); + + apiClient.fetchScopeNode.mockImplementation((scopeNodeId: string) => { + if (scopeNodeId === 'child-1') { + return Promise.resolve(childNode); + } else if (scopeNodeId === 'parent-container') { + return Promise.resolve(parentNode); + } + return Promise.resolve(undefined); + }); + + await service.changeScopes(['scope-1'], 'parent-container', 'child-1'); + + // First open + await service.open(); + + // Close and open again + service.closeAndReset(); + await service.open(); + + // The key: childrenLoaded flag should prevent redundant fetches + // Verify the flag is set correctly + expect(service.state.tree?.children?.['parent-container']?.childrenLoaded).toBe(true); + }); }); describe('closeAndReset', () => { diff --git a/public/app/features/scopes/selector/ScopesSelectorService.ts b/public/app/features/scopes/selector/ScopesSelectorService.ts index ede86a50135..17f36639f59 100644 --- a/public/app/features/scopes/selector/ScopesSelectorService.ts +++ b/public/app/features/scopes/selector/ScopesSelectorService.ts @@ -218,6 +218,8 @@ export class ScopesSelectorService extends ScopesServiceBase 0) { const fetchedScopes = await this.apiClient.fetchMultipleScopes(scopes.map((s) => s.scopeId)); + + // Fetch the scope node if it is not available + let newNodesState = { ...this.state.nodes }; + let scopeNode = scopes[0]?.scopeNodeId ? this.state.nodes[scopes[0]?.scopeNodeId] : undefined; + + if (!scopeNode && config.featureToggles.useScopeSingleNodeEndpoint && scopes[0]?.scopeNodeId) { + scopeNode = await this.apiClient.fetchScopeNode(scopes[0]?.scopeNodeId); + if (scopeNode) { + newNodesState[scopeNode.metadata.name] = scopeNode; + } + } + const newScopesState = { ...this.state.scopes }; for (const scope of fetchedScopes) { newScopesState[scope.metadata.name] = scope; } - const scopeNode = scopes[0]?.scopeNodeId ? this.state.nodes[scopes[0]?.scopeNodeId] : undefined; - - // If parentNodeId is provided, use it directly as the parent node // If not provided, try to get the parent from the scope node // When selected from recent scopes, we don't have access to the scope node (if it hasn't been loaded), but we do have access to the parent node from local storage. - const parentNodeId = scopes[0]?.parentNodeId || scopeNode?.spec.parentName; + const parentNodeId = scopes[0]?.parentNodeId ?? scopeNode?.spec.parentName; const parentNode = parentNodeId ? this.state.nodes[parentNodeId] : undefined; - this.addRecentScopes(fetchedScopes, parentNode); + this.addRecentScopes(fetchedScopes, parentNode, scopes[0]?.scopeNodeId); this.updateState({ scopes: newScopesState, loading: false }); } }; @@ -398,16 +408,19 @@ export class ScopesSelectorService extends ScopesServiceBase { + private addRecentScopes = (scopes: Scope[], parentNode?: ScopeNode, scopeNodeId?: string) => { if (scopes.length === 0) { return; } const newScopes: RecentScope[] = structuredClone(scopes); - // Set parent node for the first scope. We don't currently support multiple parent nodes being displayed, hence we only add for the first one + // Set parent node and scopeNodeId for the first scope. We don't currently support multiple parent nodes being displayed, hence we only add for the first one if (parentNode) { newScopes[0].parentNode = parentNode; } + if (scopeNodeId) { + newScopes[0].scopeNodeId = scopeNodeId; + } const RECENT_SCOPES_MAX_LENGTH = 5; @@ -452,15 +465,31 @@ export class ScopesSelectorService extends ScopesServiceBase { - if (!this.state.tree.children || Object.keys(this.state.tree.children).length === 0) { + if ( + !this.state.tree.children || + Object.keys(this.state.tree.children).length === 0 || + !this.state.tree.childrenLoaded + ) { await this.filterNode('', ''); } + // If the scopeNode isn't avilable, fetch it and add it to the nodes cache + if ( + config.featureToggles.useScopeSingleNodeEndpoint && + this.state.selectedScopes[0]?.scopeNodeId && + !this.state.nodes[this.state.selectedScopes[0].scopeNodeId] + ) { + const scopeNode = await this.apiClient.fetchScopeNode(this.state.selectedScopes[0].scopeNodeId); + if (scopeNode) { + this.updateState({ nodes: { ...this.state.nodes, [scopeNode.metadata.name]: scopeNode } }); + } + } + // First close all nodes let newTree = closeNodes(this.state.tree); - if (this.state.selectedScopes.length && this.state.selectedScopes[0].parentNodeId) { - let path = getPathOfNode(this.state.selectedScopes[0].parentNodeId, this.state.nodes); + if (this.state.selectedScopes.length && this.state.selectedScopes[0].scopeNodeId) { + let path = getPathOfNode(this.state.selectedScopes[0].scopeNodeId, this.state.nodes); // Get node at path, and request it's children if they don't exist yet let nodeAtPath = treeNodeAtPath(newTree, path); @@ -468,22 +497,30 @@ export class ScopesSelectorService extends ScopesServiceBase n.metadata.name); + path.unshift(''); nodeAtPath = treeNodeAtPath(newTree, path); } catch (error) { console.error('Failed to resolve path to root', error); } } - if (nodeAtPath && !nodeAtPath.children) { + // We have resolved to root, which means the parent node should be available + let parentPath = path.slice(0, -1); + let parentNodeAtPath = treeNodeAtPath(newTree, parentPath); + + if (parentNodeAtPath && !parentNodeAtPath.childrenLoaded) { // This will update the tree with the children - const { newTree: newTreeWithChildren } = await this.loadNodeChildren(path, nodeAtPath, ''); + const { newTree: newTreeWithChildren } = await this.loadNodeChildren(parentPath, parentNodeAtPath, ''); newTree = newTreeWithChildren; } // Expand the nodes to the selected scope - must be done after loading children try { - newTree = expandNodes(newTree, path); + newTree = expandNodes(newTree, parentPath); } catch (error) { console.error('Failed to expand nodes', error); } diff --git a/public/app/features/scopes/selector/ScopesTree.tsx b/public/app/features/scopes/selector/ScopesTree.tsx index 928827b3d32..dd2fd61184c 100644 --- a/public/app/features/scopes/selector/ScopesTree.tsx +++ b/public/app/features/scopes/selector/ScopesTree.tsx @@ -25,7 +25,7 @@ export interface ScopesTreeProps { // Recent scopes are only shown at the root node recentScopes?: Scope[][]; - onRecentScopesSelect?: (scopeIds: string[], parentNodeId?: string) => void; + onRecentScopesSelect?: (scopeIds: string[], parentNodeId?: string, scopeNodeId?: string) => void; toggleExpandedNode: (scopeNodeId: string) => void; } diff --git a/public/app/features/scopes/selector/scopesTreeUtils.test.ts b/public/app/features/scopes/selector/scopesTreeUtils.test.ts index 84f6578efbb..ca96868d5c0 100644 --- a/public/app/features/scopes/selector/scopesTreeUtils.test.ts +++ b/public/app/features/scopes/selector/scopesTreeUtils.test.ts @@ -237,5 +237,120 @@ describe('scopesTreeUtils', () => { expect(newTree.children?.child1.expanded).toBe(false); expect(newTree.children?.child1.children?.grandchild1.expanded).toBe(false); }); + + it('should set childrenLoaded to false for newly inserted nodes', () => { + const tree: TreeNode = { + expanded: false, + scopeNodeId: 'root', + query: '', + children: {}, + }; + + const path: ScopeNode[] = [ + { + metadata: { name: 'child1' }, + spec: { + parentName: 'root', + nodeType: 'container', + title: 'Child 1', + }, + }, + { + metadata: { name: 'grandchild1' }, + spec: { + parentName: 'child1', + nodeType: 'container', + title: 'Grandchild 1', + }, + }, + ]; + + const newTree = insertPathNodesIntoTree(tree, path); + + // Since we only handle insertion, it should never be true + expect(newTree.childrenLoaded).toBe(false); + + // Newly inserted nodes should have childrenLoaded set to false + expect(newTree.children?.child1.childrenLoaded).toBe(false); + expect(newTree.children?.child1.children?.grandchild1.childrenLoaded).toBe(false); + }); + + it('should preserve existing children when inserting path', () => { + const tree: TreeNode = { + expanded: true, + scopeNodeId: 'root', + query: '', + childrenLoaded: true, + children: { + existingChild: { + expanded: false, + scopeNodeId: 'existingChild', + query: '', + childrenLoaded: true, + }, + }, + }; + + const path: ScopeNode[] = [ + { + metadata: { name: 'newChild' }, + spec: { + parentName: 'root', + nodeType: 'container', + title: 'New Child', + }, + }, + ]; + + const newTree = insertPathNodesIntoTree(tree, path); + + // Existing child should still be there + expect(newTree.children?.existingChild).toBeDefined(); + expect(newTree.children?.existingChild.childrenLoaded).toBe(true); + + // New child should be added + expect(newTree.children?.newChild).toBeDefined(); + expect(newTree.children?.newChild.childrenLoaded).toBe(false); + + // Since we only handle insertion, it should never be true + expect(newTree.childrenLoaded).toBe(true); + }); + + it('should handle empty path', () => { + const tree: TreeNode = { + expanded: false, + scopeNodeId: 'root', + query: '', + children: {}, + }; + + const path: ScopeNode[] = []; + + const newTree = insertPathNodesIntoTree(tree, path); + + // Tree should remain unchanged except for childrenLoaded + expect(newTree.scopeNodeId).toBe('root'); + expect(newTree.childrenLoaded).toBeUndefined(); + }); + + it('should maintain the childrenLoaded value of the root node when inserting path', () => { + const tree: TreeNode = { + expanded: false, + scopeNodeId: 'root', + query: '', + childrenLoaded: true, + }; + + const path: ScopeNode[] = [ + { + metadata: { name: 'child1' }, + spec: { parentName: 'root', nodeType: 'container', title: 'Child 1' }, + }, + ]; + + const newTree = insertPathNodesIntoTree(tree, path); + + expect(newTree.childrenLoaded).toBe(true); + }); }); }); diff --git a/public/app/features/scopes/selector/scopesTreeUtils.ts b/public/app/features/scopes/selector/scopesTreeUtils.ts index d9184889170..8824742505d 100644 --- a/public/app/features/scopes/selector/scopesTreeUtils.ts +++ b/public/app/features/scopes/selector/scopesTreeUtils.ts @@ -126,6 +126,7 @@ export const insertPathNodesIntoTree = (tree: TreeNode, path: ScopeNode[]) => { treeNode.children = { ...treeNode.children }; if (!childNodeName) { console.warn('Failed to insert full path into tree. Did not find child to' + stringPath[index]); + treeNode.childrenLoaded = treeNode.childrenLoaded ?? false; return treeNode; } treeNode.children[childNodeName] = { @@ -133,7 +134,9 @@ export const insertPathNodesIntoTree = (tree: TreeNode, path: ScopeNode[]) => { scopeNodeId: childNodeName, query: '', children: undefined, + childrenLoaded: false, }; + treeNode.childrenLoaded = treeNode.childrenLoaded ?? false; return treeNode; }); } diff --git a/public/app/features/scopes/selector/types.ts b/public/app/features/scopes/selector/types.ts index 8a999bc98fb..b5a47b8a4e1 100644 --- a/public/app/features/scopes/selector/types.ts +++ b/public/app/features/scopes/selector/types.ts @@ -8,7 +8,7 @@ export type ScopesMap = Record; export interface SelectedScope { scopeId: string; scopeNodeId?: string; - // @deprecated Used to display title next to selected scope. scopeNodeId is used to resolve this anyways. Remove if we can confirm it doesn't break anything. + // Used for recent scopes functionality when scope node isn't loaded yet parentNodeId?: string; } @@ -17,10 +17,13 @@ export interface TreeNode { expanded: boolean; query: string; children?: Record; + // Check if we have loaded all the children. Used when resolving to root. + childrenLoaded?: boolean; } export interface RecentScope extends Scope { parentNode?: ScopeNode; + scopeNodeId?: string; } // Zod schemas for type validation @@ -64,4 +67,5 @@ export const ScopeNodeSchema = z.object({ export const RecentScopeSchema = ScopeSchema.extend({ parentNode: ScopeNodeSchema.optional(), + scopeNodeId: z.string().optional(), }); diff --git a/public/app/features/scopes/selector/useScopesHighlighting.tsx b/public/app/features/scopes/selector/useScopesHighlighting.tsx index c0b8aef8002..6aac9bddb22 100644 --- a/public/app/features/scopes/selector/useScopesHighlighting.tsx +++ b/public/app/features/scopes/selector/useScopesHighlighting.tsx @@ -62,7 +62,7 @@ export function useScopesHighlighting({ : undefined; if (parentNode?.spec.disableMultiSelect && changeScopes && scopeNodes[nodeId]?.spec.linkId) { - changeScopes([scopeNodes[nodeId].spec.linkId], parentNode.metadata.name); + changeScopes([scopeNodes[nodeId].spec.linkId], undefined, nodeId); return; } diff --git a/public/app/features/scopes/tests/selector.test.ts b/public/app/features/scopes/tests/selector.test.ts index b7083a7fc13..f12f848657a 100644 --- a/public/app/features/scopes/tests/selector.test.ts +++ b/public/app/features/scopes/tests/selector.test.ts @@ -91,7 +91,7 @@ describe('Selector', () => { it('Should initializae values from the URL', async () => { const mockLocation = { pathname: '/dashboard', - search: '?scopes=grafana&scope_parent=applications', + search: '?scopes=grafana&scope_node=applications-grafana', hash: '', key: 'test', state: null, @@ -105,6 +105,7 @@ describe('Selector', () => { // Lowercase because we don't have any backend that returns the correct case, then it falls back to the value in the URL expectScopesSelectorValue('grafana'); await openSelector(); + //screen.debug(undefined, 100000); expectResultApplicationsGrafanaSelected(); jest.spyOn(locationService, 'getLocation').mockRestore(); diff --git a/public/app/features/scopes/tests/tree.test.ts b/public/app/features/scopes/tests/tree.test.ts index f0f46e2dd9c..f11ec276c0c 100644 --- a/public/app/features/scopes/tests/tree.test.ts +++ b/public/app/features/scopes/tests/tree.test.ts @@ -194,6 +194,45 @@ describe('Tree', () => { expectResultApplicationsMimirPresent(); }); + it('Opens to a selected scope and shows all sibling nodes', async () => { + // Select a scope and apply + await openSelector(); + await expandResultApplications(); + await selectResultApplicationsMimir(); + await applyScopes(); + + // Reopen selector - should show the selected scope AND all its siblings + await openSelector(); + + // Verify all sibling nodes (Grafana, Mimir, Cloud) are visible + expectResultApplicationsGrafanaPresent(); + expectResultApplicationsMimirPresent(); + expectResultApplicationsCloudPresent(); + + // Verify the Applications container is expanded + expect(screen.getByRole('button', { name: 'Applications' })).toBeInTheDocument(); + }); + + it('Opens to a nested selected scope and shows all siblings at that level', async () => { + // Select a nested scope + await openSelector(); + await expandResultApplications(); + await expandResultApplicationsCloud(); + await selectResultApplicationsCloudDev(); + await applyScopes(); + + // Reopen selector - should expand to Cloud and show all its children + await openSelector(); + + // Verify the full path is expanded + expect(screen.getByRole('button', { name: 'Cloud' })).toBeInTheDocument(); + + // Verify all siblings at the Cloud level are visible + // The test should verify that when Cloud is expanded, we see all its children + // (This depends on what siblings Dev has - at minimum, we should see Dev itself) + expect(screen.getByRole('treeitem', { name: 'Dev' })).toBeInTheDocument(); + }); + it('Persists a scope', async () => { await openSelector(); await expandResultApplications(); @@ -291,7 +330,7 @@ describe('Tree', () => { expectScopesHeadline('Recommended'); }); - it('Should open to a specific path when scopes and scope_parent are provided', async () => { + it('Should open to a specific path when scopes and scope_node are applied', async () => { await openSelector(); await expandResultApplications(); await expandResultApplicationsCloud(); diff --git a/public/app/features/scopes/tests/utils/mocks.ts b/public/app/features/scopes/tests/utils/mocks.ts index 0a0e85b1791..c1afb8b0de2 100644 --- a/public/app/features/scopes/tests/utils/mocks.ts +++ b/public/app/features/scopes/tests/utils/mocks.ts @@ -412,6 +412,12 @@ export const getMock = jest return mocksScopes.find((scope) => scope.metadata.name.toLowerCase() === name.toLowerCase()) ?? {}; } + if (url.startsWith('/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes/')) { + const name = url.replace('/apis/scope.grafana.app/v0alpha1/namespaces/default/scopenodes/', ''); + + return mocksNodes.find((node) => node.metadata.name === name); + } + if (url.startsWith('/apis/scope.grafana.app/v0alpha1/namespaces/default/find/scope_dashboard_bindings')) { return { items: mocksScopeDashboardBindings.filter(({ spec: { scope: bindingScope } }) => diff --git a/public/app/features/transformers/regression/regressionEditor.tsx b/public/app/features/transformers/regression/regressionEditor.tsx index 909e2b69285..a1a27af1d39 100644 --- a/public/app/features/transformers/regression/regressionEditor.tsx +++ b/public/app/features/transformers/regression/regressionEditor.tsx @@ -120,7 +120,15 @@ export const RegressionTransformerEditor = ({ ); }; -const RegressionField = ({ label, tooltip, children }: { label: string; tooltip?: string; children: ReactElement }) => ( +const RegressionField = ({ + label, + tooltip, + children, +}: { + label: string; + tooltip?: string; + children: ReactElement>; +}) => ( {children} diff --git a/public/app/plugins/datasource/azuremonitor/components/ConfigEditor/DefaultSubscription.tsx b/public/app/plugins/datasource/azuremonitor/components/ConfigEditor/DefaultSubscription.tsx index 0bd33039bda..91f5240a4b8 100644 --- a/public/app/plugins/datasource/azuremonitor/components/ConfigEditor/DefaultSubscription.tsx +++ b/public/app/plugins/datasource/azuremonitor/components/ConfigEditor/DefaultSubscription.tsx @@ -39,7 +39,7 @@ export const DefaultSubscription = (props: Props) => { let canceled = false; getSubscriptions().then((result) => { if (!canceled) { - updateSubscriptions(result, loadSubscriptionsClicked); + updateSubscriptions(result, Boolean(loadSubscriptionsClicked)); } }); return () => { diff --git a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.test.tsx b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.test.tsx new file mode 100644 index 00000000000..3c472fcb69e --- /dev/null +++ b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.test.tsx @@ -0,0 +1,191 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { + BuilderQueryEditorExpressionType, + BuilderQueryEditorPropertyType, + BuilderQueryEditorReduceExpression, + BuilderQueryEditorReduceParameterTypes, +} from '../../dataquery.gen'; + +import AggregateItem from './AggregateItem'; + +describe('AggregateItem', () => { + const mockColumns = [ + { label: 'TimeGenerated', value: 'TimeGenerated' }, + { label: 'Level', value: 'Level' }, + { label: 'Message', value: 'Message' }, + ]; + + const mockTemplateVariables = { label: '$variable', value: '$variable' }; + + const defaultAggregate: BuilderQueryEditorReduceExpression = { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + property: { + name: 'TimeGenerated', + type: BuilderQueryEditorPropertyType.String, + }, + }; + + const defaultProps = { + aggregate: defaultAggregate, + columns: mockColumns, + onChange: jest.fn(), + onDelete: jest.fn(), + templateVariableOptions: mockTemplateVariables, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders aggregate function select (with column field)', () => { + render(); + expect(screen.getByLabelText('Aggregate function')).toBeInTheDocument(); + expect(screen.getByLabelText('Column')).toBeInTheDocument(); + }); + + it('does not render column select for count aggregates', () => { + const countAggregate = { + ...defaultAggregate, + reduce: { + name: 'count', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Generic, + }, + }; + render(); + expect(screen.queryByLabelText('Column')).not.toBeInTheDocument(); + }); + + it('renders percentile input and OF label for percentile aggregate', () => { + const percentileAggregate: BuilderQueryEditorReduceExpression = { + reduce: { + name: 'percentile', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + parameters: [ + { + type: BuilderQueryEditorExpressionType.Function_parameter, + fieldType: BuilderQueryEditorPropertyType.Number, + value: '95', + }, + { + type: BuilderQueryEditorExpressionType.Function_parameter, + fieldType: BuilderQueryEditorPropertyType.String, + value: 'TimeGenerated', + }, + ], + property: { + name: 'TimeGenerated', + type: BuilderQueryEditorPropertyType.String, + }, + }; + render(); + expect(screen.getByDisplayValue('95')).toBeInTheDocument(); + expect(screen.getByText('OF')).toBeInTheDocument(); + }); + + it('calls onChange when aggregate function changes', async () => { + render(); + + const select = screen.getByLabelText('Aggregate function'); + await userEvent.click(select); + + const avgOption = await screen.findByText('avg'); + await userEvent.click(avgOption); + + expect(defaultProps.onChange).toHaveBeenCalledWith( + expect.objectContaining({ + reduce: expect.objectContaining({ + name: 'avg', + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }), + }) + ); + }); + + it('calls onChange when column changes', async () => { + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + const levelOption = await screen.findByText('Level'); + await userEvent.click(levelOption); + + expect(defaultProps.onChange).toHaveBeenCalledWith( + expect.objectContaining({ + property: expect.objectContaining({ + name: 'Level', + }), + }) + ); + }); + + it('calls onChange when percentile value changes', async () => { + const percentileAggregate: BuilderQueryEditorReduceExpression = { + reduce: { + name: 'percentile', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + parameters: [ + { + type: BuilderQueryEditorExpressionType.Function_parameter, + fieldType: BuilderQueryEditorPropertyType.Number, + value: '95', + }, + { + type: BuilderQueryEditorExpressionType.Function_parameter, + fieldType: BuilderQueryEditorPropertyType.String, + value: 'TimeGenerated', + }, + ], + }; + render(); + + const percentileInput = screen.getByDisplayValue('95'); + await userEvent.clear(percentileInput); + await userEvent.type(percentileInput, '99'); + + expect(defaultProps.onChange).toHaveBeenCalledWith( + expect.objectContaining({ + parameters: expect.arrayContaining([expect.objectContaining({ value: '99' })]), + }) + ); + }); + + it('calls onDelete when delete button clicked', async () => { + render(); + + const deleteButton = screen.getByLabelText('Remove'); + await userEvent.click(deleteButton); + expect(defaultProps.onDelete).toHaveBeenCalledTimes(1); + }); + + it('includes template variables in column options', async () => { + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + expect(await screen.findByText('$variable')).toBeInTheDocument(); + }); + + it('handles array of template variables', async () => { + const arrayTemplateVars = [ + { label: '$var1', value: '$var1' }, + { label: '$var2', value: '$var2' }, + ]; + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + + expect(await screen.findByText('$var1')).toBeInTheDocument(); + }); +}); diff --git a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.tsx b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.tsx index 867098f7574..294c85fdb87 100644 --- a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.tsx +++ b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregateItem.tsx @@ -9,6 +9,7 @@ import { BuilderQueryEditorExpressionType, BuilderQueryEditorPropertyType, BuilderQueryEditorReduceExpression, + BuilderQueryEditorReduceParameterTypes, } from '../../dataquery.gen'; import { aggregateOptions, inputFieldSize } from './utils'; @@ -29,7 +30,7 @@ const AggregateItem: React.FC = ({ templateVariableOptions, }) => { const isPercentile = aggregate.reduce?.name === 'percentile'; - const isCountAggregate = aggregate.reduce?.name?.includes('count'); + const isCountAggregate = aggregate.reduce?.name === 'count'; const [percentileValue, setPercentileValue] = useState(aggregate.parameters?.[0]?.value || ''); const [columnValue, setColumnValue] = useState( @@ -65,8 +66,16 @@ const AggregateItem: React.FC = ({ }; const handleAggregateChange = (funcName?: string) => { + const functionParameterType = + aggregateOptions.find((option) => option.value === (funcName || ''))?.parameterType || + BuilderQueryEditorReduceParameterTypes.Generic; + updateAggregate({ - reduce: { name: funcName || '', type: BuilderQueryEditorPropertyType.Function }, + reduce: { + name: funcName || '', + type: BuilderQueryEditorPropertyType.Function, + parameterType: functionParameterType, + }, }); }; diff --git a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.test.tsx b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.test.tsx new file mode 100644 index 00000000000..ea073e1e8e5 --- /dev/null +++ b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.test.tsx @@ -0,0 +1,293 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { + AzureQueryType, + BuilderQueryEditorExpressionType, + BuilderQueryEditorPropertyType, + BuilderQueryEditorReduceExpression, + BuilderQueryEditorReduceParameterTypes, +} from '../../dataquery.gen'; +import { AzureMonitorQuery } from '../../types/query'; + +import { AggregateSection } from './AggregationSection'; + +describe('AggregationSection', () => { + const mockAllColumns = [ + { name: 'TimeGenerated', type: 'datetime' }, + { name: 'Level', type: 'string' }, + { name: 'Count', type: 'int' }, + { name: 'Duration', type: 'real' }, + ]; + + const mockTemplateVariables = { label: '$variable', value: '$variable' }; + + const createMockQuery = (reduce?: BuilderQueryEditorReduceExpression[]): AzureMonitorQuery => ({ + refId: 'A', + queryType: AzureQueryType.LogAnalytics, + azureLogAnalytics: { + builderQuery: { + from: { + type: BuilderQueryEditorExpressionType.Property, + property: { type: BuilderQueryEditorPropertyType.String, name: 'AppRequests' }, + }, + columns: { + type: BuilderQueryEditorExpressionType.Property, + columns: [], + }, + reduce: { + type: BuilderQueryEditorExpressionType.Reduce, + expressions: reduce || [], + }, + where: { + type: BuilderQueryEditorExpressionType.And, + expressions: [], + }, + groupBy: { + type: BuilderQueryEditorExpressionType.Group_by, + expressions: [], + }, + }, + }, + }); + + const defaultProps = { + query: createMockQuery(), + allColumns: mockAllColumns, + templateVariableOptions: mockTemplateVariables, + buildAndUpdateQuery: jest.fn(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders the aggregate section', () => { + render(); + expect(screen.getByTestId('aggregate-section')).toBeInTheDocument(); + }); + + it('renders empty list when no aggregates exist', () => { + render(); + const addButton = screen.getByRole('button', { name: /add/i }); + expect(addButton).toBeInTheDocument(); + }); + + it('renders existing aggregates', () => { + const existingAggregates: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + property: { + name: 'Count', + type: BuilderQueryEditorPropertyType.String, + }, + }, + { + reduce: { + name: 'avg', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + property: { + name: 'Duration', + type: BuilderQueryEditorPropertyType.String, + }, + }, + ]; + + const queryWithAggregates = createMockQuery(existingAggregates); + render(); + + expect(screen.getAllByLabelText('Aggregate function')).toHaveLength(2); + }); + + it('calls buildAndUpdateQuery when aggregate is added', async () => { + render(); + + const addButton = screen.getByRole('button', { name: /add/i }); + await userEvent.click(addButton); + + expect(defaultProps.buildAndUpdateQuery).toHaveBeenCalledWith({ + reduce: expect.arrayContaining([expect.objectContaining({})]), + }); + }); + + it('calls buildAndUpdateQuery when aggregate is deleted', async () => { + const existingAggregates: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + property: { + name: 'Count', + type: BuilderQueryEditorPropertyType.String, + }, + }, + ]; + const avgAggregate = { + reduce: { + name: 'avg', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + property: { + name: 'Duration', + type: BuilderQueryEditorPropertyType.String, + }, + }; + existingAggregates.push(avgAggregate); + + const queryWithAggregates = createMockQuery(existingAggregates); + render(); + + const deleteButton = (await screen.findAllByLabelText('Remove'))[0]; + await userEvent.click(deleteButton); + + expect(defaultProps.buildAndUpdateQuery).toHaveBeenCalledWith({ + reduce: [avgAggregate], + }); + expect(screen.getAllByLabelText('Aggregate function')).toHaveLength(1); + }); + + it('provides numeric columns for numeric aggregate functions', async () => { + const numericAggregate: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + }, + ]; + + const queryWithAggregate = createMockQuery(numericAggregate); + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('Count')).toBeInTheDocument(); + expect(await screen.getByText('Duration')).toBeInTheDocument(); + + expect(screen.queryByText('Level')).not.toBeInTheDocument(); + }); + + it('provides all columns for generic aggregate functions', async () => { + const genericAggregate: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'min', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Generic, + }, + }, + ]; + + const queryWithAggregate = createMockQuery(genericAggregate); + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('TimeGenerated')).toBeInTheDocument(); + expect(await screen.getByText('Level')).toBeInTheDocument(); + expect(await screen.getByText('Count')).toBeInTheDocument(); + expect(await screen.getByText('Duration')).toBeInTheDocument(); + }); + + it('resets aggregates when table changes', () => { + const existingAggregates: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Numeric, + }, + property: { + name: 'Count', + type: BuilderQueryEditorPropertyType.String, + }, + }, + ]; + + const queryWithAggregates = createMockQuery(existingAggregates); + const { rerender } = render(); + + const newQuery = createMockQuery(existingAggregates); + newQuery.azureLogAnalytics!.builderQuery!.from!.property.name = 'AppEvents'; + + rerender(); + + const addButton = screen.getByRole('button', { name: /add/i }); + expect(addButton).toBeInTheDocument(); + }); + + it('uses selected columns when available', async () => { + const aggregate: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Generic, + }, + }, + ]; + + const query = createMockQuery(aggregate); + query.azureLogAnalytics!.builderQuery = { + ...query.azureLogAnalytics!.builderQuery, + columns: { + columns: ['TimeGenerated', 'Level'], + type: BuilderQueryEditorExpressionType.Property, + }, + }; + + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('TimeGenerated')).toBeInTheDocument(); + expect(await screen.getByText('Level')).toBeInTheDocument(); + + expect(screen.queryByText('Count')).not.toBeInTheDocument(); + expect(screen.queryByText('Duration')).not.toBeInTheDocument(); + }); + + it('falls back to all columns when no columns selected', async () => { + const aggregate: BuilderQueryEditorReduceExpression[] = [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + parameterType: BuilderQueryEditorReduceParameterTypes.Generic, + }, + }, + ]; + + const query = createMockQuery(aggregate); + query.azureLogAnalytics!.builderQuery = { + ...query.azureLogAnalytics!.builderQuery, + columns: { + columns: [], + type: BuilderQueryEditorExpressionType.Property, + }, + }; + + render(); + + const columnSelect = screen.getByLabelText('Column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('TimeGenerated')).toBeInTheDocument(); + expect(await screen.getByText('Level')).toBeInTheDocument(); + expect(await screen.getByText('Count')).toBeInTheDocument(); + expect(await screen.getByText('Duration')).toBeInTheDocument(); + }); +}); diff --git a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.tsx b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.tsx index 4f3a1050a14..6910792685d 100644 --- a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.tsx +++ b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/AggregationSection.tsx @@ -4,12 +4,12 @@ import { SelectableValue } from '@grafana/data'; import { t } from '@grafana/i18n'; import { EditorField, EditorFieldGroup, EditorList, EditorRow } from '@grafana/plugin-ui'; -import { BuilderQueryEditorReduceExpression } from '../../dataquery.gen'; +import { BuilderQueryEditorReduceExpression, BuilderQueryEditorReduceParameterTypes } from '../../dataquery.gen'; import { AzureLogAnalyticsMetadataColumn } from '../../types/logAnalyticsMetadata'; import { AzureMonitorQuery } from '../../types/query'; import AggregateItem from './AggregateItem'; -import { BuildAndUpdateOptions } from './utils'; +import { BuildAndUpdateOptions, isNumericColumn } from './utils'; interface AggregateSectionProps { query: AzureMonitorQuery; @@ -43,6 +43,10 @@ export const AggregateSection: React.FC = ({ const availableColumns: Array> = builderQuery?.columns?.columns?.length ? builderQuery.columns.columns.map((col) => ({ label: col, value: col })) : allColumns.map((col) => ({ label: col.name, value: col.name })); + const numericColumns: Array> = allColumns.filter(isNumericColumn).map((col) => ({ + label: col.name, + value: col.name, + })); const onChange = (newItems: Array>) => { setAggregates(newItems); @@ -82,7 +86,12 @@ export const AggregateSection: React.FC = ({ @@ -93,6 +102,7 @@ export const AggregateSection: React.FC = ({ function makeRenderAggregate( availableColumns: Array>, + numericColumns: Array>, onDeleteAggregate: (aggregate: BuilderQueryEditorReduceExpression) => void, templateVariableOptions: SelectableValue ) { @@ -105,7 +115,11 @@ function makeRenderAggregate( aggregate={item} onChange={onChange} onDelete={() => onDeleteAggregate(item)} - columns={availableColumns} + columns={ + item.reduce?.name && item.reduce.parameterType === BuilderQueryEditorReduceParameterTypes.Numeric + ? numericColumns + : availableColumns + } templateVariableOptions={templateVariableOptions} /> ); diff --git a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/OrderBySection.test.tsx b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/OrderBySection.test.tsx new file mode 100644 index 00000000000..471470aed86 --- /dev/null +++ b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/OrderBySection.test.tsx @@ -0,0 +1,373 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { + AzureQueryType, + BuilderQueryEditorExpressionType, + BuilderQueryEditorOrderByExpression, + BuilderQueryEditorOrderByOptions, + BuilderQueryEditorPropertyType, +} from '../../dataquery.gen'; +import { AzureMonitorQuery } from '../../types/query'; + +import { OrderBySection } from './OrderBySection'; + +describe('OrderBySection', () => { + const mockAllColumns = [ + { name: 'TimeGenerated', type: 'datetime' }, + { name: 'Level', type: 'string' }, + { name: 'Count', type: 'int' }, + { name: 'Duration', type: 'real' }, + ]; + + const createMockQuery = (orderBy?: BuilderQueryEditorOrderByExpression[]): AzureMonitorQuery => ({ + refId: 'A', + queryType: AzureQueryType.LogAnalytics, + azureLogAnalytics: { + builderQuery: { + from: { + type: BuilderQueryEditorExpressionType.Property, + property: { type: BuilderQueryEditorPropertyType.String, name: 'AppRequests' }, + }, + columns: { + type: BuilderQueryEditorExpressionType.Property, + columns: ['TimeGenerated', 'Level', 'Count'], + }, + orderBy: { + type: BuilderQueryEditorExpressionType.Order_by, + expressions: orderBy || [], + }, + reduce: { + type: BuilderQueryEditorExpressionType.Reduce, + expressions: [], + }, + groupBy: { + type: BuilderQueryEditorExpressionType.Group_by, + expressions: [], + }, + where: { + type: BuilderQueryEditorExpressionType.And, + expressions: [], + }, + }, + }, + }); + + const defaultProps = { + query: createMockQuery(), + allColumns: mockAllColumns, + buildAndUpdateQuery: jest.fn(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders the order by section', () => { + render(); + expect(screen.getByText('Order By')).toBeInTheDocument(); + }); + + it('renders add button when no order by exists', () => { + render(); + const addButton = screen.getByLabelText('Add order by'); + expect(addButton).toBeInTheDocument(); + }); + + it('renders existing order by expressions', () => { + const existingOrderBy: BuilderQueryEditorOrderByExpression[] = [ + { + property: { name: 'TimeGenerated', type: BuilderQueryEditorPropertyType.String }, + order: BuilderQueryEditorOrderByOptions.Desc, + type: BuilderQueryEditorExpressionType.Order_by, + }, + { + property: { name: 'Level', type: BuilderQueryEditorPropertyType.String }, + order: BuilderQueryEditorOrderByOptions.Asc, + type: BuilderQueryEditorExpressionType.Order_by, + }, + ]; + + const queryWithOrderBy = createMockQuery(existingOrderBy); + render(); + + expect(screen.getAllByLabelText('Order by column')).toHaveLength(2); + expect(screen.getAllByLabelText('Order Direction')).toHaveLength(2); + expect(screen.getByText('TimeGenerated')).toBeInTheDocument(); + expect(screen.getByText('Level')).toBeInTheDocument(); + }); + + it('calls buildAndUpdateQuery when order by is added', async () => { + render(); + + const addButton = screen.getByLabelText('Add order by'); + await userEvent.click(addButton); + + expect(defaultProps.buildAndUpdateQuery).toHaveBeenCalledWith({ + orderBy: expect.arrayContaining([ + expect.objectContaining({ + property: expect.objectContaining({ name: '' }), + order: BuilderQueryEditorOrderByOptions.Asc, + }), + ]), + }); + }); + + it('calls buildAndUpdateQuery when column is changed', async () => { + const existingOrderBy: BuilderQueryEditorOrderByExpression[] = [ + { + property: { name: 'TimeGenerated', type: BuilderQueryEditorPropertyType.String }, + order: BuilderQueryEditorOrderByOptions.Desc, + type: BuilderQueryEditorExpressionType.Order_by, + }, + ]; + + const queryWithOrderBy = createMockQuery(existingOrderBy); + render(); + + const columnSelect = screen.getByLabelText('Order by column'); + await userEvent.click(columnSelect); + + const levelOption = await screen.getByText('Level'); + await userEvent.click(levelOption); + + expect(defaultProps.buildAndUpdateQuery).toHaveBeenCalledWith({ + orderBy: expect.arrayContaining([ + expect.objectContaining({ + property: expect.objectContaining({ name: 'Level' }), + }), + ]), + }); + }); + + it('calls buildAndUpdateQuery when order direction is changed', async () => { + const existingOrderBy: BuilderQueryEditorOrderByExpression[] = [ + { + property: { name: 'TimeGenerated', type: BuilderQueryEditorPropertyType.String }, + order: BuilderQueryEditorOrderByOptions.Asc, + type: BuilderQueryEditorExpressionType.Order_by, + }, + ]; + + const queryWithOrderBy = createMockQuery(existingOrderBy); + render(); + + const orderSelect = screen.getByLabelText('Order Direction'); + await userEvent.click(orderSelect); + + const descOption = await screen.getByText('Descending'); + await userEvent.click(descOption); + + expect(defaultProps.buildAndUpdateQuery).toHaveBeenCalledWith({ + orderBy: expect.arrayContaining([ + expect.objectContaining({ + order: BuilderQueryEditorOrderByOptions.Desc, + }), + ]), + }); + }); + + it('calls buildAndUpdateQuery when order by is deleted', async () => { + const existingOrderBy: BuilderQueryEditorOrderByExpression[] = [ + { + property: { name: 'TimeGenerated', type: BuilderQueryEditorPropertyType.String }, + order: BuilderQueryEditorOrderByOptions.Desc, + type: BuilderQueryEditorExpressionType.Order_by, + }, + { + property: { name: 'Level', type: BuilderQueryEditorPropertyType.String }, + order: BuilderQueryEditorOrderByOptions.Asc, + type: BuilderQueryEditorExpressionType.Order_by, + }, + ]; + + const queryWithOrderBy = createMockQuery(existingOrderBy); + render(); + + const removeButtons = screen.getAllByLabelText('Remove order by'); + await userEvent.click(removeButtons[0]); + + expect(defaultProps.buildAndUpdateQuery).toHaveBeenCalledWith({ + orderBy: [ + expect.objectContaining({ + property: expect.objectContaining({ name: 'Level' }), + }), + ], + }); + }); + + it('uses group by columns when available', async () => { + const query = createMockQuery(); + query.azureLogAnalytics!.builderQuery!.groupBy = { + type: BuilderQueryEditorExpressionType.Group_by, + expressions: [ + { + property: { name: 'Level', type: BuilderQueryEditorPropertyType.String }, + type: BuilderQueryEditorExpressionType.Group_by, + }, + ], + }; + + render(); + + const addButton = screen.getByLabelText('Add order by'); + await userEvent.click(addButton); + + const columnSelect = screen.getByLabelText('Order by column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('Level')).toBeInTheDocument(); + }); + + it('uses aggregate columns when available', async () => { + const query = createMockQuery(); + query.azureLogAnalytics!.builderQuery!.reduce = { + type: BuilderQueryEditorExpressionType.Reduce, + expressions: [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + }, + property: { name: 'Count', type: BuilderQueryEditorPropertyType.String }, + }, + ], + }; + + render(); + + const addButton = screen.getByLabelText('Add order by'); + await userEvent.click(addButton); + + const columnSelect = screen.getByLabelText('Order by column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('Count')).toBeInTheDocument(); + }); + + it('uses both group by and aggregate columns when available', async () => { + const query = createMockQuery(); + query.azureLogAnalytics!.builderQuery!.groupBy = { + type: BuilderQueryEditorExpressionType.Group_by, + expressions: [ + { + property: { name: 'Level', type: BuilderQueryEditorPropertyType.String }, + type: BuilderQueryEditorExpressionType.Group_by, + }, + ], + }; + query.azureLogAnalytics!.builderQuery!.reduce = { + type: BuilderQueryEditorExpressionType.Reduce, + expressions: [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + }, + property: { name: 'Count', type: BuilderQueryEditorPropertyType.String }, + }, + ], + }; + + render(); + + const addButton = screen.getByLabelText('Add order by'); + await userEvent.click(addButton); + + const columnSelect = screen.getByLabelText('Order by column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('Level')).toBeInTheDocument(); + expect(await screen.getByText('Count')).toBeInTheDocument(); + }); + + it('does not duplicate available columns', async () => { + const query = createMockQuery(); + query.azureLogAnalytics!.builderQuery!.groupBy = { + type: BuilderQueryEditorExpressionType.Group_by, + expressions: [ + { + property: { name: 'Level', type: BuilderQueryEditorPropertyType.String }, + type: BuilderQueryEditorExpressionType.Group_by, + }, + ], + }; + query.azureLogAnalytics!.builderQuery!.reduce = { + type: BuilderQueryEditorExpressionType.Reduce, + expressions: [ + { + reduce: { + name: 'sum', + type: BuilderQueryEditorPropertyType.Function, + }, + property: { name: 'Level', type: BuilderQueryEditorPropertyType.String }, + }, + ], + }; + + render(); + + const addButton = screen.getByLabelText('Add order by'); + await userEvent.click(addButton); + + const columnSelect = screen.getByLabelText('Order by column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('Level')).toBeInTheDocument(); + }); + + it('uses selected columns when no group by or aggregates', async () => { + const query = createMockQuery(); + query.azureLogAnalytics!.builderQuery!.columns!.columns = ['TimeGenerated', 'Level']; + + render(); + + const addButton = screen.getByLabelText('Add order by'); + await userEvent.click(addButton); + + const columnSelect = screen.getByLabelText('Order by column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('TimeGenerated')).toBeInTheDocument(); + expect(await screen.getByText('Level')).toBeInTheDocument(); + }); + + it('falls back to all columns when no other columns available', async () => { + const query = createMockQuery(); + query.azureLogAnalytics!.builderQuery!.columns!.columns = []; + + render(); + + const addButton = screen.getByLabelText('Add order by'); + await userEvent.click(addButton); + + const columnSelect = screen.getByLabelText('Order by column'); + await userEvent.click(columnSelect); + + expect(await screen.getByText('TimeGenerated')).toBeInTheDocument(); + expect(await screen.getByText('Level')).toBeInTheDocument(); + expect(await screen.getByText('Count')).toBeInTheDocument(); + expect(await screen.getByText('Duration')).toBeInTheDocument(); + }); + + it('resets order by when table changes', () => { + const existingOrderBy: BuilderQueryEditorOrderByExpression[] = [ + { + property: { name: 'TimeGenerated', type: BuilderQueryEditorPropertyType.String }, + order: BuilderQueryEditorOrderByOptions.Desc, + type: BuilderQueryEditorExpressionType.Order_by, + }, + ]; + + const queryWithOrderBy = createMockQuery(existingOrderBy); + const { rerender } = render(); + + const newQuery = createMockQuery(existingOrderBy); + newQuery.azureLogAnalytics!.builderQuery!.from!.property.name = 'AppEvents'; + + rerender(); + + const addButton = screen.getByLabelText('Add order by'); + expect(addButton).toBeInTheDocument(); + }); +}); diff --git a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/OrderBySection.tsx b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/OrderBySection.tsx index 98587b1401f..ed8cde5ab39 100644 --- a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/OrderBySection.tsx +++ b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/OrderBySection.tsx @@ -45,16 +45,35 @@ export const OrderBySection: React.FC = ({ query, allColumn const aggregateColumns = builderQuery?.reduce?.expressions?.map((r) => r.property?.name) || []; const selectedColumns = builderQuery?.columns?.columns || []; - const allAvailableColumns = - groupByColumns.length > 0 - ? groupByColumns - : aggregateColumns.length > 0 - ? aggregateColumns - : selectedColumns.length > 0 - ? selectedColumns - : allColumns.map((col) => col.name); + const allAvailableColumns = new Set(); + if (groupByColumns.length > 0) { + groupByColumns.forEach((col) => { + if (col) { + allAvailableColumns.add(col); + } + }); + } + if (aggregateColumns.length > 0) { + aggregateColumns.forEach((col) => { + if (col) { + allAvailableColumns.add(col); + } + }); + } + if (allAvailableColumns.size === 0 && selectedColumns.length > 0) { + selectedColumns.forEach((col) => { + if (col) { + allAvailableColumns.add(col); + } + }); + } + if (allAvailableColumns.size === 0) { + allColumns.forEach((col) => { + allAvailableColumns.add(col.name); + }); + } - const columnOptions = allAvailableColumns.map((col) => ({ + const columnOptions = Array.from(allAvailableColumns).map((col) => ({ label: col, value: col, })); diff --git a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/utils.ts b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/utils.ts index 062dac286f9..cb660fb98e9 100644 --- a/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/utils.ts +++ b/public/app/plugins/datasource/azuremonitor/components/LogsQueryBuilder/utils.ts @@ -9,6 +9,7 @@ import { BuilderQueryEditorPropertyExpression, BuilderQueryEditorPropertyType, BuilderQueryEditorReduceExpression, + BuilderQueryEditorReduceParameterTypes, BuilderQueryEditorWhereExpression, BuilderQueryExpression, } from '../../dataquery.gen'; @@ -93,12 +94,17 @@ export interface BuildAndUpdateOptions { } export const aggregateOptions = [ - { label: 'sum', value: 'sum' }, - { label: 'avg', value: 'avg' }, - { label: 'percentile', value: 'percentile' }, - { label: 'count', value: 'count' }, - { label: 'min', value: 'min' }, - { label: 'max', value: 'max' }, - { label: 'dcount', value: 'dcount' }, - { label: 'stdev', value: 'stdev' }, + { label: 'sum', value: 'sum', parameterType: BuilderQueryEditorReduceParameterTypes.Numeric }, + { label: 'avg', value: 'avg', parameterType: BuilderQueryEditorReduceParameterTypes.Numeric }, + { label: 'percentile', value: 'percentile', parameterType: BuilderQueryEditorReduceParameterTypes.Numeric }, + { label: 'stdev', value: 'stdev', parameterType: BuilderQueryEditorReduceParameterTypes.Numeric }, + { label: 'min', value: 'min', parameterType: BuilderQueryEditorReduceParameterTypes.Generic }, + { label: 'max', value: 'max', parameterType: BuilderQueryEditorReduceParameterTypes.Generic }, + { label: 'count', value: 'count', parameterType: BuilderQueryEditorReduceParameterTypes.Generic }, + { label: 'dcount', value: 'dcount', parameterType: BuilderQueryEditorReduceParameterTypes.Generic }, ]; + +export const isNumericColumn = (column: AzureLogAnalyticsMetadataColumn): boolean => { + const numericTypes = ['decimal', 'int', 'long', 'real']; + return numericTypes.includes(column.type); +}; diff --git a/public/app/plugins/datasource/azuremonitor/dataquery.cue b/public/app/plugins/datasource/azuremonitor/dataquery.cue index 4fd52d5f297..403fd1ea72e 100644 --- a/public/app/plugins/datasource/azuremonitor/dataquery.cue +++ b/public/app/plugins/datasource/azuremonitor/dataquery.cue @@ -175,10 +175,13 @@ composableKinds: DataQuery: { #BuilderQueryEditorExpressionType: "property" | "operator" | "reduce" | "function_parameter" | "group_by" | "or" | "and" | "order_by" @cuetsy(kind="enum", memberNames:"Property|Operator|Reduce|FunctionParameter|GroupBy|Or|And|OrderBy") #BuilderQueryEditorPropertyType: "number" | "string" | "boolean" | "datetime" | "time_span" | "function" | "interval" @cuetsy(kind="enum", memberNames:"Number|String|Boolean|Datetime|TimeSpan|Function|Interval") #BuilderQueryEditorOrderByOptions: "asc" | "desc" @cuetsy(kind="enum", memberNames:"Asc|Desc") + #BuilderQueryEditorReduceParameterTypes: "generic" | "numeric" @cuetsy(kind="enum", memberNames:"Asc|Desc") #BuilderQueryEditorProperty: { type: #BuilderQueryEditorPropertyType name: string + // Optional parameter type for function properties + parameterType?: #BuilderQueryEditorReduceParameterTypes } @cuetsy(kind="interface") #BuilderQueryEditorPropertyExpression: { diff --git a/public/app/plugins/datasource/azuremonitor/dataquery.gen.ts b/public/app/plugins/datasource/azuremonitor/dataquery.gen.ts index c4b986970ca..2ed7b87a5ce 100644 --- a/public/app/plugins/datasource/azuremonitor/dataquery.gen.ts +++ b/public/app/plugins/datasource/azuremonitor/dataquery.gen.ts @@ -327,8 +327,17 @@ export enum BuilderQueryEditorOrderByOptions { Desc = 'desc', } +export enum BuilderQueryEditorReduceParameterTypes { + Generic = 'generic', + Numeric = 'numeric', +} + export interface BuilderQueryEditorProperty { name: string; + /** + * Optional parameter type for function properties + */ + parameterType?: BuilderQueryEditorReduceParameterTypes; type: BuilderQueryEditorPropertyType; } diff --git a/public/app/plugins/datasource/cloud-monitoring/CloudMonitoringMetricFindQuery.ts b/public/app/plugins/datasource/cloud-monitoring/CloudMonitoringMetricFindQuery.ts index 6131457fb25..5629c3693ad 100644 --- a/public/app/plugins/datasource/cloud-monitoring/CloudMonitoringMetricFindQuery.ts +++ b/public/app/plugins/datasource/cloud-monitoring/CloudMonitoringMetricFindQuery.ts @@ -1,6 +1,7 @@ import { isString } from 'lodash'; import { ALIGNMENT_PERIODS, SELECTORS } from './constants'; +import { ValueTypes, MetricFindQueryTypes } from './dataquery.gen'; import CloudMonitoringDatasource from './datasource'; import { extractServicesFromMetricDescriptors, @@ -9,7 +10,6 @@ import { getLabelKeys, getMetricTypesByService, } from './functions'; -import { ValueTypes, MetricFindQueryTypes } from './types/query'; import { CloudMonitoringVariableQuery, MetricDescriptor } from './types/types'; export default class CloudMonitoringMetricFindQuery { diff --git a/public/app/plugins/datasource/cloud-monitoring/annotationSupport.test.ts b/public/app/plugins/datasource/cloud-monitoring/annotationSupport.test.ts index c187351f957..086a01e2b56 100644 --- a/public/app/plugins/datasource/cloud-monitoring/annotationSupport.test.ts +++ b/public/app/plugins/datasource/cloud-monitoring/annotationSupport.test.ts @@ -1,14 +1,9 @@ import { AnnotationQuery } from '@grafana/data'; import { CloudMonitoringAnnotationSupport } from './annotationSupport'; +import { AlignmentTypes, QueryType, MetricKind, LegacyCloudMonitoringAnnotationQuery } from './dataquery.gen'; import { createMockDatasource } from './mocks/cloudMonitoringDatasource'; -import { - AlignmentTypes, - CloudMonitoringQuery, - QueryType, - MetricKind, - LegacyCloudMonitoringAnnotationQuery, -} from './types/query'; +import { CloudMonitoringQuery } from './types/query'; const query: CloudMonitoringQuery = { refId: 'query', diff --git a/public/app/plugins/datasource/cloud-monitoring/annotationSupport.ts b/public/app/plugins/datasource/cloud-monitoring/annotationSupport.ts index 024b6af060a..8e28fcc159a 100644 --- a/public/app/plugins/datasource/cloud-monitoring/annotationSupport.ts +++ b/public/app/plugins/datasource/cloud-monitoring/annotationSupport.ts @@ -1,8 +1,9 @@ import { AnnotationSupport, AnnotationQuery } from '@grafana/data'; import { AnnotationQueryEditor } from './components/AnnotationQueryEditor'; +import { AlignmentTypes, QueryType, LegacyCloudMonitoringAnnotationQuery } from './dataquery.gen'; import CloudMonitoringDatasource from './datasource'; -import { AlignmentTypes, CloudMonitoringQuery, QueryType, LegacyCloudMonitoringAnnotationQuery } from './types/query'; +import { CloudMonitoringQuery } from './types/query'; // The legacy query format sets the title and text values to empty strings by default. // If the title or text is not undefined at the top-level of the annotation target, diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.test.tsx index e19a5f79cb8..1d5e016097f 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.test.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react'; import { openMenu } from 'react-select-event'; -import { MetricKind, ValueTypes } from '../types/query'; +import { MetricKind, ValueTypes } from '../dataquery.gen'; import { MetricDescriptor } from '../types/types'; import { Aggregation, Props } from './Aggregation'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.tsx index 2d5089f06fc..f68d2981801 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.tsx @@ -4,8 +4,8 @@ import { SelectableValue } from '@grafana/data'; import { EditorField } from '@grafana/plugin-ui'; import { Select } from '@grafana/ui'; +import { ValueTypes } from '../dataquery.gen'; import { getAggregationOptionsByMetric } from '../functions'; -import { ValueTypes } from '../types/query'; import { MetricDescriptor } from '../types/types'; export interface Props { diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Alignment.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Alignment.test.tsx index 96bd3f8d71f..68ea7b17e29 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Alignment.test.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Alignment.test.tsx @@ -4,10 +4,10 @@ import { openMenu } from 'react-select-event'; import { CustomVariableModel } from '@grafana/data'; +import { MetricKind, ValueTypes } from '../dataquery.gen'; import { createMockDatasource } from '../mocks/cloudMonitoringDatasource'; import { createMockMetricDescriptor } from '../mocks/cloudMonitoringMetricDescriptor'; import { createMockTimeSeriesList } from '../mocks/cloudMonitoringQuery'; -import { MetricKind, ValueTypes } from '../types/query'; import { Alignment } from './Alignment'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Alignment.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Alignment.tsx index 1a3d21c3a9d..e5b485be921 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Alignment.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Alignment.tsx @@ -4,9 +4,9 @@ import { SelectableValue } from '@grafana/data'; import { EditorField, EditorFieldGroup } from '@grafana/plugin-ui'; import { ALIGNMENT_PERIODS } from '../constants'; +import { PreprocessorType, TimeSeriesList } from '../dataquery.gen'; import CloudMonitoringDatasource from '../datasource'; import { alignmentPeriodLabel } from '../functions'; -import { PreprocessorType, TimeSeriesList } from '../types/query'; import { CustomMetaData, MetricDescriptor } from '../types/types'; import { AlignmentFunction } from './AlignmentFunction'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/AlignmentFunction.tsx b/public/app/plugins/datasource/cloud-monitoring/components/AlignmentFunction.tsx index 5ab061d55ae..6a0b0ef8d99 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/AlignmentFunction.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/AlignmentFunction.tsx @@ -3,8 +3,8 @@ import { useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; import { Select } from '@grafana/ui'; +import { PreprocessorType, SLOQuery, TimeSeriesList } from '../dataquery.gen'; import { getAlignmentPickerData } from '../functions'; -import { PreprocessorType, SLOQuery, TimeSeriesList } from '../types/query'; import { MetricDescriptor } from '../types/types'; export interface Props { diff --git a/public/app/plugins/datasource/cloud-monitoring/components/AnnotationQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/AnnotationQueryEditor.tsx index cb754445570..6154722f70c 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/AnnotationQueryEditor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/AnnotationQueryEditor.tsx @@ -6,8 +6,9 @@ import { QueryEditorProps, getDefaultTimeRange, toOption } from '@grafana/data'; import { EditorField, EditorRows } from '@grafana/plugin-ui'; import { Input } from '@grafana/ui'; +import { TimeSeriesList, QueryType } from '../dataquery.gen'; import CloudMonitoringDatasource from '../datasource'; -import { TimeSeriesList, CloudMonitoringQuery, QueryType } from '../types/query'; +import { CloudMonitoringQuery } from '../types/query'; import { CloudMonitoringOptions } from '../types/types'; import { AnnotationsHelp } from './AnnotationsHelp'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/GroupBy.tsx b/public/app/plugins/datasource/cloud-monitoring/components/GroupBy.tsx index 356a81d5ade..a504133df57 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/GroupBy.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/GroupBy.tsx @@ -5,8 +5,8 @@ import { EditorField, EditorFieldGroup } from '@grafana/plugin-ui'; import { MultiSelect } from '@grafana/ui'; import { SYSTEM_LABELS } from '../constants'; +import { TimeSeriesList } from '../dataquery.gen'; import { labelsToGroupedOptions } from '../functions'; -import { TimeSeriesList } from '../types/query'; import { MetricDescriptor } from '../types/types'; import { Aggregation } from './Aggregation'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/MetricQueryEditor.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/MetricQueryEditor.test.tsx index 12ed2dfd0aa..80ddb62ed52 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/MetricQueryEditor.test.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/MetricQueryEditor.test.tsx @@ -4,9 +4,9 @@ import { openMenu } from 'react-select-event'; import { getDefaultTimeRange } from '@grafana/data'; +import { QueryType } from '../dataquery.gen'; import { createMockDatasource } from '../mocks/cloudMonitoringDatasource'; import { createMockQuery } from '../mocks/cloudMonitoringQuery'; -import { QueryType } from '../types/query'; import { MetricQueryEditor } from './MetricQueryEditor'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/MetricQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/MetricQueryEditor.tsx index 7cd44f61ffb..74a8f211de0 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/MetricQueryEditor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/MetricQueryEditor.tsx @@ -5,8 +5,9 @@ import { SelectableValue, TimeRange } from '@grafana/data'; import { EditorRows } from '@grafana/plugin-ui'; import { Stack } from '@grafana/ui'; +import { AlignmentTypes, QueryType, TimeSeriesList, TimeSeriesQuery } from '../dataquery.gen'; import CloudMonitoringDatasource from '../datasource'; -import { AlignmentTypes, CloudMonitoringQuery, QueryType, TimeSeriesList, TimeSeriesQuery } from '../types/query'; +import { CloudMonitoringQuery } from '../types/query'; import { CustomMetaData } from '../types/types'; import { AliasBy } from './AliasBy'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.test.tsx index cb3003e9117..837dd8eee80 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.test.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.test.tsx @@ -3,9 +3,9 @@ import userEvent from '@testing-library/user-event'; import { CustomVariableModel } from '@grafana/data'; +import { MetricKind, ValueTypes } from '../dataquery.gen'; import { createMockMetricDescriptor } from '../mocks/cloudMonitoringMetricDescriptor'; import { createMockTimeSeriesList } from '../mocks/cloudMonitoringQuery'; -import { MetricKind, ValueTypes } from '../types/query'; import { Preprocessor } from './Preprocessor'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.tsx index 3ca7d101942..fc7cf80bf78 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.tsx @@ -4,8 +4,8 @@ import { SelectableValue } from '@grafana/data'; import { EditorField } from '@grafana/plugin-ui'; import { RadioButtonGroup } from '@grafana/ui'; +import { PreprocessorType, TimeSeriesList, MetricKind, ValueTypes } from '../dataquery.gen'; import { getAlignmentPickerData } from '../functions'; -import { PreprocessorType, TimeSeriesList, MetricKind, ValueTypes } from '../types/query'; import { MetricDescriptor } from '../types/types'; const NONE_OPTION = { label: 'None', value: PreprocessorType.None }; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/PromQLEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/PromQLEditor.tsx index deaa5e7eaf8..1c97fc1a761 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/PromQLEditor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/PromQLEditor.tsx @@ -4,9 +4,9 @@ import { SelectableValue } from '@grafana/data'; import { EditorField, EditorRow } from '@grafana/plugin-ui'; import { TextArea, Input } from '@grafana/ui'; +import { PromQLQuery } from '../dataquery.gen'; import CloudMonitoringDatasource from '../datasource'; import { selectors } from '../e2e/selectors'; -import { PromQLQuery } from '../types/query'; import { Project } from './Project'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/QueryEditor.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/QueryEditor.test.tsx index 7f410a17e8c..a2b5ac4aa11 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/QueryEditor.test.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/QueryEditor.test.tsx @@ -1,10 +1,10 @@ import { render, waitFor, screen } from '@testing-library/react'; import { select } from 'react-select-event'; +import { QueryType } from '../dataquery.gen'; import { selectors } from '../e2e/selectors'; import { createMockDatasource } from '../mocks/cloudMonitoringDatasource'; import { createMockQuery } from '../mocks/cloudMonitoringQuery'; -import { QueryType } from '../types/query'; import { QueryEditor } from './QueryEditor'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/QueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/QueryEditor.tsx index d0578dea9d4..1aa62a43c0c 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/QueryEditor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/QueryEditor.tsx @@ -6,9 +6,10 @@ import { QueryEditorProps, getDefaultTimeRange, toOption } from '@grafana/data'; import { EditorRows } from '@grafana/plugin-ui'; import { ConfirmModal } from '@grafana/ui'; +import { PromQLQuery, QueryType, SLOQuery } from '../dataquery.gen'; import CloudMonitoringDatasource from '../datasource'; import { selectors } from '../e2e/selectors'; -import { CloudMonitoringQuery, PromQLQuery, QueryType, SLOQuery } from '../types/query'; +import { CloudMonitoringQuery } from '../types/query'; import { CloudMonitoringOptions } from '../types/types'; import { defaultTimeSeriesList, defaultTimeSeriesQuery, MetricQueryEditor } from './MetricQueryEditor'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/QueryHeader.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/QueryHeader.test.tsx index 331ad7c4d4b..2de5f4f703a 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/QueryHeader.test.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/QueryHeader.test.tsx @@ -1,8 +1,8 @@ import { render, screen } from '@testing-library/react'; import { openMenu, select } from 'react-select-event'; +import { QueryType } from '../dataquery.gen'; import { createMockQuery } from '../mocks/cloudMonitoringQuery'; -import { QueryType } from '../types/query'; import { QueryHeader } from './QueryHeader'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/SLO.tsx b/public/app/plugins/datasource/cloud-monitoring/components/SLO.tsx index be4606155d7..1d57172f9b6 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/SLO.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/SLO.tsx @@ -4,8 +4,8 @@ import { SelectableValue } from '@grafana/data'; import { EditorField } from '@grafana/plugin-ui'; import { Select } from '@grafana/ui'; +import { SLOQuery } from '../dataquery.gen'; import CloudMonitoringDatasource from '../datasource'; -import { SLOQuery } from '../types/query'; export interface Props { refId: string; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/SLOQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/SLOQueryEditor.tsx index 1a4ec805596..aac2ee3a570 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/SLOQueryEditor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/SLOQueryEditor.tsx @@ -5,10 +5,10 @@ import { SelectableValue } from '@grafana/data'; import { EditorField, EditorFieldGroup, EditorRow } from '@grafana/plugin-ui'; import { ALIGNMENT_PERIODS, SLO_BURN_RATE_SELECTOR_NAME } from '../constants'; +import { AlignmentTypes, SLOQuery } from '../dataquery.gen'; import CloudMonitoringDatasource from '../datasource'; import { selectors } from '../e2e/selectors'; import { alignmentPeriodLabel } from '../functions'; -import { AlignmentTypes, SLOQuery } from '../types/query'; import { CustomMetaData } from '../types/types'; import { AliasBy } from './AliasBy'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Selector.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Selector.tsx index ea0e5903af5..1e41d6917c0 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Selector.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Selector.tsx @@ -3,8 +3,8 @@ import { EditorField } from '@grafana/plugin-ui'; import { Select } from '@grafana/ui'; import { SELECTORS } from '../constants'; +import { SLOQuery } from '../dataquery.gen'; import CloudMonitoringDatasource from '../datasource'; -import { SLOQuery } from '../types/query'; export interface Props { refId: string; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Service.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Service.tsx index 9425437d7b3..03862ac8c8a 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Service.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Service.tsx @@ -4,8 +4,8 @@ import { SelectableValue } from '@grafana/data'; import { EditorField } from '@grafana/plugin-ui'; import { Select } from '@grafana/ui'; +import { SLOQuery } from '../dataquery.gen'; import CloudMonitoringDatasource from '../datasource'; -import { SLOQuery } from '../types/query'; export interface Props { refId: string; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/VariableQueryEditor.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/VariableQueryEditor.test.tsx index e94c8aefae0..64cb2addbea 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/VariableQueryEditor.test.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/VariableQueryEditor.test.tsx @@ -2,8 +2,8 @@ import { render, screen, waitFor } from '@testing-library/react'; import { VariableModel } from '@grafana/data'; +import { MetricFindQueryTypes } from '../dataquery.gen'; import CloudMonitoringDatasource from '../datasource'; -import { MetricFindQueryTypes } from '../types/query'; import { CloudMonitoringVariableQuery } from '../types/types'; import { CloudMonitoringVariableQueryEditor, Props } from './VariableQueryEditor'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/VariableQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/VariableQueryEditor.tsx index 6045e61b37d..c672d115343 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/VariableQueryEditor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/VariableQueryEditor.tsx @@ -3,9 +3,10 @@ import { PureComponent } from 'react'; import { QueryEditorProps } from '@grafana/data'; import { getTemplateSrv } from '@grafana/runtime'; +import { MetricFindQueryTypes } from '../dataquery.gen'; import CloudMonitoringDatasource from '../datasource'; import { extractServicesFromMetricDescriptors, getLabelKeys, getMetricTypes } from '../functions'; -import { CloudMonitoringQuery, MetricFindQueryTypes } from '../types/query'; +import { CloudMonitoringQuery } from '../types/query'; import { CloudMonitoringOptions, CloudMonitoringVariableQuery, diff --git a/public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.test.tsx index 05e2f9c3721..c31b43bca1e 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.test.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.test.tsx @@ -6,10 +6,10 @@ import { CustomVariableModel, getDefaultTimeRange } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { getTemplateSrv } from '@grafana/runtime'; +import { PreprocessorType, MetricKind, ValueTypes } from '../dataquery.gen'; import { createMockDatasource } from '../mocks/cloudMonitoringDatasource'; import { createMockMetricDescriptor } from '../mocks/cloudMonitoringMetricDescriptor'; import { createMockTimeSeriesList } from '../mocks/cloudMonitoringQuery'; -import { PreprocessorType, MetricKind, ValueTypes } from '../types/query'; import { defaultTimeSeriesList } from './MetricQueryEditor'; import { VisualMetricQueryEditor } from './VisualMetricQueryEditor'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.tsx index 56824f89358..732e7f0c36a 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.tsx @@ -9,10 +9,10 @@ import { EditorField, EditorFieldGroup, EditorRow } from '@grafana/plugin-ui'; import { reportInteraction } from '@grafana/runtime'; import { getSelectStyles, Select, AsyncSelect, useStyles2, useTheme2 } from '@grafana/ui'; +import { PreprocessorType, TimeSeriesList, MetricKind, ValueTypes } from '../dataquery.gen'; import CloudMonitoringDatasource from '../datasource'; import { selectors } from '../e2e/selectors'; import { getAlignmentPickerData, getMetricType, setMetricType } from '../functions'; -import { PreprocessorType, TimeSeriesList, MetricKind, ValueTypes } from '../types/query'; import { CustomMetaData, MetricDescriptor } from '../types/types'; import { AliasBy } from './AliasBy'; diff --git a/public/app/plugins/datasource/cloud-monitoring/constants.ts b/public/app/plugins/datasource/cloud-monitoring/constants.ts index 6560e6feb6b..40c7988ba2f 100644 --- a/public/app/plugins/datasource/cloud-monitoring/constants.ts +++ b/public/app/plugins/datasource/cloud-monitoring/constants.ts @@ -1,4 +1,4 @@ -import { QueryType, MetricKind, ValueTypes } from './types/query'; +import { QueryType, MetricKind, ValueTypes } from './dataquery.gen'; // not super excited about using uneven numbers, but this makes it align perfectly with rows that has two fields export const INPUT_WIDTH = 71; diff --git a/public/app/plugins/datasource/cloud-monitoring/datasource.test.ts b/public/app/plugins/datasource/cloud-monitoring/datasource.test.ts index a87d4e266d0..7700cd7a6d1 100644 --- a/public/app/plugins/datasource/cloud-monitoring/datasource.test.ts +++ b/public/app/plugins/datasource/cloud-monitoring/datasource.test.ts @@ -4,10 +4,11 @@ import { lastValueFrom, of } from 'rxjs'; import { CustomVariableModel, ScopedVars } from '@grafana/data'; import { getTemplateSrv } from '@grafana/runtime'; +import { PreprocessorType, QueryType, MetricKind } from './dataquery.gen'; import Datasource from './datasource'; import { createMockInstanceSetttings } from './mocks/cloudMonitoringInstanceSettings'; import { createMockQuery } from './mocks/cloudMonitoringQuery'; -import { CloudMonitoringQuery, PreprocessorType, QueryType, MetricKind } from './types/query'; +import { CloudMonitoringQuery } from './types/query'; let getTempVars = () => [] as CustomVariableModel[]; let replace = () => ''; diff --git a/public/app/plugins/datasource/cloud-monitoring/datasource.ts b/public/app/plugins/datasource/cloud-monitoring/datasource.ts index 9dc3f83262d..e030de33612 100644 --- a/public/app/plugins/datasource/cloud-monitoring/datasource.ts +++ b/public/app/plugins/datasource/cloud-monitoring/datasource.ts @@ -23,8 +23,9 @@ import { import { CloudMonitoringAnnotationSupport } from './annotationSupport'; import { SLO_BURN_RATE_SELECTOR_NAME } from './constants'; +import { QueryType, MetricQuery, Filter } from './dataquery.gen'; import { getMetricType, setMetricType } from './functions'; -import { CloudMonitoringQuery, QueryType, MetricQuery, Filter } from './types/query'; +import { CloudMonitoringQuery } from './types/query'; import { CloudMonitoringOptions, MetricDescriptor, PostResponse, Aggregation } from './types/types'; import { CloudMonitoringVariableSupport } from './variables'; diff --git a/public/app/plugins/datasource/cloud-monitoring/functions.test.ts b/public/app/plugins/datasource/cloud-monitoring/functions.test.ts index 5fad032253a..97c5251dfcc 100644 --- a/public/app/plugins/datasource/cloud-monitoring/functions.test.ts +++ b/public/app/plugins/datasource/cloud-monitoring/functions.test.ts @@ -1,4 +1,5 @@ import { AGGREGATIONS, SYSTEM_LABELS } from './constants'; +import { AlignmentTypes, TimeSeriesList, MetricKind, ValueTypes } from './dataquery.gen'; import { extractServicesFromMetricDescriptors, getAggregationOptionsByMetric, @@ -14,7 +15,6 @@ import { setMetricType, } from './functions'; import { newMockDatasource } from './specs/testData'; -import { AlignmentTypes, TimeSeriesList, MetricKind, ValueTypes } from './types/query'; import { MetricDescriptor } from './types/types'; jest.mock('@grafana/runtime', () => ({ diff --git a/public/app/plugins/datasource/cloud-monitoring/functions.ts b/public/app/plugins/datasource/cloud-monitoring/functions.ts index 13e0aceb1fe..9a9e64581c1 100644 --- a/public/app/plugins/datasource/cloud-monitoring/functions.ts +++ b/public/app/plugins/datasource/cloud-monitoring/functions.ts @@ -4,8 +4,8 @@ import { rangeUtil } from '@grafana/data'; import { getTemplateSrv, TemplateSrv } from '@grafana/runtime'; import { AGGREGATIONS, ALIGNMENTS, SYSTEM_LABELS } from './constants'; +import { AlignmentTypes, PreprocessorType, TimeSeriesList, MetricKind, ValueTypes } from './dataquery.gen'; import CloudMonitoringDatasource from './datasource'; -import { AlignmentTypes, PreprocessorType, TimeSeriesList, MetricKind, ValueTypes } from './types/query'; import { CustomMetaData, MetricDescriptor } from './types/types'; export const extractServicesFromMetricDescriptors = (metricDescriptors: MetricDescriptor[]) => diff --git a/public/app/plugins/datasource/cloud-monitoring/mocks/cloudMonitoringMetricDescriptor.ts b/public/app/plugins/datasource/cloud-monitoring/mocks/cloudMonitoringMetricDescriptor.ts index bb77e381b24..52dd7e09f5c 100644 --- a/public/app/plugins/datasource/cloud-monitoring/mocks/cloudMonitoringMetricDescriptor.ts +++ b/public/app/plugins/datasource/cloud-monitoring/mocks/cloudMonitoringMetricDescriptor.ts @@ -1,4 +1,4 @@ -import { MetricKind, ValueTypes } from '../types/query'; +import { MetricKind, ValueTypes } from '../dataquery.gen'; import { MetricDescriptor } from '../types/types'; export const createMockMetricDescriptor = (overrides?: Partial): MetricDescriptor => { diff --git a/public/app/plugins/datasource/cloud-monitoring/mocks/cloudMonitoringQuery.ts b/public/app/plugins/datasource/cloud-monitoring/mocks/cloudMonitoringQuery.ts index 77b015756ed..6862f2ee0b9 100644 --- a/public/app/plugins/datasource/cloud-monitoring/mocks/cloudMonitoringQuery.ts +++ b/public/app/plugins/datasource/cloud-monitoring/mocks/cloudMonitoringQuery.ts @@ -1,11 +1,5 @@ -import { - AlignmentTypes, - CloudMonitoringQuery, - QueryType, - SLOQuery, - TimeSeriesList, - TimeSeriesQuery, -} from '../types/query'; +import { AlignmentTypes, QueryType, SLOQuery, TimeSeriesList, TimeSeriesQuery } from '../dataquery.gen'; +import { CloudMonitoringQuery } from '../types/query'; type Subset = { [attr in keyof K]?: K[attr] extends object ? Subset : K[attr]; diff --git a/public/app/plugins/datasource/cloud-monitoring/module.ts b/public/app/plugins/datasource/cloud-monitoring/module.ts index 6818e0d8763..aa3b77527e6 100644 --- a/public/app/plugins/datasource/cloud-monitoring/module.ts +++ b/public/app/plugins/datasource/cloud-monitoring/module.ts @@ -7,10 +7,11 @@ import CloudMonitoringCheatSheet from './components/CloudMonitoringCheatSheet'; import { ConfigEditor } from './components/ConfigEditor/ConfigEditor'; import { QueryEditor } from './components/QueryEditor'; import { CloudMonitoringVariableQueryEditor } from './components/VariableQueryEditor'; +import { QueryType } from './dataquery.gen'; import CloudMonitoringDatasource from './datasource'; import pluginJson from './plugin.json'; import { trackCloudMonitoringDashboardLoaded } from './tracking'; -import { CloudMonitoringQuery, QueryType } from './types/query'; +import { CloudMonitoringQuery } from './types/query'; export const plugin = new DataSourcePlugin(CloudMonitoringDatasource) .setQueryEditorHelp(CloudMonitoringCheatSheet) diff --git a/public/app/plugins/datasource/cloud-monitoring/types/query.ts b/public/app/plugins/datasource/cloud-monitoring/types/query.ts index a202c85bd3e..52f8f722455 100644 --- a/public/app/plugins/datasource/cloud-monitoring/types/query.ts +++ b/public/app/plugins/datasource/cloud-monitoring/types/query.ts @@ -1,17 +1,5 @@ import { CloudMonitoringQuery as CloudMonitoringQueryBase, QueryType } from '../dataquery.gen'; -export { QueryType }; -export { PreprocessorType, MetricKind, AlignmentTypes, ValueTypes, MetricFindQueryTypes } from '../dataquery.gen'; -export type { - TimeSeriesQuery, - SLOQuery, - TimeSeriesList, - MetricQuery, - PromQLQuery, - LegacyCloudMonitoringAnnotationQuery, - Filter, -} from '../dataquery.gen'; - /** * Represents the query as it moves through the frontend query editor and datasource files. * It can represent new queries that are still being edited, so all properties are optional diff --git a/public/app/plugins/datasource/cloud-monitoring/types/types.ts b/public/app/plugins/datasource/cloud-monitoring/types/types.ts index c7eb809c739..849f72ea69b 100644 --- a/public/app/plugins/datasource/cloud-monitoring/types/types.ts +++ b/public/app/plugins/datasource/cloud-monitoring/types/types.ts @@ -1,7 +1,7 @@ import { DataQuery, SelectableValue, VariableWithMultiSupport } from '@grafana/data'; import { DataSourceOptions, DataSourceSecureJsonData } from '@grafana/google-sdk'; -import { MetricKind } from './query'; +import { MetricKind } from '../dataquery.gen'; export interface CloudMonitoringVariableQuery extends DataQuery { selectedQueryType: string; diff --git a/public/app/plugins/datasource/cloudwatch/annotationSupport.test.ts b/public/app/plugins/datasource/cloudwatch/annotationSupport.test.ts index 6bd10edb54c..3b94647b4ac 100644 --- a/public/app/plugins/datasource/cloudwatch/annotationSupport.test.ts +++ b/public/app/plugins/datasource/cloudwatch/annotationSupport.test.ts @@ -1,7 +1,8 @@ import { AnnotationQuery } from '@grafana/data'; import { CloudWatchAnnotationSupport } from './annotationSupport'; -import { CloudWatchAnnotationQuery, LegacyAnnotationQuery } from './types'; +import { CloudWatchAnnotationQuery } from './dataquery.gen'; +import { LegacyAnnotationQuery } from './types'; const metricStatAnnotationQuery: CloudWatchAnnotationQuery = { queryMode: 'Annotations', diff --git a/public/app/plugins/datasource/cloudwatch/annotationSupport.ts b/public/app/plugins/datasource/cloudwatch/annotationSupport.ts index 4c1d91746bd..23d72ad3721 100644 --- a/public/app/plugins/datasource/cloudwatch/annotationSupport.ts +++ b/public/app/plugins/datasource/cloudwatch/annotationSupport.ts @@ -1,9 +1,10 @@ import { AnnotationQuery } from '@grafana/data'; import { AnnotationQueryEditor } from './components/AnnotationQueryEditor/AnnotationQueryEditor'; +import { CloudWatchAnnotationQuery } from './dataquery.gen'; import { DEFAULT_ANNOTATIONS_QUERY } from './defaultQueries'; import { isCloudWatchAnnotation } from './guards'; -import { CloudWatchAnnotationQuery, CloudWatchQuery, LegacyAnnotationQuery } from './types'; +import { CloudWatchQuery, LegacyAnnotationQuery } from './types'; export const CloudWatchAnnotationSupport = { // converts legacy angular style queries to new format. Also sets the same default values as in the deprecated angular directive diff --git a/public/app/plugins/datasource/cloudwatch/components/AnnotationQueryEditor/AnnotationQueryEditor.test.tsx b/public/app/plugins/datasource/cloudwatch/components/AnnotationQueryEditor/AnnotationQueryEditor.test.tsx index 9178eb849c4..6033c4bba72 100644 --- a/public/app/plugins/datasource/cloudwatch/components/AnnotationQueryEditor/AnnotationQueryEditor.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/AnnotationQueryEditor/AnnotationQueryEditor.test.tsx @@ -3,9 +3,10 @@ import '@testing-library/jest-dom'; import { QueryEditorProps } from '@grafana/data'; +import { CloudWatchAnnotationQuery, CloudWatchMetricsQuery } from '../../dataquery.gen'; import { CloudWatchDatasource } from '../../datasource'; import { setupMockedDataSource } from '../../mocks/CloudWatchDataSource'; -import { CloudWatchAnnotationQuery, CloudWatchJsonData, CloudWatchMetricsQuery, CloudWatchQuery } from '../../types'; +import { CloudWatchJsonData, CloudWatchQuery } from '../../types'; import { AnnotationQueryEditor } from './AnnotationQueryEditor'; diff --git a/public/app/plugins/datasource/cloudwatch/components/AnnotationQueryEditor/AnnotationQueryEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/AnnotationQueryEditor/AnnotationQueryEditor.tsx index 9d3a061c76d..df62a07d40e 100644 --- a/public/app/plugins/datasource/cloudwatch/components/AnnotationQueryEditor/AnnotationQueryEditor.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/AnnotationQueryEditor/AnnotationQueryEditor.tsx @@ -4,10 +4,11 @@ import { QueryEditorProps } from '@grafana/data'; import { EditorField, EditorHeader, EditorRow, EditorSwitch, InlineSelect } from '@grafana/plugin-ui'; import { Alert, Input, Space } from '@grafana/ui'; +import { MetricStat } from '../../dataquery.gen'; import { CloudWatchDatasource } from '../../datasource'; import { isCloudWatchAnnotationQuery } from '../../guards'; import { useRegions } from '../../hooks'; -import { CloudWatchJsonData, CloudWatchQuery, MetricStat } from '../../types'; +import { CloudWatchJsonData, CloudWatchQuery } from '../../types'; import { MetricStatEditor } from '../shared/MetricStatEditor/MetricStatEditor'; export type Props = QueryEditorProps; diff --git a/public/app/plugins/datasource/cloudwatch/components/CheatSheet/LogsCheatSheet.tsx b/public/app/plugins/datasource/cloudwatch/components/CheatSheet/LogsCheatSheet.tsx index 082a8eaf44a..f714992aa7d 100644 --- a/public/app/plugins/datasource/cloudwatch/components/CheatSheet/LogsCheatSheet.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/CheatSheet/LogsCheatSheet.tsx @@ -6,8 +6,9 @@ import { GrafanaTheme2 } from '@grafana/data'; import { Collapse, useStyles2, Text, TextLink } from '@grafana/ui'; import { flattenTokens } from '@grafana/ui/internal'; +import { CloudWatchLogsQuery, LogsQueryLanguage } from '../../dataquery.gen'; import { trackSampleQuerySelection } from '../../tracking'; -import { CloudWatchLogsQuery, CloudWatchQuery, LogsQueryLanguage } from '../../types'; +import { CloudWatchQuery } from '../../types'; import * as sampleQueries from './sampleQueries'; import { cwliTokenizer, pplTokenizer, sqlTokenizer } from './tokenizer'; diff --git a/public/app/plugins/datasource/cloudwatch/components/CheatSheet/sampleQueries.ts b/public/app/plugins/datasource/cloudwatch/components/CheatSheet/sampleQueries.ts index 4c67fe68c9b..5800ba42c82 100644 --- a/public/app/plugins/datasource/cloudwatch/components/CheatSheet/sampleQueries.ts +++ b/public/app/plugins/datasource/cloudwatch/components/CheatSheet/sampleQueries.ts @@ -1,6 +1,6 @@ import { stripIndents } from 'common-tags'; -import { LogsQueryLanguage } from '../../types'; +import { LogsQueryLanguage } from '../../dataquery.gen'; export interface SampleQuery { title: string; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/CloudWatchLink.test.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/CloudWatchLink.test.tsx index 8c2ed9adb1f..ea291ea8a4d 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/CloudWatchLink.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/CloudWatchLink.test.tsx @@ -2,10 +2,10 @@ import { act, render, screen, waitFor } from '@testing-library/react'; import { LoadingState } from '@grafana/data'; +import { CloudWatchLogsQuery } from '../../../dataquery.gen'; import { setupMockedDataSource } from '../../../mocks/CloudWatchDataSource'; import { RequestMock } from '../../../mocks/Request'; import { validLogsQuery } from '../../../mocks/queries'; -import { CloudWatchLogsQuery } from '../../../types'; import { CloudWatchLink } from './CloudWatchLink'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/CloudWatchLink.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/CloudWatchLink.tsx index 957fe7981ca..107c6c28157 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/CloudWatchLink.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/CloudWatchLink.tsx @@ -5,8 +5,8 @@ import { PanelData } from '@grafana/data'; import { LinkButton } from '@grafana/ui'; import { AwsUrl, encodeUrl } from '../../../aws_url'; +import { CloudWatchLogsQuery } from '../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../datasource'; -import { CloudWatchLogsQuery } from '../../../types'; interface Props { query: CloudWatchLogsQuery; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/LogsQueryEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/LogsQueryEditor.tsx index 96158987b68..516a0c4e6d0 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/LogsQueryEditor.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/LogsQueryEditor.tsx @@ -4,9 +4,10 @@ import { useEffectOnce } from 'react-use'; import { QueryEditorProps, SelectableValue } from '@grafana/data'; import { InlineSelect } from '@grafana/plugin-ui'; +import { CloudWatchLogsQuery, LogsMode, LogsQueryLanguage } from '../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../datasource'; import { DEFAULT_CWLI_QUERY_STRING, DEFAULT_PPL_QUERY_STRING, DEFAULT_SQL_QUERY_STRING } from '../../../defaultQueries'; -import { CloudWatchJsonData, CloudWatchLogsQuery, CloudWatchQuery, LogsMode, LogsQueryLanguage } from '../../../types'; +import { CloudWatchQuery, CloudWatchJsonData } from '../../../types'; import { CloudWatchLink } from './CloudWatchLink'; import { LogsAnomaliesQueryEditor } from './LogsAnomaliesQueryEditor'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/LogsQueryField.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/LogsQueryField.tsx index 111084dbb1e..72e5bb702b0 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/LogsQueryField.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/LogsQueryField.tsx @@ -4,8 +4,9 @@ import { ReactNode, useCallback } from 'react'; import { GrafanaTheme2, QueryEditorProps } from '@grafana/data'; import { useStyles2 } from '@grafana/ui'; +import { CloudWatchLogsQuery, LogsQueryLanguage } from '../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../datasource'; -import { CloudWatchJsonData, CloudWatchLogsQuery, CloudWatchQuery, LogsQueryLanguage } from '../../../types'; +import { CloudWatchJsonData, CloudWatchQuery } from '../../../types'; import { LogGroupsFieldWrapper } from '../../shared/LogGroups/LogGroupsField'; import { LogsQLCodeEditor } from './code-editors/LogsQLCodeEditor'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/code-editors/LogsQLCodeEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/code-editors/LogsQLCodeEditor.tsx index dec250d42fd..399d2ff21c3 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/code-editors/LogsQLCodeEditor.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/code-editors/LogsQLCodeEditor.tsx @@ -3,11 +3,11 @@ import { useCallback, useRef } from 'react'; import { CodeEditor, Monaco } from '@grafana/ui'; +import { CloudWatchLogsQuery } from '../../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../../datasource'; import language from '../../../../language/logs/definition'; import { TRIGGER_SUGGEST } from '../../../../language/monarch/commands'; import { registerLanguage, reRegisterCompletionProvider } from '../../../../language/monarch/register'; -import { CloudWatchLogsQuery } from '../../../../types'; import { getStatsGroups } from '../../../../utils/query/getStatsGroups'; import { codeEditorCommonProps } from './PPLQueryEditor'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/code-editors/PPLQueryEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/code-editors/PPLQueryEditor.tsx index 84ff7e7738c..6c17005ee78 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/code-editors/PPLQueryEditor.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/code-editors/PPLQueryEditor.tsx @@ -4,11 +4,11 @@ import { useCallback, useRef } from 'react'; import { CodeEditor, Monaco } from '@grafana/ui'; import { CodeEditorProps } from '@grafana/ui/internal'; +import { CloudWatchLogsQuery } from '../../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../../datasource'; import language from '../../../../language/cloudwatch-ppl/definition'; import { TRIGGER_SUGGEST } from '../../../../language/monarch/commands'; import { registerLanguage, reRegisterCompletionProvider } from '../../../../language/monarch/register'; -import { CloudWatchLogsQuery } from '../../../../types'; import { getStatsGroups } from '../../../../utils/query/getStatsGroups'; export const codeEditorCommonProps: Partial = { diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/code-editors/SQLCodeEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/code-editors/SQLCodeEditor.tsx index 59abe051f76..e5b82121483 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/code-editors/SQLCodeEditor.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/LogsQueryEditor/code-editors/SQLCodeEditor.tsx @@ -3,11 +3,11 @@ import { useCallback, useRef } from 'react'; import { CodeEditor, Monaco } from '@grafana/ui'; +import { CloudWatchLogsQuery } from '../../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../../datasource'; import language from '../../../../language/cloudwatch-logs-sql/definition'; import { TRIGGER_SUGGEST } from '../../../../language/monarch/commands'; import { registerLanguage, reRegisterCompletionProvider } from '../../../../language/monarch/register'; -import { CloudWatchLogsQuery } from '../../../../types'; import { getStatsGroups } from '../../../../utils/query/getStatsGroups'; import { codeEditorCommonProps } from './PPLQueryEditor'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.test.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.test.tsx index bca545ec45f..1aff9157f4c 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.test.tsx @@ -5,10 +5,11 @@ import { CustomVariableModel, DataSourceInstanceSettings } from '@grafana/data'; // eslint-disable-next-line no-restricted-imports import * as ui from '@grafana/ui'; +import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../datasource'; import { setupMockedTemplateService } from '../../../mocks/CloudWatchDataSource'; import { initialVariableModelState } from '../../../mocks/CloudWatchVariables'; -import { CloudWatchJsonData, CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../../../types'; +import { CloudWatchJsonData } from '../../../types'; import { MetricsQueryEditor, Props } from './MetricsQueryEditor'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.tsx index db88bda25cd..c9625bbddb0 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/MetricsQueryEditor.tsx @@ -6,17 +6,11 @@ import { EditorField, EditorRow, InlineSelect } from '@grafana/plugin-ui'; import { config } from '@grafana/runtime'; import { ConfirmModal, Input, RadioButtonGroup, Space } from '@grafana/ui'; +import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType, MetricStat } from '../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../datasource'; import { DEFAULT_METRICS_QUERY } from '../../../defaultQueries'; import useMigratedMetricsQuery from '../../../migrations/useMigratedMetricsQuery'; -import { - CloudWatchJsonData, - CloudWatchMetricsQuery, - CloudWatchQuery, - MetricEditorMode, - MetricQueryType, - MetricStat, -} from '../../../types'; +import { CloudWatchQuery, CloudWatchJsonData } from '../../../types'; import { MetricStatEditor } from '../../shared/MetricStatEditor/MetricStatEditor'; import { DynamicLabelsField } from './DynamicLabelsField'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderEditor.test.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderEditor.test.tsx index 2e3c8e16403..bad9162ae87 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderEditor.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderEditor.test.tsx @@ -1,8 +1,14 @@ import { render, screen, waitFor } from '@testing-library/react'; -import { QueryEditorExpressionType, QueryEditorPropertyType } from '../../../../expressions'; +import { + CloudWatchMetricsQuery, + MetricEditorMode, + MetricQueryType, + SQLExpression, + QueryEditorExpressionType, + QueryEditorPropertyType, +} from '../../../../dataquery.gen'; import { setupMockedDataSource } from '../../../../mocks/CloudWatchDataSource'; -import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType, SQLExpression } from '../../../../types'; import { SQLBuilderEditor } from './SQLBuilderEditor'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderEditor.tsx index 93ff8e4d4e4..adb81c609bc 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderEditor.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderEditor.tsx @@ -4,9 +4,9 @@ import * as React from 'react'; import { EditorField, EditorRow, EditorRows } from '@grafana/plugin-ui'; import { Input } from '@grafana/ui'; +import { CloudWatchMetricsQuery } from '../../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../../datasource'; import SQLGenerator from '../../../../language/cloudwatch-sql/SQLGenerator'; -import { CloudWatchMetricsQuery } from '../../../../types'; import SQLBuilderSelectRow from './SQLBuilderSelectRow'; import SQLFilter from './SQLFilter'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderSelectRow.test.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderSelectRow.test.tsx index fca1c946f06..621566f4cf9 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderSelectRow.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderSelectRow.test.tsx @@ -1,9 +1,15 @@ import { act, render, screen } from '@testing-library/react'; import { selectOptionInTest } from 'test/helpers/selectOptionInTest'; -import { QueryEditorExpressionType, QueryEditorPropertyType } from '../../../../expressions'; +import { + CloudWatchMetricsQuery, + MetricEditorMode, + MetricQueryType, + SQLExpression, + QueryEditorExpressionType, + QueryEditorPropertyType, +} from '../../../../dataquery.gen'; import { setupMockedDataSource } from '../../../../mocks/CloudWatchDataSource'; -import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType, SQLExpression } from '../../../../types'; import SQLBuilderSelectRow from './SQLBuilderSelectRow'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderSelectRow.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderSelectRow.tsx index 707b7b5b137..ff3ff1969ef 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderSelectRow.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLBuilderSelectRow.tsx @@ -5,10 +5,10 @@ import { EditorField, EditorFieldGroup, EditorSwitch } from '@grafana/plugin-ui' import { config } from '@grafana/runtime'; import { Select } from '@grafana/ui'; +import { CloudWatchMetricsQuery } from '../../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../../datasource'; import { useAccountOptions, useDimensionKeys, useMetrics, useNamespaces } from '../../../../hooks'; import { STATISTICS } from '../../../../language/cloudwatch-sql/language'; -import { CloudWatchMetricsQuery } from '../../../../types'; import { appendTemplateVariables } from '../../../../utils/utils'; import { Account } from '../../../shared/Account'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLFilter.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLFilter.tsx index a911f8d05eb..e40c8ec44ee 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLFilter.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLFilter.tsx @@ -6,16 +6,16 @@ import { SelectableValue, toOption } from '@grafana/data'; import { AccessoryButton, EditorList, InputGroup } from '@grafana/plugin-ui'; import { config } from '@grafana/runtime'; import { Alert, Select, useStyles2 } from '@grafana/ui'; +import { + CloudWatchMetricsQuery, + QueryEditorExpressionType, + QueryEditorPropertyType, +} from 'app/plugins/datasource/cloudwatch/dataquery.gen'; import { CloudWatchDatasource } from '../../../../datasource'; -import { - QueryEditorExpressionType, - QueryEditorOperatorExpression, - QueryEditorPropertyType, -} from '../../../../expressions'; +import { QueryEditorOperatorExpression } from '../../../../expressions'; import { useDimensionKeys, useEnsureVariableHasSingleSelection } from '../../../../hooks'; import { COMPARISON_OPERATORS, EQUALS } from '../../../../language/cloudwatch-sql/language'; -import { CloudWatchMetricsQuery } from '../../../../types'; import { appendTemplateVariables } from '../../../../utils/utils'; import { diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLGroupBy.test.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLGroupBy.test.tsx index 315eafb511a..a1be51358ce 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLGroupBy.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLGroupBy.test.tsx @@ -4,9 +4,9 @@ import selectEvent from 'react-select-event'; import { config } from '@grafana/runtime'; +import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType, SQLExpression } from '../../../../dataquery.gen'; import { setupMockedDataSource } from '../../../../mocks/CloudWatchDataSource'; import { createArray, createGroupBy } from '../../../../mocks/sqlUtils'; -import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType, SQLExpression } from '../../../../types'; import SQLGroupBy from './SQLGroupBy'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLGroupBy.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLGroupBy.tsx index a288b74b0b8..f49aa2ba00c 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLGroupBy.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLGroupBy.tsx @@ -5,14 +5,14 @@ import { AccessoryButton, EditorList, InputGroup } from '@grafana/plugin-ui'; import { config } from '@grafana/runtime'; import { Select } from '@grafana/ui'; -import { CloudWatchDatasource } from '../../../../datasource'; import { + CloudWatchMetricsQuery, QueryEditorExpressionType, QueryEditorGroupByExpression, QueryEditorPropertyType, -} from '../../../../expressions'; +} from '../../../../dataquery.gen'; +import { CloudWatchDatasource } from '../../../../datasource'; import { useDimensionKeys, useIsMonitoringAccount } from '../../../../hooks'; -import { CloudWatchMetricsQuery } from '../../../../types'; import { getFlattenedGroupBys, diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLOrderByGroup.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLOrderByGroup.tsx index 188c7a1ce69..58427587f2d 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLOrderByGroup.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/SQLOrderByGroup.tsx @@ -2,9 +2,9 @@ import { SelectableValue, toOption } from '@grafana/data'; import { AccessoryButton, EditorField, EditorFieldGroup, InputGroup } from '@grafana/plugin-ui'; import { Select } from '@grafana/ui'; +import { CloudWatchMetricsQuery } from '../../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../../datasource'; import { ASC, DESC, STATISTICS } from '../../../../language/cloudwatch-sql/language'; -import { CloudWatchMetricsQuery } from '../../../../types'; import { appendTemplateVariables } from '../../../../utils/utils'; import { setOrderBy, setSql } from './utils'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/utils.ts b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/utils.ts index b25dd6fa45e..e53c02ac173 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/utils.ts +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/MetricsQueryEditor/SQLBuilderEditor/utils.ts @@ -1,15 +1,17 @@ import { SelectableValue } from '@grafana/data'; import { + SQLExpression, + CloudWatchMetricsQuery, + Dimensions, QueryEditorExpressionType, QueryEditorPropertyType, QueryEditorFunctionParameterExpression, QueryEditorArrayExpression, - QueryEditorOperatorExpression, QueryEditorGroupByExpression, -} from '../../../../expressions'; +} from '../../../../dataquery.gen'; +import { QueryEditorOperatorExpression } from '../../../../expressions'; import { SCHEMA } from '../../../../language/cloudwatch-sql/language'; -import { SQLExpression, CloudWatchMetricsQuery, Dimensions } from '../../../../types'; export function getMetricNameFromExpression(selectExpression: SQLExpression['select']): string | undefined { return selectExpression?.parameters?.[0].name; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/QueryEditor.test.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/QueryEditor.test.tsx index 1d87bd29596..47c4633df65 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/QueryEditor.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/QueryEditor.test.tsx @@ -5,6 +5,7 @@ import { selectOptionInTest } from 'test/helpers/selectOptionInTest'; import { QueryEditorProps } from '@grafana/data'; import { config } from '@grafana/runtime'; +import { MetricEditorMode, MetricQueryType, LogsQueryLanguage } from '../../dataquery.gen'; import { CloudWatchDatasource } from '../../datasource'; import { DEFAULT_CWLI_QUERY_STRING, DEFAULT_SQL_QUERY_STRING } from '../../defaultQueries'; import { setupMockedDataSource } from '../../mocks/CloudWatchDataSource'; @@ -15,7 +16,7 @@ import { validMetricSearchBuilderQuery, validMetricSearchCodeQuery, } from '../../mocks/queries'; -import { CloudWatchQuery, CloudWatchJsonData, MetricEditorMode, MetricQueryType, LogsQueryLanguage } from '../../types'; +import { CloudWatchJsonData, CloudWatchQuery } from '../../types'; import { QueryEditor } from './QueryEditor'; diff --git a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/QueryHeader.tsx b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/QueryHeader.tsx index 78da93ba3a1..ae8e987b48c 100644 --- a/public/app/plugins/datasource/cloudwatch/components/QueryEditor/QueryHeader.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/QueryEditor/QueryHeader.tsx @@ -5,10 +5,11 @@ import { EditorHeader, InlineSelect, FlexItem } from '@grafana/plugin-ui'; import { config } from '@grafana/runtime'; import { Badge, Button } from '@grafana/ui'; +import { CloudWatchQueryMode } from '../../dataquery.gen'; import { CloudWatchDatasource } from '../../datasource'; import { isCloudWatchLogsQuery, isCloudWatchMetricsQuery } from '../../guards'; import { useIsMonitoringAccount, useRegions } from '../../hooks'; -import { CloudWatchJsonData, CloudWatchQuery, CloudWatchQueryMode } from '../../types'; +import { CloudWatchJsonData, CloudWatchQuery } from '../../types'; export interface Props extends QueryEditorProps { extraHeaderElementLeft?: JSX.Element; diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.test.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.test.tsx index 6374c95b8a6..8509a230c45 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.test.tsx @@ -1,8 +1,8 @@ import { fireEvent, render, screen, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import { CloudWatchMetricsQuery } from '../../../dataquery.gen'; import { setupMockedDataSource } from '../../../mocks/CloudWatchDataSource'; -import { CloudWatchMetricsQuery } from '../../../types'; import { Dimensions } from './Dimensions'; diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.tsx index 3ab31316fc9..5f66358636d 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.tsx @@ -3,8 +3,8 @@ import { useMemo, useState } from 'react'; import { EditorList } from '@grafana/plugin-ui'; +import { Dimensions as DimensionsType, MetricStat } from '../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../datasource'; -import { Dimensions as DimensionsType, MetricStat } from '../../../types'; import { FilterItem } from './FilterItem'; diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.test.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.test.tsx index 2afbd64e195..a98deecd5ef 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.test.tsx @@ -1,8 +1,8 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import { CloudWatchMetricsQuery } from '../../../dataquery.gen'; import { setupMockedDataSource } from '../../../mocks/CloudWatchDataSource'; -import { CloudWatchMetricsQuery } from '../../../types'; import { FilterItem } from './FilterItem'; diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.tsx index 592ecfbe76f..673a193145a 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.tsx @@ -6,9 +6,9 @@ import { GrafanaTheme2, SelectableValue, toOption } from '@grafana/data'; import { AccessoryButton, InputGroup } from '@grafana/plugin-ui'; import { Alert, Select, useStyles2 } from '@grafana/ui'; +import { Dimensions, MetricStat } from '../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../datasource'; import { useDimensionKeys, useEnsureVariableHasSingleSelection } from '../../../hooks'; -import { Dimensions, MetricStat } from '../../../types'; import { appendTemplateVariables } from '../../../utils/utils'; import { DimensionFilterCondition } from './Dimensions'; diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/LogGroupsField.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/LogGroupsField.tsx index 85c4cf74336..9190cc2bcc9 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/LogGroupsField.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/LogGroupsField.tsx @@ -3,10 +3,10 @@ import { useEffect, useState } from 'react'; import { config } from '@grafana/runtime'; +import { LogGroup } from '../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../datasource'; import { useAccountOptions } from '../../../hooks'; import { DescribeLogGroupsRequest } from '../../../resources/types'; -import { LogGroup } from '../../../types'; import { isTemplateVariable } from '../../../utils/templateVariableUtils'; import { LegacyLogGroupSelection } from './LegacyLogGroupNamesSelection'; diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/LogGroupsSelector.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/LogGroupsSelector.tsx index 170359cdfcb..9f5eb9be6a7 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/LogGroupsSelector.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/LogGroupsSelector.tsx @@ -15,8 +15,8 @@ import { useStyles2, } from '@grafana/ui'; +import { LogGroup } from '../../../dataquery.gen'; import { DescribeLogGroupsRequest, ResourceResponse, LogGroupResponse } from '../../../resources/types'; -import { LogGroup } from '../../../types'; import getStyles from '../../styles'; import { Account, ALL_ACCOUNTS_OPTION } from '../Account'; diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/SelectedLogGroups.test.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/SelectedLogGroups.test.tsx index 7ad0fea4ec4..f404f50c436 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/SelectedLogGroups.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/SelectedLogGroups.test.tsx @@ -1,7 +1,7 @@ import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { LogGroup } from '../../../types'; +import { LogGroup } from '../../../dataquery.gen'; import { SelectedLogGroups } from './SelectedLogGroups'; diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/SelectedLogGroups.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/SelectedLogGroups.tsx index e1c20db7f50..6991861d7a4 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/SelectedLogGroups.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/LogGroups/SelectedLogGroups.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import { Button, ConfirmModal, useStyles2 } from '@grafana/ui'; -import { LogGroup } from '../../../types'; +import { LogGroup } from '../../../dataquery.gen'; import getStyles from '../../styles'; type CrossAccountLogsQueryProps = { diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/MetricStatEditor/MetricStatEditor.test.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/MetricStatEditor/MetricStatEditor.test.tsx index 5eec534a5ca..8a353ebd239 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/MetricStatEditor/MetricStatEditor.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/MetricStatEditor/MetricStatEditor.test.tsx @@ -4,9 +4,9 @@ import selectEvent from 'react-select-event'; import { config } from '@grafana/runtime'; +import { MetricStat } from '../../../dataquery.gen'; import { setupMockedDataSource, statisticVariable } from '../../../mocks/CloudWatchDataSource'; import { validMetricSearchBuilderQuery } from '../../../mocks/queries'; -import { MetricStat } from '../../../types'; import { MetricStatEditor } from './MetricStatEditor'; diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/MetricStatEditor/MetricStatEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/MetricStatEditor/MetricStatEditor.tsx index cf98588d377..0aab1780826 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/MetricStatEditor/MetricStatEditor.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/MetricStatEditor/MetricStatEditor.tsx @@ -6,10 +6,10 @@ import { EditorField, EditorFieldGroup, EditorRow, EditorRows, EditorSwitch } fr import { config } from '@grafana/runtime'; import { Select, TextLink } from '@grafana/ui'; +import { MetricStat } from '../../../dataquery.gen'; import { CloudWatchDatasource } from '../../../datasource'; import { useAccountOptions, useMetrics, useNamespaces } from '../../../hooks'; import { standardStatistics } from '../../../standardStatistics'; -import { MetricStat } from '../../../types'; import { appendTemplateVariables, toOption } from '../../../utils/utils'; import { Account } from '../Account'; import { Dimensions } from '../Dimensions/Dimensions'; diff --git a/public/app/plugins/datasource/cloudwatch/datasource.test.ts b/public/app/plugins/datasource/cloudwatch/datasource.test.ts index 2a84dca2490..a922629e07f 100644 --- a/public/app/plugins/datasource/cloudwatch/datasource.test.ts +++ b/public/app/plugins/datasource/cloudwatch/datasource.test.ts @@ -3,6 +3,13 @@ import { toArray } from 'rxjs/operators'; import { CoreApp, Field } from '@grafana/data'; +import { + CloudWatchLogsQuery, + CloudWatchMetricsQuery, + LogsQueryLanguage, + MetricEditorMode, + MetricQueryType, +} from './dataquery.gen'; import { CloudWatchSettings, fieldsVariable, @@ -13,16 +20,7 @@ import { import { setupForLogs } from './mocks/logsTestContext'; import { validLogsQuery, validMetricSearchBuilderQuery } from './mocks/queries'; import { TimeRangeMock } from './mocks/timeRange'; -import { - CloudWatchDefaultQuery, - CloudWatchLogsQuery, - CloudWatchLogsRequest, - CloudWatchMetricsQuery, - CloudWatchQuery, - LogsQueryLanguage, - MetricEditorMode, - MetricQueryType, -} from './types'; +import { CloudWatchQuery, CloudWatchLogsRequest, CloudWatchDefaultQuery } from './types'; import * as templateUtils from './utils/templateVariableUtils'; describe('datasource', () => { diff --git a/public/app/plugins/datasource/cloudwatch/datasource.ts b/public/app/plugins/datasource/cloudwatch/datasource.ts index 27c240dd6cd..c5b0dc50d56 100644 --- a/public/app/plugins/datasource/cloudwatch/datasource.ts +++ b/public/app/plugins/datasource/cloudwatch/datasource.ts @@ -15,6 +15,12 @@ import { import { DataSourceWithBackend, TemplateSrv, getTemplateSrv } from '@grafana/runtime'; import { CloudWatchAnnotationSupport } from './annotationSupport'; +import { + CloudWatchAnnotationQuery, + CloudWatchLogsAnomaliesQuery, + CloudWatchLogsQuery, + CloudWatchMetricsQuery, +} from './dataquery.gen'; import { DEFAULT_METRICS_QUERY, getDefaultLogsQuery } from './defaultQueries'; import { isCloudWatchAnnotationQuery, @@ -42,14 +48,7 @@ import { CloudWatchAnnotationQueryRunner } from './query-runner/CloudWatchAnnota import { CloudWatchLogsQueryRunner } from './query-runner/CloudWatchLogsQueryRunner'; import { CloudWatchMetricsQueryRunner } from './query-runner/CloudWatchMetricsQueryRunner'; import { ResourcesAPI } from './resources/ResourcesAPI'; -import { - CloudWatchAnnotationQuery, - CloudWatchJsonData, - CloudWatchLogsAnomaliesQuery, - CloudWatchLogsQuery, - CloudWatchMetricsQuery, - CloudWatchQuery, -} from './types'; +import { CloudWatchQuery, CloudWatchJsonData } from './types'; import { CloudWatchVariableSupport } from './variables'; export class CloudWatchDatasource diff --git a/public/app/plugins/datasource/cloudwatch/defaultQueries.ts b/public/app/plugins/datasource/cloudwatch/defaultQueries.ts index 22055f17256..c8935405f6d 100644 --- a/public/app/plugins/datasource/cloudwatch/defaultQueries.ts +++ b/public/app/plugins/datasource/cloudwatch/defaultQueries.ts @@ -6,9 +6,8 @@ import { LogsQueryLanguage, MetricEditorMode, MetricQueryType, - VariableQuery, - VariableQueryType, -} from './types'; +} from './dataquery.gen'; +import { VariableQuery, VariableQueryType } from './types'; export const DEFAULT_METRICS_QUERY: Omit = { queryMode: 'Metrics', diff --git a/public/app/plugins/datasource/cloudwatch/expressions.ts b/public/app/plugins/datasource/cloudwatch/expressions.ts index 206e9284089..60b9d1eca8e 100644 --- a/public/app/plugins/datasource/cloudwatch/expressions.ts +++ b/public/app/plugins/datasource/cloudwatch/expressions.ts @@ -3,17 +3,6 @@ import { QueryEditorOperator as QueryEditorOperatorBase, QueryEditorOperatorValueType, } from './dataquery.gen'; -export { - QueryEditorPropertyType, - type QueryEditorProperty, - type QueryEditorPropertyExpression, - type QueryEditorGroupByExpression, - type QueryEditorFunctionExpression, - type QueryEditorFunctionParameterExpression, - type QueryEditorArrayExpression, - QueryEditorExpressionType, - type QueryEditorExpression, -} from './dataquery.gen'; export interface QueryEditorOperator extends QueryEditorOperatorBase { value?: T; diff --git a/public/app/plugins/datasource/cloudwatch/guards.ts b/public/app/plugins/datasource/cloudwatch/guards.ts index 2a54dd9719c..9c29f4b4c15 100644 --- a/public/app/plugins/datasource/cloudwatch/guards.ts +++ b/public/app/plugins/datasource/cloudwatch/guards.ts @@ -5,9 +5,9 @@ import { CloudWatchLogsAnomaliesQuery, CloudWatchLogsQuery, CloudWatchMetricsQuery, - CloudWatchQuery, LogsMode, -} from './types'; +} from './dataquery.gen'; +import { CloudWatchQuery } from './types'; export const isCloudWatchLogsQuery = (cloudwatchQuery: CloudWatchQuery): cloudwatchQuery is CloudWatchLogsQuery => cloudwatchQuery.queryMode === 'Logs'; diff --git a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-logs-sql/completion/CompletionItemProvider.test.ts b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-logs-sql/completion/CompletionItemProvider.test.ts index 04b71f35a6d..606527f4711 100644 --- a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-logs-sql/completion/CompletionItemProvider.test.ts +++ b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-logs-sql/completion/CompletionItemProvider.test.ts @@ -1,6 +1,7 @@ import { CustomVariableModel } from '@grafana/data'; import { Monaco, monacoTypes } from '@grafana/ui'; +import { LogGroup } from '../../../dataquery.gen'; import { setupMockedTemplateService, logGroupNamesVariable } from '../../../mocks/CloudWatchDataSource'; import { multiLineFullQuery } from '../../../mocks/cloudwatch-logs-sql-test-data/multiLineFullQuery'; import { multiLineFullQueryWithCaseClause } from '../../../mocks/cloudwatch-logs-sql-test-data/multiLineFullQueryWithCaseClause'; @@ -11,7 +12,7 @@ import MonacoMock from '../../../mocks/monarch/Monaco'; import TextModel from '../../../mocks/monarch/TextModel'; import { ResourcesAPI } from '../../../resources/ResourcesAPI'; import { ResourceResponse } from '../../../resources/types'; -import { LogGroup, LogGroupField } from '../../../types'; +import { LogGroupField } from '../../../types'; import cloudWatchLogsLanguageDefinition from '../definition'; import { SELECT, diff --git a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-logs-sql/completion/CompletionItemProvider.ts b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-logs-sql/completion/CompletionItemProvider.ts index ea8063ff196..cdba699b7a0 100644 --- a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-logs-sql/completion/CompletionItemProvider.ts +++ b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-logs-sql/completion/CompletionItemProvider.ts @@ -1,8 +1,8 @@ import { getTemplateSrv, TemplateSrv } from '@grafana/runtime'; import type { Monaco, monacoTypes } from '@grafana/ui'; +import { LogGroup } from '../../../dataquery.gen'; import { ResourcesAPI } from '../../../resources/ResourcesAPI'; -import { LogGroup } from '../../../types'; import { CompletionItemProvider } from '../../monarch/CompletionItemProvider'; import { LinkedToken } from '../../monarch/LinkedToken'; import { TRIGGER_SUGGEST } from '../../monarch/commands'; diff --git a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-logs/CloudWatchLogsLanguageProvider.ts b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-logs/CloudWatchLogsLanguageProvider.ts index ba36458e0be..bae8ee4785f 100644 --- a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-logs/CloudWatchLogsLanguageProvider.ts +++ b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-logs/CloudWatchLogsLanguageProvider.ts @@ -5,8 +5,9 @@ import { AbsoluteTimeRange, HistoryItem, LanguageProvider } from '@grafana/data' import { BackendDataSourceResponse, FetchResponse, TemplateSrv, getTemplateSrv } from '@grafana/runtime'; import { CompletionItemGroup, SearchFunctionType, Token, TypeaheadInput, TypeaheadOutput } from '@grafana/ui'; +import { LogGroup } from '../../dataquery.gen'; import { CloudWatchDatasource } from '../../datasource'; -import { CloudWatchQuery, LogGroup } from '../../types'; +import { CloudWatchQuery } from '../../types'; import { fetchLogGroupFields } from '../utils'; import syntax, { diff --git a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-ppl/completion/PPLCompletionItemProvider.test.ts b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-ppl/completion/PPLCompletionItemProvider.test.ts index 7809ac001b5..e9f197e7c4d 100644 --- a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-ppl/completion/PPLCompletionItemProvider.test.ts +++ b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-ppl/completion/PPLCompletionItemProvider.test.ts @@ -1,6 +1,7 @@ import { CustomVariableModel } from '@grafana/data'; import { Monaco, monacoTypes } from '@grafana/ui'; +import { LogGroup } from '../../../dataquery.gen'; import { logGroupNamesVariable, setupMockedTemplateService } from '../../../mocks/CloudWatchDataSource'; import { newCommandQuery } from '../../../mocks/cloudwatch-ppl-test-data/newCommandQuery'; import { @@ -22,7 +23,7 @@ import MonacoMock from '../../../mocks/monarch/Monaco'; import TextModel from '../../../mocks/monarch/TextModel'; import { ResourcesAPI } from '../../../resources/ResourcesAPI'; import { ResourceResponse } from '../../../resources/types'; -import { LogGroup, LogGroupField } from '../../../types'; +import { LogGroupField } from '../../../types'; import cloudWatchLogsPPLLanguageDefinition from '../definition'; import { BOOLEAN_LITERALS, diff --git a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-ppl/completion/PPLCompletionItemProvider.ts b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-ppl/completion/PPLCompletionItemProvider.ts index fee0f2e23fe..52626a27ed6 100644 --- a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-ppl/completion/PPLCompletionItemProvider.ts +++ b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-ppl/completion/PPLCompletionItemProvider.ts @@ -1,8 +1,8 @@ import { getTemplateSrv, type TemplateSrv } from '@grafana/runtime'; import { Monaco, monacoTypes } from '@grafana/ui'; +import { LogGroup } from '../../../dataquery.gen'; import { type ResourcesAPI } from '../../../resources/ResourcesAPI'; -import { LogGroup } from '../../../types'; import { CompletionItemProvider } from '../../monarch/CompletionItemProvider'; import { LinkedToken } from '../../monarch/LinkedToken'; import { TRIGGER_SUGGEST } from '../../monarch/commands'; diff --git a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-sql/SQLGenerator.test.ts b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-sql/SQLGenerator.test.ts index 83f943a4f95..20a990f5ba0 100644 --- a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-sql/SQLGenerator.test.ts +++ b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-sql/SQLGenerator.test.ts @@ -1,4 +1,4 @@ -import { QueryEditorExpressionType } from '../../expressions'; +import { SQLExpression, QueryEditorExpressionType } from '../../dataquery.gen'; import { aggregationvariable, labelsVariable, @@ -14,7 +14,6 @@ import { createFunction, createProperty, } from '../../mocks/sqlUtils'; -import { SQLExpression } from '../../types'; import SQLGenerator from './SQLGenerator'; diff --git a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-sql/SQLGenerator.ts b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-sql/SQLGenerator.ts index b6058dc2daf..a74a179c248 100644 --- a/public/app/plugins/datasource/cloudwatch/language/cloudwatch-sql/SQLGenerator.ts +++ b/public/app/plugins/datasource/cloudwatch/language/cloudwatch-sql/SQLGenerator.ts @@ -7,10 +7,10 @@ import { QueryEditorExpression, QueryEditorExpressionType, QueryEditorFunctionExpression, - QueryEditorOperatorExpression, QueryEditorPropertyExpression, -} from '../../expressions'; -import { SQLExpression } from '../../types'; + SQLExpression, +} from '../../dataquery.gen'; +import { QueryEditorOperatorExpression } from '../../expressions'; import { InsightsReservedKeywords } from './consts'; diff --git a/public/app/plugins/datasource/cloudwatch/language/logs/completion/CompletionItemProvider.test.ts b/public/app/plugins/datasource/cloudwatch/language/logs/completion/CompletionItemProvider.test.ts index e586b46ed64..bcf605b9a27 100644 --- a/public/app/plugins/datasource/cloudwatch/language/logs/completion/CompletionItemProvider.test.ts +++ b/public/app/plugins/datasource/cloudwatch/language/logs/completion/CompletionItemProvider.test.ts @@ -3,6 +3,7 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; import { CustomVariableModel } from '@grafana/data'; import { monacoTypes } from '@grafana/ui'; +import { LogGroup } from '../../../dataquery.gen'; import { setupMockedTemplateService, logGroupNamesVariable } from '../../../mocks/CloudWatchDataSource'; import { logsTestDataDiffModifierQuery } from '../../../mocks/cloudwatch-logs-test-data/diffModifierQuery'; import { logsTestDataDiffQuery } from '../../../mocks/cloudwatch-logs-test-data/diffQuery'; @@ -12,7 +13,7 @@ import { logsTestDataNewCommandQuery } from '../../../mocks/cloudwatch-logs-test import { logsTestDataSortQuery } from '../../../mocks/cloudwatch-logs-test-data/sortQuery'; import { ResourcesAPI } from '../../../resources/ResourcesAPI'; import { ResourceResponse } from '../../../resources/types'; -import { LogGroup, LogGroupField } from '../../../types'; +import { LogGroupField } from '../../../types'; import cloudWatchLogsLanguageDefinition, { CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID } from '../definition'; import { DIFF_MODIFIERS, LOGS_COMMANDS, LOGS_FUNCTION_OPERATORS, SORT_DIRECTION_KEYWORDS, language } from '../language'; diff --git a/public/app/plugins/datasource/cloudwatch/language/logs/completion/CompletionItemProvider.ts b/public/app/plugins/datasource/cloudwatch/language/logs/completion/CompletionItemProvider.ts index 2d8a62920cb..e6f8ba31d74 100644 --- a/public/app/plugins/datasource/cloudwatch/language/logs/completion/CompletionItemProvider.ts +++ b/public/app/plugins/datasource/cloudwatch/language/logs/completion/CompletionItemProvider.ts @@ -1,8 +1,8 @@ import { getTemplateSrv, TemplateSrv } from '@grafana/runtime'; import { Monaco, monacoTypes } from '@grafana/ui'; +import { LogGroup } from '../../../dataquery.gen'; import { type ResourcesAPI } from '../../../resources/ResourcesAPI'; -import { LogGroup } from '../../../types'; import { CompletionItemProvider } from '../../monarch/CompletionItemProvider'; import { LinkedToken } from '../../monarch/LinkedToken'; import { TRIGGER_SUGGEST } from '../../monarch/commands'; diff --git a/public/app/plugins/datasource/cloudwatch/migrations/dashboardMigrations.test.ts b/public/app/plugins/datasource/cloudwatch/migrations/dashboardMigrations.test.ts index 848dda3d857..439b11037f7 100644 --- a/public/app/plugins/datasource/cloudwatch/migrations/dashboardMigrations.test.ts +++ b/public/app/plugins/datasource/cloudwatch/migrations/dashboardMigrations.test.ts @@ -1,6 +1,7 @@ import { AnnotationQuery, DataQuery } from '@grafana/data'; -import { CloudWatchMetricsQuery, LegacyAnnotationQuery, MetricEditorMode, MetricQueryType } from '../types'; +import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../dataquery.gen'; +import { LegacyAnnotationQuery } from '../types'; import { migrateCloudWatchQuery, diff --git a/public/app/plugins/datasource/cloudwatch/migrations/dashboardMigrations.ts b/public/app/plugins/datasource/cloudwatch/migrations/dashboardMigrations.ts index 4d97404fdcb..19171a71b2f 100644 --- a/public/app/plugins/datasource/cloudwatch/migrations/dashboardMigrations.ts +++ b/public/app/plugins/datasource/cloudwatch/migrations/dashboardMigrations.ts @@ -5,7 +5,8 @@ import { AnnotationQuery, getNextRefId } from '@grafana/data'; import { DataQuery } from '@grafana/schema'; -import { CloudWatchMetricsQuery, LegacyAnnotationQuery, MetricQueryType, MetricEditorMode } from '../types'; +import { CloudWatchMetricsQuery, MetricQueryType, MetricEditorMode } from '../dataquery.gen'; +import { LegacyAnnotationQuery } from '../types'; // E.g query.statistics = ['Max', 'Min'] will be migrated to two queries - query1.statistic = 'Max' and query2.statistic = 'Min' export function migrateMultipleStatsMetricsQuery( diff --git a/public/app/plugins/datasource/cloudwatch/migrations/metricQueryMigrations.test.ts b/public/app/plugins/datasource/cloudwatch/migrations/metricQueryMigrations.test.ts index ae6476e29bd..a15bc132531 100644 --- a/public/app/plugins/datasource/cloudwatch/migrations/metricQueryMigrations.test.ts +++ b/public/app/plugins/datasource/cloudwatch/migrations/metricQueryMigrations.test.ts @@ -1,4 +1,4 @@ -import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../types'; +import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../dataquery.gen'; import { migrateAliasPatterns, migrateMetricQuery } from './metricQueryMigrations'; diff --git a/public/app/plugins/datasource/cloudwatch/migrations/metricQueryMigrations.ts b/public/app/plugins/datasource/cloudwatch/migrations/metricQueryMigrations.ts index 7d79fbd1d86..079f0cbf12a 100644 --- a/public/app/plugins/datasource/cloudwatch/migrations/metricQueryMigrations.ts +++ b/public/app/plugins/datasource/cloudwatch/migrations/metricQueryMigrations.ts @@ -1,6 +1,6 @@ import deepEqual from 'fast-deep-equal'; -import { CloudWatchMetricsQuery } from '../types'; +import { CloudWatchMetricsQuery } from '../dataquery.gen'; import { migrateCloudWatchQuery } from './dashboardMigrations'; diff --git a/public/app/plugins/datasource/cloudwatch/migrations/useMigratedMetricsQuery.test.ts b/public/app/plugins/datasource/cloudwatch/migrations/useMigratedMetricsQuery.test.ts index 5ac0dde4410..dd6c976737a 100644 --- a/public/app/plugins/datasource/cloudwatch/migrations/useMigratedMetricsQuery.test.ts +++ b/public/app/plugins/datasource/cloudwatch/migrations/useMigratedMetricsQuery.test.ts @@ -1,7 +1,7 @@ import { renderHook } from '@testing-library/react'; +import { CloudWatchMetricsQuery } from '../dataquery.gen'; import { DEFAULT_METRICS_QUERY } from '../defaultQueries'; -import { CloudWatchMetricsQuery } from '../types'; import { migrateAliasPatterns } from './metricQueryMigrations'; import useMigratedMetricsQuery from './useMigratedMetricsQuery'; diff --git a/public/app/plugins/datasource/cloudwatch/migrations/useMigratedMetricsQuery.ts b/public/app/plugins/datasource/cloudwatch/migrations/useMigratedMetricsQuery.ts index 890a0b20908..b0933284e77 100644 --- a/public/app/plugins/datasource/cloudwatch/migrations/useMigratedMetricsQuery.ts +++ b/public/app/plugins/datasource/cloudwatch/migrations/useMigratedMetricsQuery.ts @@ -1,6 +1,6 @@ import { useEffect, useMemo } from 'react'; -import { CloudWatchMetricsQuery } from '../types'; +import { CloudWatchMetricsQuery } from '../dataquery.gen'; import { migrateMetricQuery } from './metricQueryMigrations'; diff --git a/public/app/plugins/datasource/cloudwatch/migrations/variableQueryMigrations.ts b/public/app/plugins/datasource/cloudwatch/migrations/variableQueryMigrations.ts index 74e1e6a63e2..95102d0eb74 100644 --- a/public/app/plugins/datasource/cloudwatch/migrations/variableQueryMigrations.ts +++ b/public/app/plugins/datasource/cloudwatch/migrations/variableQueryMigrations.ts @@ -1,6 +1,7 @@ import { omit } from 'lodash'; -import { Dimensions, VariableQuery, VariableQueryType, OldVariableQuery, MultiFilters } from '../types'; +import { Dimensions } from '../dataquery.gen'; +import { VariableQuery, VariableQueryType, OldVariableQuery, MultiFilters } from '../types'; const jsonVariable = /\${(\w+):json}/g; diff --git a/public/app/plugins/datasource/cloudwatch/mocks/Request.ts b/public/app/plugins/datasource/cloudwatch/mocks/Request.ts index dfcdfbeff0d..f466526c4cd 100644 --- a/public/app/plugins/datasource/cloudwatch/mocks/Request.ts +++ b/public/app/plugins/datasource/cloudwatch/mocks/Request.ts @@ -1,6 +1,7 @@ import { DataQueryRequest } from '@grafana/data'; -import { CloudWatchQuery, CloudWatchLogsQuery } from '../types'; +import { CloudWatchLogsQuery } from '../dataquery.gen'; +import { CloudWatchQuery } from '../types'; import { TimeRangeMock } from './timeRange'; diff --git a/public/app/plugins/datasource/cloudwatch/mocks/queries.ts b/public/app/plugins/datasource/cloudwatch/mocks/queries.ts index 82e6e3ef1ae..cdfca0cea3f 100644 --- a/public/app/plugins/datasource/cloudwatch/mocks/queries.ts +++ b/public/app/plugins/datasource/cloudwatch/mocks/queries.ts @@ -1,5 +1,10 @@ -import { QueryEditorExpressionType } from '../expressions'; -import { CloudWatchMetricsQuery, MetricQueryType, MetricEditorMode, CloudWatchLogsQuery } from '../types'; +import { + CloudWatchMetricsQuery, + MetricQueryType, + MetricEditorMode, + CloudWatchLogsQuery, + QueryEditorExpressionType, +} from '../dataquery.gen'; export const validMetricSearchCodeQuery: CloudWatchMetricsQuery = { id: '', diff --git a/public/app/plugins/datasource/cloudwatch/mocks/sqlUtils.ts b/public/app/plugins/datasource/cloudwatch/mocks/sqlUtils.ts index f593d43f4e4..ebc4edf07e2 100644 --- a/public/app/plugins/datasource/cloudwatch/mocks/sqlUtils.ts +++ b/public/app/plugins/datasource/cloudwatch/mocks/sqlUtils.ts @@ -2,13 +2,13 @@ import { QueryEditorExpression, QueryEditorExpressionType, QueryEditorArrayExpression, - QueryEditorOperatorExpression, QueryEditorPropertyType, QueryEditorGroupByExpression, QueryEditorFunctionExpression, QueryEditorFunctionParameterExpression, QueryEditorPropertyExpression, -} from '../expressions'; +} from '../dataquery.gen'; +import { QueryEditorOperatorExpression } from '../expressions'; export function createArray( expressions: QueryEditorExpression[], diff --git a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchAnnotationQueryRunner.test.ts b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchAnnotationQueryRunner.test.ts index cac628cea6e..3e9105f82e1 100644 --- a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchAnnotationQueryRunner.test.ts +++ b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchAnnotationQueryRunner.test.ts @@ -1,6 +1,6 @@ +import { CloudWatchAnnotationQuery } from '../dataquery.gen'; import { setupMockedAnnotationQueryRunner } from '../mocks/AnnotationQueryRunner'; import { namespaceVariable, regionVariable } from '../mocks/CloudWatchDataSource'; -import { CloudWatchAnnotationQuery } from '../types'; describe('CloudWatchAnnotationQueryRunner', () => { const queries: CloudWatchAnnotationQuery[] = [ diff --git a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchAnnotationQueryRunner.ts b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchAnnotationQueryRunner.ts index 013d14bbd6f..a563cbbe9d7 100644 --- a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchAnnotationQueryRunner.ts +++ b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchAnnotationQueryRunner.ts @@ -3,7 +3,8 @@ import { Observable } from 'rxjs'; import { DataQueryRequest, DataQueryResponse, DataSourceInstanceSettings } from '@grafana/data'; import { TemplateSrv } from '@grafana/runtime'; -import { CloudWatchAnnotationQuery, CloudWatchJsonData, CloudWatchQuery } from '../types'; +import { CloudWatchAnnotationQuery } from '../dataquery.gen'; +import { CloudWatchJsonData, CloudWatchQuery } from '../types'; import { CloudWatchRequest } from './CloudWatchRequest'; diff --git a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchLogsQueryRunner.test.ts b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchLogsQueryRunner.test.ts index 8eee779cdcf..150a89aaad4 100644 --- a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchLogsQueryRunner.test.ts +++ b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchLogsQueryRunner.test.ts @@ -10,12 +10,12 @@ import { LogRowModel, } from '@grafana/data'; +import { CloudWatchLogsAnomaliesQuery, CloudWatchLogsQuery, LogsMode } from '../dataquery.gen'; // Add this import statement import { logGroupNamesVariable, regionVariable } from '../mocks/CloudWatchDataSource'; import { setupMockedLogsQueryRunner } from '../mocks/LogsQueryRunner'; import { LogsRequestMock } from '../mocks/Request'; import { validLogsQuery } from '../mocks/queries'; import { TimeRangeMock } from '../mocks/timeRange'; -import { CloudWatchLogsAnomaliesQuery, CloudWatchLogsQuery, LogsMode } from '../types'; // Add this import statement import { LOGSTREAM_IDENTIFIER_INTERNAL, diff --git a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchLogsQueryRunner.ts b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchLogsQueryRunner.ts index cd8e8b29f1c..470824f76c0 100644 --- a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchLogsQueryRunner.ts +++ b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchLogsQueryRunner.ts @@ -38,17 +38,14 @@ import { type CustomFormatterVariable } from '@grafana/scenes'; import { GraphDrawStyle } from '@grafana/schema/dist/esm/index'; import { TableCellDisplayMode } from '@grafana/ui'; +import { CloudWatchLogsQuery, LogsMode, CloudWatchLogsAnomaliesQuery, LogsQueryLanguage } from '../dataquery.gen'; import { CloudWatchJsonData, - CloudWatchLogsAnomaliesQuery, - CloudWatchLogsQuery, CloudWatchLogsQueryStatus, CloudWatchLogsRequest, CloudWatchQuery, GetLogEventsRequest, LogAction, - LogsMode, - LogsQueryLanguage, QueryParam, StartQueryRequest, } from '../types'; diff --git a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchMetricsQueryRunner.test.ts b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchMetricsQueryRunner.test.ts index 0234af74af8..59c84b7634c 100644 --- a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchMetricsQueryRunner.test.ts +++ b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchMetricsQueryRunner.test.ts @@ -3,6 +3,7 @@ import { of } from 'rxjs'; import { dateTime, CustomVariableModel, getFrameDisplayName, VariableHide } from '@grafana/data'; import { toDataQueryResponse } from '@grafana/runtime'; +import { MetricQueryType, MetricEditorMode, CloudWatchMetricsQuery } from '../dataquery.gen'; import { namespaceVariable, metricVariable, @@ -15,7 +16,6 @@ import { import { initialVariableModelState } from '../mocks/CloudWatchVariables'; import { setupMockedMetricsQueryRunner } from '../mocks/MetricsQueryRunner'; import { validMetricSearchBuilderQuery, validMetricSearchCodeQuery } from '../mocks/queries'; -import { MetricQueryType, MetricEditorMode, CloudWatchMetricsQuery } from '../types'; jest.mock('@grafana/runtime', () => ({ ...jest.requireActual('@grafana/runtime'), diff --git a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchMetricsQueryRunner.ts b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchMetricsQueryRunner.ts index 6560e3d4eed..852cfa93fd4 100644 --- a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchMetricsQueryRunner.ts +++ b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchMetricsQueryRunner.ts @@ -17,9 +17,10 @@ import { import { TemplateSrv, getAppEvents } from '@grafana/runtime'; import { ThrottlingErrorMessage } from '../components/Errors/ThrottlingErrorMessage'; +import { CloudWatchMetricsQuery } from '../dataquery.gen'; import memoizedDebounce from '../memoizedDebounce'; import { migrateMetricQuery } from '../migrations/metricQueryMigrations'; -import { CloudWatchJsonData, CloudWatchMetricsQuery, CloudWatchQuery } from '../types'; +import { CloudWatchJsonData, CloudWatchQuery } from '../types'; import { filterMetricsQuery } from '../utils/utils'; import { CloudWatchRequest } from './CloudWatchRequest'; diff --git a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchRequest.ts b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchRequest.ts index 460a2e7ee49..7a022e197c3 100644 --- a/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchRequest.ts +++ b/public/app/plugins/datasource/cloudwatch/query-runner/CloudWatchRequest.ts @@ -3,8 +3,9 @@ import { Observable } from 'rxjs'; import { DataSourceInstanceSettings, DataSourceRef, getDataSourceRef, ScopedVars, AppEvents } from '@grafana/data'; import { BackendDataSourceResponse, FetchResponse, getBackendSrv, TemplateSrv, getAppEvents } from '@grafana/runtime'; +import { Dimensions } from '../dataquery.gen'; import memoizedDebounce from '../memoizedDebounce'; -import { CloudWatchJsonData, Dimensions, MetricRequest, MultiFilters } from '../types'; +import { CloudWatchJsonData, MetricRequest, MultiFilters } from '../types'; import { getVariableName } from '../utils/templateVariableUtils'; export abstract class CloudWatchRequest { diff --git a/public/app/plugins/datasource/cloudwatch/resources/types.ts b/public/app/plugins/datasource/cloudwatch/resources/types.ts index 290da62c171..83c3252561a 100644 --- a/public/app/plugins/datasource/cloudwatch/resources/types.ts +++ b/public/app/plugins/datasource/cloudwatch/resources/types.ts @@ -1,6 +1,6 @@ import { SelectableValue } from '@grafana/data'; -import { Dimensions } from '../types'; +import { Dimensions } from '../dataquery.gen'; export interface ResourceResponse { accountId?: string; diff --git a/public/app/plugins/datasource/cloudwatch/tracking.ts b/public/app/plugins/datasource/cloudwatch/tracking.ts index 51a4559ee1e..e2d863f3d64 100644 --- a/public/app/plugins/datasource/cloudwatch/tracking.ts +++ b/public/app/plugins/datasource/cloudwatch/tracking.ts @@ -1,19 +1,19 @@ import { DashboardLoadedEvent } from '@grafana/data'; import { config, reportInteraction } from '@grafana/runtime'; +import { + CloudWatchLogsQuery, + CloudWatchLogsAnomaliesQuery, + CloudWatchMetricsQuery, + LogsMode, + LogsQueryLanguage, + MetricQueryType, + MetricEditorMode, +} from './dataquery.gen'; import { isCloudWatchLogsQuery, isCloudWatchMetricsQuery, isLogsAnomaliesQuery } from './guards'; import { migrateMetricQuery } from './migrations/metricQueryMigrations'; import pluginJson from './plugin.json'; -import { - CloudWatchLogsAnomaliesQuery, - CloudWatchLogsQuery, - CloudWatchMetricsQuery, - CloudWatchQuery, - LogsMode, - LogsQueryLanguage, - MetricEditorMode, - MetricQueryType, -} from './types'; +import { CloudWatchQuery } from './types'; import { filterMetricsQuery } from './utils/utils'; type CloudWatchOnDashboardLoadedTrackingEvent = { diff --git a/public/app/plugins/datasource/cloudwatch/types.ts b/public/app/plugins/datasource/cloudwatch/types.ts index b774bfade40..f1e92d47cbd 100644 --- a/public/app/plugins/datasource/cloudwatch/types.ts +++ b/public/app/plugins/datasource/cloudwatch/types.ts @@ -4,8 +4,6 @@ import { DataQuery } from '@grafana/schema'; import * as raw from './dataquery.gen'; -export * from './dataquery.gen'; - export type CloudWatchQuery = | raw.CloudWatchMetricsQuery | raw.CloudWatchLogsQuery diff --git a/public/app/plugins/datasource/cloudwatch/utils/datalinks.ts b/public/app/plugins/datasource/cloudwatch/utils/datalinks.ts index e69ae4e4e17..16bfc81f70e 100644 --- a/public/app/plugins/datasource/cloudwatch/utils/datalinks.ts +++ b/public/app/plugins/datasource/cloudwatch/utils/datalinks.ts @@ -10,7 +10,8 @@ import { import { getDataSourceSrv } from '@grafana/runtime'; import { AwsUrl, encodeUrl } from '../aws_url'; -import { CloudWatchLogsQuery, CloudWatchQuery } from '../types'; +import { CloudWatchLogsQuery } from '../dataquery.gen'; +import { CloudWatchQuery } from '../types'; type ReplaceFn = ( target?: string, diff --git a/public/app/plugins/datasource/cloudwatch/utils/utils.ts b/public/app/plugins/datasource/cloudwatch/utils/utils.ts index b98751ce156..38fc50067a7 100644 --- a/public/app/plugins/datasource/cloudwatch/utils/utils.ts +++ b/public/app/plugins/datasource/cloudwatch/utils/utils.ts @@ -1,6 +1,6 @@ import { SelectableValue } from '@grafana/data'; -import { CloudWatchMetricsQuery, MetricQueryType, MetricEditorMode } from '../types'; +import { CloudWatchMetricsQuery, MetricQueryType, MetricEditorMode } from '../dataquery.gen'; import { CloudWatchDatasource } from './../datasource'; diff --git a/public/app/plugins/datasource/grafana-postgresql-datasource/datasource.test.ts b/public/app/plugins/datasource/grafana-postgresql-datasource/datasource.test.ts index 207991a495a..9067ab7f138 100644 --- a/public/app/plugins/datasource/grafana-postgresql-datasource/datasource.test.ts +++ b/public/app/plugins/datasource/grafana-postgresql-datasource/datasource.test.ts @@ -714,7 +714,7 @@ describe('PostgreSQLDatasource', () => { it('should return a quoted value', () => { const { ds, variable } = setupTestContext({}); variable.multi = true; - expect(ds.interpolateVariable('abc', variable)).toEqual("'abc'"); + expect(ds.interpolateVariable('abc', variable)).toEqual('abc'); }); }); @@ -722,8 +722,8 @@ describe('PostgreSQLDatasource', () => { it('should return a quoted value', () => { const { ds, variable } = setupTestContext({}); variable.multi = true; - expect(ds.interpolateVariable("a'bc", variable)).toEqual("'a''bc'"); - expect(ds.interpolateVariable("a'b'c", variable)).toEqual("'a''b''c'"); + expect(ds.interpolateVariable("a'bc", variable)).toEqual("a''bc"); + expect(ds.interpolateVariable("a'b'c", variable)).toEqual("a''b''c"); }); }); @@ -731,7 +731,7 @@ describe('PostgreSQLDatasource', () => { it('should return a quoted value', () => { const { ds, variable } = setupTestContext({}); variable.includeAll = true; - expect(ds.interpolateVariable('abc', variable)).toEqual("'abc'"); + expect(ds.interpolateVariable('abc', variable)).toEqual('abc'); }); }); }); diff --git a/public/app/plugins/datasource/grafana-postgresql-datasource/datasource.ts b/public/app/plugins/datasource/grafana-postgresql-datasource/datasource.ts index 3a79e700fb7..9ea4498db62 100644 --- a/public/app/plugins/datasource/grafana-postgresql-datasource/datasource.ts +++ b/public/app/plugins/datasource/grafana-postgresql-datasource/datasource.ts @@ -1,6 +1,6 @@ import { v4 as uuidv4 } from 'uuid'; -import { DataSourceInstanceSettings, ScopedVars } from '@grafana/data'; +import { DataSourceInstanceSettings, ScopedVars, VariableWithMultiSupport } from '@grafana/data'; import { LanguageDefinition } from '@grafana/plugin-ui'; import { TemplateSrv } from '@grafana/runtime'; import { @@ -31,6 +31,28 @@ export class PostgresDatasource extends SqlDatasource { return new PostgresQueryModel(target, templateSrv, scopedVars); } + interpolateVariable = (value: string | string[] | number, variable: VariableWithMultiSupport) => { + if (typeof value === 'string') { + // For single string values, just escape quotes (don't add outer quotes) + // The quotes are provided by the query template: WHERE x = '$var' + // We only escape internal single quotes: O'Brien -> O''Brien + return String(value).replace(/'/g, "''"); + } + + if (typeof value === 'number') { + return value; + } + + if (Array.isArray(value)) { + // For arrays, quote each value individually and join with comma + // Used in: WHERE x IN ($var) -> WHERE x IN ('val1','val2','val3') + const quotedValues = value.map((v) => this.getQueryModel().quoteLiteral(v)); + return quotedValues.join(','); + } + + return value; + }; + async getVersion(): Promise { const value = await this.runSql<{ version: number }>(getVersion()); const results = value.fields.version?.values; diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/EditorField.tsx b/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/EditorField.tsx index dd5b27f56c1..401a3ed4d5c 100644 --- a/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/EditorField.tsx +++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/EditorField.tsx @@ -7,7 +7,7 @@ import { Field, Icon, PopoverContent, ReactUtils, Tooltip, useStyles2 } from '@g interface EditorFieldProps extends ComponentProps { label: string; - children: React.ReactElement; + children: React.ReactElement>; width?: number | string; optional?: boolean; tooltip?: PopoverContent; diff --git a/public/app/plugins/datasource/loki/LanguageProvider.test.ts b/public/app/plugins/datasource/loki/LanguageProvider.test.ts index 02a365c7d9a..447911c70a5 100644 --- a/public/app/plugins/datasource/loki/LanguageProvider.test.ts +++ b/public/app/plugins/datasource/loki/LanguageProvider.test.ts @@ -2,6 +2,7 @@ import { AbstractLabelOperator, DataFrame, TimeRange, dateTime, ScopedVars } fro import { config } from '@grafana/runtime'; import LanguageProvider from './LanguageProvider'; +import { LokiQueryType } from './dataquery.gen'; import { DEFAULT_MAX_LINES_SAMPLE, LokiDatasource } from './datasource'; import { createDetectedFieldValuesMetadataRequest } from './mocks/createDetectedFieldValuesMetadataRequest'; import { createDetectedFieldsMetadataRequest } from './mocks/createDetectedFieldsMetadataRequest'; @@ -12,7 +13,7 @@ import { extractLabelKeysFromDataFrame, extractUnwrapLabelKeysFromDataFrame, } from './responseUtils'; -import { DetectedFieldsResult, LabelType, LokiQueryType } from './types'; +import { DetectedFieldsResult, LabelType } from './types'; jest.mock('./responseUtils'); diff --git a/public/app/plugins/datasource/loki/LanguageProvider.ts b/public/app/plugins/datasource/loki/LanguageProvider.ts index 9b86f01796d..a6851e474d4 100644 --- a/public/app/plugins/datasource/loki/LanguageProvider.ts +++ b/public/app/plugins/datasource/loki/LanguageProvider.ts @@ -4,6 +4,7 @@ import { LRUCache } from 'lru-cache'; import { AbstractQuery, getDefaultTimeRange, KeyValue, LanguageProvider, ScopedVars, TimeRange } from '@grafana/data'; import { BackendSrvRequest, config } from '@grafana/runtime'; +import { LokiQueryType } from './dataquery.gen'; import { DEFAULT_MAX_LINES_SAMPLE, LokiDatasource } from './datasource'; import { abstractQueryToExpr, mapAbstractOperatorsToOp, processLabels } from './languageUtils'; import { getStreamSelectorsFromQuery } from './queryUtils'; @@ -13,7 +14,7 @@ import { extractLogParserFromDataFrame, extractUnwrapLabelKeysFromDataFrame, } from './responseUtils'; -import { DetectedFieldsResult, LabelType, LokiQuery, LokiQueryType, ParserAndLabelKeysResult } from './types'; +import { DetectedFieldsResult, LabelType, LokiQuery, ParserAndLabelKeysResult } from './types'; const NS_IN_MS = 1000000; const EMPTY_SELECTOR = '{}'; diff --git a/public/app/plugins/datasource/loki/LogContextProvider.ts b/public/app/plugins/datasource/loki/LogContextProvider.ts index 3de58ba2e4a..83d22fa49fe 100644 --- a/public/app/plugins/datasource/loki/LogContextProvider.ts +++ b/public/app/plugins/datasource/loki/LogContextProvider.ts @@ -19,6 +19,7 @@ import { import { LabelParser, LabelFilter, LineFilters, PipelineStage, Logfmt, Json } from '@grafana/lezer-logql'; import { LokiContextUi } from './components/LokiContextUi'; +import { LokiQueryDirection, LokiQueryType } from './dataquery.gen'; import { LokiDatasource, makeRequest, REF_ID_STARTER_LOG_ROW_CONTEXT } from './datasource'; import { escapeLabelValueInExactSelector, getLabelTypeFromFrame } from './languageUtils'; import { addLabelToQuery, addParserToQuery } from './modifyQuery'; @@ -29,7 +30,7 @@ import { isQueryWithParser, } from './queryUtils'; import { sortDataFrameByTime, SortDirection } from './sortDataFrame'; -import { ContextFilter, LabelType, LokiQuery, LokiQueryDirection, LokiQueryType } from './types'; +import { ContextFilter, LabelType, LokiQuery } from './types'; export const LOKI_LOG_CONTEXT_PRESERVED_LABELS = 'lokiLogContextPreservedLabels'; export const SHOULD_INCLUDE_PIPELINE_OPERATIONS = 'lokiLogContextShouldIncludePipelineOperations'; diff --git a/public/app/plugins/datasource/loki/backendResultTransformer.ts b/public/app/plugins/datasource/loki/backendResultTransformer.ts index 1cc91c4c621..6ed0ee1d288 100644 --- a/public/app/plugins/datasource/loki/backendResultTransformer.ts +++ b/public/app/plugins/datasource/loki/backendResultTransformer.ts @@ -1,10 +1,11 @@ import { DataQueryResponse, DataFrame, isDataFrame, FieldType, QueryResultMeta, DataQueryError } from '@grafana/data'; +import { LokiQueryType } from './dataquery.gen'; import { getDerivedFields } from './getDerivedFields'; import { makeTableFrames } from './makeTableFrames'; import { getExpressionFromExecutedQuery, getHighlighterExpressionsFromQuery } from './queryUtils'; import { dataFrameHasLokiError } from './responseUtils'; -import { DerivedFieldConfig, LokiQuery, LokiQueryType } from './types'; +import { DerivedFieldConfig, LokiQuery } from './types'; function isMetricFrame(frame: DataFrame): boolean { return frame.fields.every((field) => field.type === FieldType.time || field.type === FieldType.number); diff --git a/public/app/plugins/datasource/loki/components/LokiOptionFields.tsx b/public/app/plugins/datasource/loki/components/LokiOptionFields.tsx index 01aeb2c0574..3e773722f88 100644 --- a/public/app/plugins/datasource/loki/components/LokiOptionFields.tsx +++ b/public/app/plugins/datasource/loki/components/LokiOptionFields.tsx @@ -5,7 +5,8 @@ import { SelectableValue } from '@grafana/data'; import { config, reportInteraction } from '@grafana/runtime'; import { InlineField, Input, Stack } from '@grafana/ui'; -import { LokiQuery, LokiQueryDirection, LokiQueryType } from '../types'; +import { LokiQueryType, LokiQueryDirection } from '../dataquery.gen'; +import { LokiQuery } from '../types'; export interface LokiOptionFieldsProps { lineLimitValue: string; diff --git a/public/app/plugins/datasource/loki/components/LokiQueryEditor.test.tsx b/public/app/plugins/datasource/loki/components/LokiQueryEditor.test.tsx index 5897d65018c..3d228199ac8 100644 --- a/public/app/plugins/datasource/loki/components/LokiQueryEditor.test.tsx +++ b/public/app/plugins/datasource/loki/components/LokiQueryEditor.test.tsx @@ -5,9 +5,10 @@ import { cloneDeep, defaultsDeep } from 'lodash'; import { CoreApp } from '@grafana/data'; import { QueryEditorMode } from '@grafana/plugin-ui'; +import { LokiQueryType } from '../dataquery.gen'; import { createLokiDatasource } from '../mocks/datasource'; import { EXPLAIN_LABEL_FILTER_CONTENT } from '../querybuilder/components/LokiQueryBuilderExplained'; -import { LokiQuery, LokiQueryType } from '../types'; +import { LokiQuery } from '../types'; import { LokiQueryEditor } from './LokiQueryEditor'; import { LokiQueryEditorProps } from './types'; diff --git a/public/app/plugins/datasource/loki/components/stats.test.ts b/public/app/plugins/datasource/loki/components/stats.test.ts index 89535558ef1..4fea9703117 100644 --- a/public/app/plugins/datasource/loki/components/stats.test.ts +++ b/public/app/plugins/datasource/loki/components/stats.test.ts @@ -1,6 +1,6 @@ import { dateTime, getDefaultTimeRange } from '@grafana/data'; -import { LokiQueryType } from '../types'; +import { LokiQueryType } from '../dataquery.gen'; import { shouldUpdateStats } from './stats'; diff --git a/public/app/plugins/datasource/loki/components/stats.ts b/public/app/plugins/datasource/loki/components/stats.ts index 1b35497c67f..3a3d3f9188e 100644 --- a/public/app/plugins/datasource/loki/components/stats.ts +++ b/public/app/plugins/datasource/loki/components/stats.ts @@ -1,6 +1,6 @@ import { DateTime, isDateTime, TimeRange } from '@grafana/data'; -import { LokiQueryType } from '../types'; +import { LokiQueryType } from '../dataquery.gen'; /** * This function compares two time values. If the first is absolute, it compares them using `DateTime.isSame`. diff --git a/public/app/plugins/datasource/loki/datasource.test.ts b/public/app/plugins/datasource/loki/datasource.test.ts index 359e1716055..533ce1ce23c 100644 --- a/public/app/plugins/datasource/loki/datasource.test.ts +++ b/public/app/plugins/datasource/loki/datasource.test.ts @@ -33,11 +33,12 @@ import { } from '@grafana/runtime'; import { LokiVariableSupport } from './LokiVariableSupport'; +import { LokiQueryType, SupportingQueryType } from './dataquery.gen'; import { LokiDatasource, REF_ID_DATA_SAMPLES } from './datasource'; import { createLokiDatasource } from './mocks/datasource'; import { createMetadataRequest } from './mocks/metadataRequest'; import { runSplitQuery } from './querySplitting'; -import { LokiOptions, LokiQuery, LokiQueryType, LokiVariableQueryType, SupportingQueryType } from './types'; +import { LokiOptions, LokiQuery, LokiVariableQueryType } from './types'; jest.mock('@grafana/runtime', () => { return { diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index c7b60f169a5..fa047772588 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -54,6 +54,7 @@ import { LokiVariableSupport } from './LokiVariableSupport'; import { transformBackendResult } from './backendResultTransformer'; import { LokiAnnotationsQueryEditor } from './components/AnnotationsQueryEditor'; import { placeHolderScopedVars } from './components/monaco-query-field/monaco-completion-provider/validation'; +import { LokiQueryType, SupportingQueryType } from './dataquery.gen'; import { escapeLabelValueInSelector, isRegexSelector, getLabelTypeFromFrame } from './languageUtils'; import { labelNamesRegex, labelValuesRegex } from './migrations/variableQueryMigrations'; import { @@ -88,15 +89,7 @@ import { replaceVariables, returnVariables } from './querybuilder/parsingUtils'; import { runShardSplitQuery } from './shardQuerySplitting'; import { convertToWebSocketUrl, doLokiChannelStream } from './streaming'; import { trackQuery } from './tracking'; -import { - LokiOptions, - LokiQuery, - LokiQueryType, - LokiVariableQuery, - LokiVariableQueryType, - QueryStats, - SupportingQueryType, -} from './types'; +import { LokiOptions, LokiQuery, LokiVariableQuery, LokiVariableQueryType, QueryStats } from './types'; export type RangeQueryOptions = DataQueryRequest | AnnotationQueryRequest; export const DEFAULT_MAX_LINES = 1000; diff --git a/public/app/plugins/datasource/loki/querySplitting.test.ts b/public/app/plugins/datasource/loki/querySplitting.test.ts index 2d04b447005..fdadf7c0965 100644 --- a/public/app/plugins/datasource/loki/querySplitting.test.ts +++ b/public/app/plugins/datasource/loki/querySplitting.test.ts @@ -3,13 +3,14 @@ import { of } from 'rxjs'; import { DataQueryError, DataQueryRequest, DataQueryResponse, dateTime, LoadingState } from '@grafana/data'; import { config } from '@grafana/runtime'; +import { LokiQueryType, LokiQueryDirection } from './dataquery.gen'; import { LokiDatasource } from './datasource'; import { createLokiDatasource } from './mocks/datasource'; import { getMockFrames } from './mocks/frames'; import { runSplitQuery } from './querySplitting'; import { LOKI_MAX_QUERY_BYTES_READ_ERROR_MSG_PREFIX, LOKI_TIMEOUT_ERROR_MSG } from './responseUtils'; import { trackGroupedQueries } from './tracking'; -import { LokiQuery, LokiQueryDirection, LokiQueryType } from './types'; +import { LokiQuery } from './types'; jest.mock('./tracking'); jest.mock('uuid', () => ({ diff --git a/public/app/plugins/datasource/loki/querySplitting.ts b/public/app/plugins/datasource/loki/querySplitting.ts index 89a466b21d0..4d383955b3f 100644 --- a/public/app/plugins/datasource/loki/querySplitting.ts +++ b/public/app/plugins/datasource/loki/querySplitting.ts @@ -15,6 +15,7 @@ import { } from '@grafana/data'; import { config } from '@grafana/runtime'; +import { LokiQueryType, LokiQueryDirection } from './dataquery.gen'; import { LokiDatasource } from './datasource'; import { splitTimeRange as splitLogsTimeRange } from './logsTimeSplitting'; import { combineResponses } from './mergeResponses'; @@ -22,7 +23,7 @@ import { splitTimeRange as splitMetricTimeRange } from './metricTimeSplitting'; import { addQueryLimitsContext, isLogsQuery, isQueryWithRangeVariable } from './queryUtils'; import { isRetriableError } from './responseUtils'; import { trackGroupedQueries } from './tracking'; -import { LokiGroupedRequest, LokiQuery, LokiQueryDirection, LokiQueryType } from './types'; +import { LokiGroupedRequest, LokiQuery } from './types'; export function partitionTimeRange( isLogsQuery: boolean, diff --git a/public/app/plugins/datasource/loki/queryUtils.test.ts b/public/app/plugins/datasource/loki/queryUtils.test.ts index e901b77c55b..9ff9a87e3d6 100644 --- a/public/app/plugins/datasource/loki/queryUtils.test.ts +++ b/public/app/plugins/datasource/loki/queryUtils.test.ts @@ -1,5 +1,6 @@ import { String } from '@grafana/lezer-logql'; +import { LokiQueryType, LokiQueryDirection } from './dataquery.gen'; import { getHighlighterExpressionsFromQuery, getLokiQueryType, @@ -20,7 +21,7 @@ import { interpolateShardingSelector, requestSupportsSharding, } from './queryUtils'; -import { LokiQuery, LokiQueryDirection, LokiQueryType } from './types'; +import { LokiQuery } from './types'; describe('getHighlighterExpressionsFromQuery', () => { it('returns no expressions for empty query', () => { diff --git a/public/app/plugins/datasource/loki/queryUtils.ts b/public/app/plugins/datasource/loki/queryUtils.ts index a4a895feae5..6b158edbe48 100644 --- a/public/app/plugins/datasource/loki/queryUtils.ts +++ b/public/app/plugins/datasource/loki/queryUtils.ts @@ -29,9 +29,10 @@ import { } from '@grafana/lezer-logql'; import { DataQuery } from '@grafana/schema'; +import { LokiQueryType, LokiQueryDirection } from './dataquery.gen'; import { addDropToQuery, addLabelToQuery, getStreamSelectorPositions, NodePosition } from './modifyQuery'; import { ErrorId } from './querybuilder/parsingUtils'; -import { LabelType, LokiQuery, LokiQueryDirection, LokiQueryType } from './types'; +import { LabelType, LokiQuery } from './types'; /** * Returns search terms from a LogQL query. diff --git a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.test.tsx b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.test.tsx index c03de3eb2e8..50a5c64f1a3 100644 --- a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.test.tsx +++ b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.test.tsx @@ -4,8 +4,9 @@ import userEvent from '@testing-library/user-event'; import { CoreApp, LogSortOrderChangeEvent, LogsSortOrder, store } from '@grafana/data'; import { config, getAppEvents } from '@grafana/runtime'; +import { LokiQueryType, LokiQueryDirection } from '../../dataquery.gen'; import { createLokiDatasource } from '../../mocks/datasource'; -import { LokiQuery, LokiQueryDirection, LokiQueryType } from '../../types'; +import { LokiQuery } from '../../types'; import { LokiQueryBuilderOptions, Props } from './LokiQueryBuilderOptions'; diff --git a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.tsx b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.tsx index 27d199cb8a5..27a6dbbe533 100644 --- a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.tsx +++ b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderOptions.tsx @@ -14,9 +14,10 @@ import { queryTypeOptions, } from '../../components/LokiOptionFields'; import { placeHolderScopedVars } from '../../components/monaco-query-field/monaco-completion-provider/validation'; +import { LokiQueryDirection, LokiQueryType } from '../../dataquery.gen'; import { LokiDatasource } from '../../datasource'; import { getLokiQueryType, isLogsQuery } from '../../queryUtils'; -import { LokiQuery, LokiQueryDirection, LokiQueryType, QueryStats } from '../../types'; +import { LokiQuery, QueryStats } from '../../types'; export interface Props { query: LokiQuery; diff --git a/public/app/plugins/datasource/loki/querybuilder/state.ts b/public/app/plugins/datasource/loki/querybuilder/state.ts index 5f8aaecad55..dcd70852465 100644 --- a/public/app/plugins/datasource/loki/querybuilder/state.ts +++ b/public/app/plugins/datasource/loki/querybuilder/state.ts @@ -1,6 +1,7 @@ import { QueryEditorMode } from '@grafana/plugin-ui'; -import { LokiQuery, LokiQueryType } from '../types'; +import { LokiQueryType } from '../dataquery.gen'; +import { LokiQuery } from '../types'; const queryEditorModeDefaultLocalStorageKey = 'LokiQueryEditorModeDefault'; diff --git a/public/app/plugins/datasource/loki/shardQuerySplitting.test.ts b/public/app/plugins/datasource/loki/shardQuerySplitting.test.ts index cebee5bee94..0196fd90d64 100644 --- a/public/app/plugins/datasource/loki/shardQuerySplitting.test.ts +++ b/public/app/plugins/datasource/loki/shardQuerySplitting.test.ts @@ -3,12 +3,13 @@ import { of } from 'rxjs'; import { DataQueryRequest, DataQueryResponse, dateTime, LoadingState } from '@grafana/data'; import { config } from '@grafana/runtime'; +import { LokiQueryDirection, LokiQueryType } from './dataquery.gen'; import { LokiDatasource } from './datasource'; import { createLokiDatasource } from './mocks/datasource'; import { getMockFrames } from './mocks/frames'; import { LOKI_MAX_QUERY_BYTES_READ_ERROR_MSG_PREFIX, LOKI_TIMEOUT_ERROR_MSG } from './responseUtils'; import { runShardSplitQuery } from './shardQuerySplitting'; -import { LokiQuery, LokiQueryDirection, LokiQueryType } from './types'; +import { LokiQuery } from './types'; jest.mock('uuid', () => ({ v4: jest.fn().mockReturnValue('uuid'), diff --git a/public/app/plugins/datasource/loki/tracking.ts b/public/app/plugins/datasource/loki/tracking.ts index 5714d8b4e5a..85d12446e6d 100644 --- a/public/app/plugins/datasource/loki/tracking.ts +++ b/public/app/plugins/datasource/loki/tracking.ts @@ -2,6 +2,7 @@ import { CoreApp, DashboardLoadedEvent, DataQueryRequest, DataQueryResponse } fr import { QueryEditorMode } from '@grafana/plugin-ui'; import { reportInteraction, config } from '@grafana/runtime'; +import { LokiQueryType } from './dataquery.gen'; import { REF_ID_STARTER_ANNOTATION, REF_ID_DATA_SAMPLES, @@ -12,7 +13,7 @@ import { import pluginJson from './plugin.json'; import { getNormalizedLokiQuery, isLogsQuery, obfuscate } from './queryUtils'; import { variableRegex } from './querybuilder/parsingUtils'; -import { LokiGroupedRequest, LokiQuery, LokiQueryType } from './types'; +import { LokiGroupedRequest, LokiQuery } from './types'; type LokiOnDashboardLoadedTrackingEvent = { grafana_version?: string; diff --git a/public/app/plugins/datasource/loki/types.ts b/public/app/plugins/datasource/loki/types.ts index ae650931390..6c2e0d2deea 100644 --- a/public/app/plugins/datasource/loki/types.ts +++ b/public/app/plugins/datasource/loki/types.ts @@ -7,8 +7,6 @@ import { LokiQueryDirection, } from './dataquery.gen'; -export { LokiQueryDirection, LokiQueryType, SupportingQueryType }; - export enum LokiResultType { Stream = 'streams', Vector = 'vector', diff --git a/public/app/plugins/datasource/mssql/configuration/ConfigurationEditor.tsx b/public/app/plugins/datasource/mssql/configuration/ConfigurationEditor.tsx index 707e1b0bb0d..5a80db52824 100644 --- a/public/app/plugins/datasource/mssql/configuration/ConfigurationEditor.tsx +++ b/public/app/plugins/datasource/mssql/configuration/ConfigurationEditor.tsx @@ -49,10 +49,8 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps - {azureAuthIsSupported && ( -
  • - - Azure Authentication Securely authenticate and access Azure resources and applications using - Azure AD credentials - Managed Service Identity and Client Secret Credentials are supported. - -
  • - )} +
  • + + Azure Authentication Securely authenticate and access Azure resources and applications using + Azure AD credentials - Managed Service Identity and Client Secret Credentials are supported. + +
  • Windows AD: Username + password Windows Active Directory - Sign on for domain user via @@ -393,7 +383,7 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps )} - {azureAuthIsSupported && jsonData.authenticationType === MSSQLAuthenticationType.azureAuth && ( + {jsonData.authenticationType === MSSQLAuthenticationType.azureAuth && (
    diff --git a/public/app/plugins/datasource/mssql/types.ts b/public/app/plugins/datasource/mssql/types.ts index c4ed9763cec..4e784c38877 100644 --- a/public/app/plugins/datasource/mssql/types.ts +++ b/public/app/plugins/datasource/mssql/types.ts @@ -39,6 +39,5 @@ export interface MssqlSecureOptions { } export type AzureAuthConfigType = { - azureAuthIsSupported: boolean; azureAuthSettingsUI: (props: HttpSettingsBaseProps) => JSX.Element; }; diff --git a/public/app/plugins/datasource/opentsdb/components/AnnotationEditor.tsx b/public/app/plugins/datasource/opentsdb/components/AnnotationEditor.tsx index d6fbfd8b8c4..e3e579185db 100644 --- a/public/app/plugins/datasource/opentsdb/components/AnnotationEditor.tsx +++ b/public/app/plugins/datasource/opentsdb/components/AnnotationEditor.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import { QueryEditorProps } from '@grafana/data'; -import { InlineFormLabel, Input, InlineSwitch } from '@grafana/ui'; +import { InlineFormLabel, Input, InlineSwitch, Stack } from '@grafana/ui'; import OpenTsDatasource from '../datasource'; import { OpenTsdbQuery, OpenTsdbOptions } from '../types'; @@ -26,8 +26,8 @@ export const AnnotationEditor = (props: QueryEditorProps -
    + + OpenTSDB metrics query updateValue('target', target)} placeholder="events.eventname" /> -
    -
    + + Show Global Annotations? updateIsGlobal(isGlobal)} /> -
    -
  • + + ); }; diff --git a/public/app/plugins/datasource/opentsdb/components/MetricSection.tsx b/public/app/plugins/datasource/opentsdb/components/MetricSection.tsx index 5c62f2ecf06..2ca39e4a19d 100644 --- a/public/app/plugins/datasource/opentsdb/components/MetricSection.tsx +++ b/public/app/plugins/datasource/opentsdb/components/MetricSection.tsx @@ -31,7 +31,7 @@ export function MetricSection({ query, onChange, onRunQuery, suggestMetrics, agg placeholder="Metric name" allowCustomValue loadOptions={metricSearch} - defaultOptions={[]} + defaultOptions={true} onChange={({ value }) => { if (value) { onChange({ ...query, metric: value }); diff --git a/public/app/plugins/datasource/opentsdb/datasource.ts b/public/app/plugins/datasource/opentsdb/datasource.ts index 2b70dfb605c..1413daacfc2 100644 --- a/public/app/plugins/datasource/opentsdb/datasource.ts +++ b/public/app/plugins/datasource/opentsdb/datasource.ts @@ -18,21 +18,28 @@ import { catchError, map } from 'rxjs/operators'; import { AnnotationEvent, + DataFrame, DataQueryRequest, DataQueryResponse, - DataSourceApi, dateMath, DateTime, ScopedVars, toDataFrame, } from '@grafana/data'; -import { FetchResponse, getBackendSrv, getTemplateSrv, TemplateSrv } from '@grafana/runtime'; +import { + config, + DataSourceWithBackend, + FetchResponse, + getBackendSrv, + getTemplateSrv, + TemplateSrv, +} from '@grafana/runtime'; import { AnnotationEditor } from './components/AnnotationEditor'; import { prepareAnnotation } from './migrations'; import { OpenTsdbFilter, OpenTsdbOptions, OpenTsdbQuery } from './types'; -export default class OpenTsDatasource extends DataSourceApi { +export default class OpenTsDatasource extends DataSourceWithBackend { type: 'opentsdb'; url: string; name: string; @@ -72,6 +79,20 @@ export default class OpenTsDatasource extends DataSourceApi): Observable { + if (config.featureToggles.opentsdbBackendMigration) { + const hasValidTargets = options.targets.some((target) => target.metric && !target.hide); + if (!hasValidTargets) { + return of({ data: [] }); + } + + return super.query(options).pipe( + map((response) => { + this._saveTagKeysFromFrames(response.data); + return response; + }) + ); + } + // migrate annotations if (options.targets.some((target: OpenTsdbQuery) => target.fromAnnotations)) { const streams: Array> = []; @@ -259,6 +280,15 @@ export default class OpenTsDatasource extends DataSourceApi { @@ -397,7 +427,11 @@ export default class OpenTsDatasource extends DataSourceApi { diff --git a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/InlineSearchField.tsx b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/InlineSearchField.tsx index d4b0678069f..3f139f8c898 100644 --- a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/InlineSearchField.tsx +++ b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/InlineSearchField.tsx @@ -5,7 +5,7 @@ import { InlineFieldRow, InlineField } from '@grafana/ui'; interface Props { label: string; tooltip?: string; - children: React.ReactElement; + children: React.ReactElement>; } const SearchField = ({ label, tooltip, children }: Props) => { return ( diff --git a/public/app/plugins/panel/canvas/editor/layer/TreeNavigationEditor.tsx b/public/app/plugins/panel/canvas/editor/layer/TreeNavigationEditor.tsx index 0ac11d42758..1117a684ac1 100644 --- a/public/app/plugins/panel/canvas/editor/layer/TreeNavigationEditor.tsx +++ b/public/app/plugins/panel/canvas/editor/layer/TreeNavigationEditor.tsx @@ -1,6 +1,6 @@ import { css } from '@emotion/css'; import { Global } from '@emotion/react'; -import Tree, { TreeNodeProps } from 'rc-tree'; +import Tree, { TreeNodeProps } from '@rc-component/tree'; import { Key, useEffect, useMemo, useState } from 'react'; import { GrafanaTheme2, StandardEditorProps } from '@grafana/data'; diff --git a/public/app/plugins/panel/radialbar/EffectsEditor.tsx b/public/app/plugins/panel/radialbar/EffectsEditor.tsx index 91805596a79..0794207f35a 100644 --- a/public/app/plugins/panel/radialbar/EffectsEditor.tsx +++ b/public/app/plugins/panel/radialbar/EffectsEditor.tsx @@ -1,6 +1,6 @@ import { StandardEditorProps } from '@grafana/data'; import { t } from '@grafana/i18n'; -import { Stack, Switch, Label } from '@grafana/ui'; +import { Stack, Switch, Label, Tooltip } from '@grafana/ui'; import { GaugePanelEffects } from './panelcfg.gen'; @@ -36,15 +36,18 @@ export function EffectsEditor(props: StandardEditorProps) { /> - - props.onChange({ ...props.value, spotlight: e.currentTarget.checked })} - /> - - + + + props.onChange({ ...props.value, spotlight: e.currentTarget.checked })} + /> + + + + ); } diff --git a/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx b/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx index 24f6be1672e..dd51ccdac51 100644 --- a/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx +++ b/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx @@ -19,7 +19,7 @@ import { XAxisInteractionAreaPlugin, usePanelContext, } from '@grafana/ui'; -import { TimeRange2, TooltipHoverMode } from '@grafana/ui/internal'; +import { FILTER_OUT_OPERATOR, TimeRange2, TooltipHoverMode } from '@grafana/ui/internal'; import { TimeSeries } from 'app/core/components/TimeSeries/TimeSeries'; import { config } from 'app/core/config'; @@ -31,7 +31,7 @@ import { OutsideRangePlugin } from './plugins/OutsideRangePlugin'; import { ThresholdControlsPlugin } from './plugins/ThresholdControlsPlugin'; import { getXAnnotationFrames } from './plugins/utils'; import { getPrepareTimeseriesSuggestion } from './suggestions'; -import { getTimezones, prepareGraphableFields } from './utils'; +import { getGroupedFilters, getTimezones, prepareGraphableFields } from './utils'; interface TimeSeriesPanelProps extends PanelProps {} @@ -56,6 +56,8 @@ export const TimeSeriesPanel = ({ showThresholds, eventBus, canExecuteActions, + getFiltersBasedOnGrouping, + onAddAdHocFilters, } = usePanelContext(); const { dataLinkPostProcessor } = useDataLinksContext(); @@ -175,6 +177,11 @@ export const TimeSeriesPanel = ({ dismiss(); }; + const groupingFilters = + seriesIdx !== null && config.featureToggles.perPanelFiltering && getFiltersBasedOnGrouping + ? getGroupedFilters(alignedFrame, seriesIdx, getFiltersBasedOnGrouping) + : []; + return ( // not sure it header time here works for annotations, since it's taken from nearest datapoint index onAddAdHocFilters(groupingFilters), + onFilterOutGroupedLabels: () => + onAddAdHocFilters( + groupingFilters.map((item) => ({ ...item, operator: FILTER_OUT_OPERATOR })) + ), + } + : undefined + } canExecuteActions={userCanExecuteActions} compareDiffMs={compareDiffMs} /> diff --git a/public/app/plugins/panel/timeseries/TimeSeriesTooltip.tsx b/public/app/plugins/panel/timeseries/TimeSeriesTooltip.tsx index 2663b8f1acb..feea20ab03b 100644 --- a/public/app/plugins/panel/timeseries/TimeSeriesTooltip.tsx +++ b/public/app/plugins/panel/timeseries/TimeSeriesTooltip.tsx @@ -18,6 +18,7 @@ import { getContentItems, VizTooltipItem, AdHocFilterModel, + FilterByGroupedLabelsModel, } from '@grafana/ui/internal'; import { getFieldActions } from '../status-history/utils'; @@ -50,6 +51,7 @@ export interface TimeSeriesTooltipProps { dataLinks: LinkModel[]; hideZeros?: boolean; adHocFilters?: AdHocFilterModel[]; + filterByGroupedLabels?: FilterByGroupedLabelsModel; canExecuteActions?: boolean; compareDiffMs?: number[]; } @@ -70,8 +72,10 @@ export const TimeSeriesTooltip = ({ adHocFilters, canExecuteActions, compareDiffMs, + filterByGroupedLabels, }: TimeSeriesTooltipProps) => { const pluginContext = usePluginContext(); + const xField = series.fields[0]; let xVal = xField.values[dataIdxs[0]!]; @@ -107,7 +111,13 @@ export const TimeSeriesTooltip = ({ : []; footer = ( - + ); } } diff --git a/public/app/plugins/panel/timeseries/utils.test.ts b/public/app/plugins/panel/timeseries/utils.test.ts index a48b861781b..22aeb901f2a 100644 --- a/public/app/plugins/panel/timeseries/utils.test.ts +++ b/public/app/plugins/panel/timeseries/utils.test.ts @@ -1,7 +1,9 @@ import { createTheme, FieldType, createDataFrame, toDataFrame } from '@grafana/data'; import { LineInterpolation } from '@grafana/ui'; -import { prepareGraphableFields } from './utils'; +import { AdHocFilterItem } from '../../../../../packages/grafana-ui/src/components/Table/TableNG/types'; + +import { getGroupedFilters, prepareGraphableFields } from './utils'; describe('prepare timeseries graph', () => { it('errors with no time fields', () => { @@ -178,4 +180,83 @@ describe('prepare timeseries graph', () => { expect(frames![0].fields[1].config.custom.lineInterpolation).toEqual(LineInterpolation.StepAfter); }); }); + + describe('getGroupedFilters', () => { + it('returns empty array if no field', () => { + const df = createDataFrame({ + fields: [{ name: 'time', type: FieldType.time, values: [1, 2, 3] }], + }); + + expect(getGroupedFilters(df, 1, jest.fn())).toEqual([]); + }); + + it('returns empty array if no labels', () => { + const df = createDataFrame({ + fields: [ + { name: 'time', type: FieldType.time, values: [1, 2, 3] }, + { + name: 'value', + type: FieldType.number, + values: [1, 2, 3], + }, + ], + }); + + expect(getGroupedFilters(df, 1, jest.fn())).toEqual([]); + }); + + it('returns empty array if field not filterable', () => { + const df = createDataFrame({ + fields: [ + { name: 'time', type: FieldType.time, values: [1, 2, 3] }, + { + name: 'value', + type: FieldType.number, + values: [1, 2, 3], + labels: { + test: 'value', + label: 'value2', + }, + }, + ], + }); + + expect(getGroupedFilters(df, 1, jest.fn())).toEqual([]); + }); + + it('returns grouped filters', () => { + const df = createDataFrame({ + fields: [ + { name: 'time', type: FieldType.time, values: [1, 2, 3] }, + { + name: 'value', + type: FieldType.number, + values: [1, 2, 3], + labels: { + test: 'value', + label: 'value2', + }, + config: { + filterable: true, + }, + }, + ], + }); + + const filtersGroupingFn = (filters: AdHocFilterItem[]) => filters; + + expect(getGroupedFilters(df, 1, filtersGroupingFn)).toEqual([ + { + key: 'test', + operator: '=', + value: 'value', + }, + { + key: 'label', + operator: '=', + value: 'value2', + }, + ]); + }); + }); }); diff --git a/public/app/plugins/panel/timeseries/utils.ts b/public/app/plugins/panel/timeseries/utils.ts index ac2f7e425ae..7fdb5d53a22 100644 --- a/public/app/plugins/panel/timeseries/utils.ts +++ b/public/app/plugins/panel/timeseries/utils.ts @@ -12,7 +12,8 @@ import { } from '@grafana/data'; import { convertFieldType } from '@grafana/data/internal'; import { GraphFieldConfig, LineInterpolation, TooltipDisplayMode, VizTooltipOptions } from '@grafana/schema'; -import { buildScaleKey } from '@grafana/ui/internal'; +import { AdHocFilterItem } from '@grafana/ui'; +import { buildScaleKey, FILTER_FOR_OPERATOR } from '@grafana/ui/internal'; import { HeatmapTooltip } from '../heatmap/panelcfg.gen'; @@ -329,3 +330,28 @@ export function getTimezones(timezones: string[] | undefined, defaultTimezone: s export const isTooltipScrollable = (tooltipOptions: VizTooltipOptions | HeatmapTooltip) => { return tooltipOptions.mode === TooltipDisplayMode.Multi && tooltipOptions.maxHeight != null; }; + +export function getGroupedFilters( + frame: DataFrame, + seriesIdx: number, + getFiltersBasedOnGrouping: (filters: AdHocFilterItem[]) => AdHocFilterItem[] +) { + const groupingFilters: AdHocFilterItem[] = []; + const xField = frame.fields[seriesIdx]; + + if (xField && xField.labels && xField.config.filterable) { + const seriesFilters: AdHocFilterItem[] = []; + + Object.entries(xField.labels).forEach(([key, value]) => { + seriesFilters.push({ + key, + operator: FILTER_FOR_OPERATOR, + value, + }); + }); + + groupingFilters.push(...getFiltersBasedOnGrouping(seriesFilters)); + } + + return groupingFilters; +} diff --git a/public/app/types/dashboard.ts b/public/app/types/dashboard.ts index e9e7cce5ea0..d0f1edfbba7 100644 --- a/public/app/types/dashboard.ts +++ b/public/app/types/dashboard.ts @@ -85,6 +85,13 @@ export interface DashboardMeta { // This is a property added specifically for edge cases where dashboards should be reloaded on scopes, time range or variables changes // This property is not persisted in the DB but its existence is controlled by the API reloadOnParamsChange?: boolean; + + // Conversion status from the API response, indicating if the dashboard was converted from another version + conversionStatus?: { + storedVersion?: string; + failed: boolean; + error?: string; + }; } export interface AnnotationActions { diff --git a/public/locales/cs-CZ/grafana.json b/public/locales/cs-CZ/grafana.json index eb0c6eba3a0..6ce52307b99 100644 --- a/public/locales/cs-CZ/grafana.json +++ b/public/locales/cs-CZ/grafana.json @@ -2350,11 +2350,8 @@ "label-tenant-sources": "Zdroje tenanta" }, "rule-details-matching-instances": { - "showing-count": "Zobrazuje se {{visibleItems}} z {{totalItems}} instancí", - "button-show-all_one": "Zobrazit všechny instance výstrah: {{totalItems}}", - "button-show-all_few": "Zobrazit všechny instance výstrah: {{totalItems}}", - "button-show-all_many": "Zobrazit všechny instance výstrah: {{totalItems}}", - "button-show-all_other": "Zobrazit všechny instance výstrah: {{totalItems}}" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4851,7 +4848,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Hodnoty oddělené čárkou" }, @@ -5125,10 +5124,7 @@ "copy-or-duplicate": "Kopírovat nebo duplikovat", "delete": "Odstranit", "duplicate": "Duplikovat", - "group-layout": "Rozvržení skupiny", - "group-layout-disabled": "Na této úrovni neexistují žádné skupiny", - "panel-layout": "Rozvržení panelu", - "panel-layout-disabled": "Vyberte řádek nebo záložku pro změnu možností rozvržení panelu" + "layout": "Rozvržení" }, "continue": "", "ungroup-nested-text": "", @@ -5871,14 +5867,26 @@ }, "annotation-settings-edit": { "back-to-list": "Zpět na seznam", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Odstranit", "description-color-annotation-event-markers": "Barva, která bude použita pro značky vysvětlivek události", "description-enabled-annotation-query-issued-every-dashboard": "Je-li povoleno, při každém obnovení nástěnky bude aktivován dotaz na vysvětlivky", - "description-hidden": "Dotazy na vysvětlivky lze zapnout nebo vypnout v horní části nástěnky. Pokud je tato možnost zaškrtnuta, bude tento přepínač skrytý.", + "label-annotation-controls-display": "", "label-color": "Barva", "label-data-source": "Zdroj dat", "label-enabled": "Povoleno", - "label-hidden": "Skryté", "label-name": "Název", "label-show-in": "Zobrazit v", "placeholder-choose-panels": "Vybrat panely", @@ -5934,6 +5942,7 @@ "label-open-link-in-new-tab": "Otevřít odkaz v nové záložce", "label-options": "Možnosti", "label-show-as-dropdown": "Zobrazit jako rozevírací seznam", + "label-show-in-controls-menu": "", "label-title": "Název", "label-tooltip": "Popisek", "label-type": "Typ", @@ -6499,6 +6508,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Formulář editoru proměnné", "back-to-list": "Zpět na seznam", @@ -6607,7 +6635,7 @@ "delete-button": "Odstranit", "title": "Odstranit" }, - "delete-modal-restore-dashboards-text": "Tato akce označí nástěnku k odstranění za 30 dnů. Správce organizace ji může obnovit kdykoli před uplynutím 30 dnů.", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Chcete odstranit tuto nástěnku?", "general": { "auto-refresh-description": "Definujte intervaly automatického obnovení, které by měly být k dispozici v seznamu automatického obnovení. Použijte formát „5 s“ pro sekundy, „1 m“ pro minuty, „1 h“ pro hodiny a „1 d“ pro dny (např.: „5 s, 10 s, 30 s, 1 m, 5 m, 15 m, 30 m, 1 h, 2 h, 1 d“).", @@ -6813,8 +6841,8 @@ "test": "Test" }, "cloud-info-box": { - "body-alert": "Nebo si to zjednodušte a získejte {{mainDS}} (a {{extraDS}}) – plně spravované, škálovatelné a hostované zdroje dat od Grafana Labs s <6>celoživotním bezplatným plánem Grafana Cloud.", - "title-alert": "Nakonfigurujte zdroje dat {{mainDS}} níže" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Odstranit nástěnku", @@ -7353,6 +7381,14 @@ "title-failed-sample-query": "Vzorek protokolů pro tento dotaz se nepodařilo načíst", "tooltip": "Zobrazit řádky protokolu, které přispěly k vizualizovaným metrikám" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Žádná pole" }, @@ -8285,6 +8321,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9285,6 +9327,8 @@ "actions-confirmation-label": "Potvrzovací zpráva", "actions-confirmation-message": "Napište popisnou výzvu k potvrzení nebo zrušení akce.", "footer-add-annotation": "Přidat vysvětlivku", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Klikněte pro {{actionTitle}}", "footer-click-to-navigate": "Klikněte pro otevření {{linkTitle}}", "footer-filter-for-value": "Filtrovat podle hodnoty „{{value}}“", @@ -12465,7 +12509,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/de-DE/grafana.json b/public/locales/de-DE/grafana.json index 4f5a351736c..5619e7c8ab5 100644 --- a/public/locales/de-DE/grafana.json +++ b/public/locales/de-DE/grafana.json @@ -2334,9 +2334,8 @@ "label-tenant-sources": "Tenant-Quellen" }, "rule-details-matching-instances": { - "showing-count": "Angezeigt werden {{visibleItems}} von {{totalItems}} Instanzen", - "button-show-all_one": "Alle {{totalItems}} Warninstanzen anzeigen", - "button-show-all_other": "Alle {{totalItems}} Warninstanzen anzeigen" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4811,7 +4810,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Werte werden durch Komma getrennt" }, @@ -5085,10 +5086,7 @@ "copy-or-duplicate": "Kopieren oder duplizieren", "delete": "Löschen", "duplicate": "Duplikat", - "group-layout": "Gruppenlayout", - "group-layout-disabled": "Auf dieser Ebene sind keine Gruppen vorhanden", - "panel-layout": "Panel-Layout", - "panel-layout-disabled": "Wählen Sie eine Zeile oder Registerkarte, um die Panel-Layout-Optionen zu ändern" + "layout": "Layout" }, "continue": "", "ungroup-nested-text": "", @@ -5827,14 +5825,26 @@ }, "annotation-settings-edit": { "back-to-list": "Zurück zur Liste", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Löschen", "description-color-annotation-event-markers": "Farbe, die für Ereignismarkierungen von Anmerkungen verwendet werden soll", "description-enabled-annotation-query-issued-every-dashboard": "Wenn dies aktiviert ist, wird bei jeder Aktualisierung des Dashboards eine Anmerkungsabfrage ausgegeben", - "description-hidden": "Anmerkungsabfragen können im oberen Bereich des Dashboards ein- oder ausgeschaltet werden. Wenn diese Option aktiviert ist, wird dieser Schalter ausgeblendet.", + "label-annotation-controls-display": "", "label-color": "Farbe", "label-data-source": "Datenquelle", "label-enabled": "Aktiviert", - "label-hidden": "Ausgeblendet", "label-name": "Name", "label-show-in": "Anzeigen in", "placeholder-choose-panels": "Panels auswählen", @@ -5890,6 +5900,7 @@ "label-open-link-in-new-tab": "Link in neuem Tab öffnen", "label-options": "Optionen", "label-show-as-dropdown": "Als Dropdown anzeigen", + "label-show-in-controls-menu": "", "label-title": "Titel", "label-tooltip": "Tooltip", "label-type": "Typ", @@ -6451,6 +6462,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Variablen-Editor-Formular", "back-to-list": "Zurück zur Liste", @@ -6559,7 +6589,7 @@ "delete-button": "Löschen", "title": "Löschen" }, - "delete-modal-restore-dashboards-text": "Diese Aktion markiert das Dashboard zur Löschung in 30 Tagen. Der Administrator Ihrer Organisation kann es jederzeit vor Ablauf der 30 Tage wiederherstellen. ", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Möchten Sie dieses Dashboard löschen?", "general": { "auto-refresh-description": "Definieren Sie die Intervalle für die automatischen Aktualisierungen, die in der Liste für die automatische Aktualisierung verfügbar sein sollen. Verwenden Sie das Format „5s“ für Sekunden, „1m“ für Minuten, „1h“ für Stunden und „1d“ für Tage (z. B.: „5s,10s,30s,1m,5m,15m,30m,1h,2h,1d“).", @@ -6765,8 +6795,8 @@ "test": "Test" }, "cloud-info-box": { - "body-alert": "Oder sparen Sie sich den Aufwand und erhalten Sie {{mainDS}} (und {{extraDS}}) als vollständig verwaltete, skalierbare und gehostete Datenquellen von Grafana Labs – mit dem <6>jederzeit kostenlosen Grafana-Cloud-Plan.", - "title-alert": "Konfigurieren Sie unten Ihre {{mainDS}} Datenquelle" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Dashboard löschen", @@ -7305,6 +7335,14 @@ "title-failed-sample-query": "Das Logs-Sample für diese Abfrage konnte nicht geladen werden", "tooltip": "Zeigen Sie Log-Zeilen an, die an visualisierten Metriken beteiligt waren" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Keine Felder" }, @@ -8213,6 +8251,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9213,6 +9257,8 @@ "actions-confirmation-label": "Bestätigungsnachricht", "actions-confirmation-message": "Geben Sie eine beschreibende Eingabeaufforderung an, um die Aktion zu bestätigen oder abzubrechen.", "footer-add-annotation": "Anmerkung hinzufügen", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Klicken, um zu {{actionTitle}}", "footer-click-to-navigate": "Zum Öffnen von {{linkTitle}} klicken", "footer-filter-for-value": "Filtern nach „{{value}}“", @@ -12359,7 +12405,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index ac054cb8f7a..d2280c05925 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -2334,9 +2334,8 @@ "label-tenant-sources": "Tenant sources" }, "rule-details-matching-instances": { - "button-show-all_one": "Show all {{totalItems}} alert instances", - "button-show-all_other": "Show all {{totalItems}} alert instances", - "showing-count": "Showing {{visibleItems}} out of {{totalItems}} instances" + "button-show-all": "Show all {{totalItemsCount}} alert instances", + "showing-count": "Showing {{visibleItemsCount}} out of {{totalItemsCount}} instances" }, "rule-editor": { "get-content": { @@ -4782,6 +4781,8 @@ "remove": "Remove {{typeName}}", "row-title": "Change row title", "switch-layout": "Switch layout", + "switch-layout-row": "Switch layout", + "switch-layout-tab": "Switch layout", "tab-title": "Change tab title" }, "edit-pane": { @@ -4811,7 +4812,9 @@ }, "variable": { "custom-options": { - "close": "Close", + "apply": "Apply", + "change-value": "Change variable value", + "discard": "Discard", "modal-title": "Custom Variable", "values": "Values separated by comma" }, @@ -5824,14 +5827,26 @@ }, "annotation-settings-edit": { "back-to-list": "Back to list", + "control-display-options": { + "above-dashboard": { + "label": "Above dashboard" + }, + "controls-menu": { + "description": "Can be accessed when the controls menu is open", + "label": "Controls menu" + }, + "hidden": { + "description": "Hides the toggle for turning this annotation on or off", + "label": "Hidden" + } + }, "delete": "Delete", "description-color-annotation-event-markers": "Color to use for the annotation event markers", "description-enabled-annotation-query-issued-every-dashboard": "When enabled the annotation query is issued every dashboard refresh", - "description-hidden": "Annotation queries can be toggled on or off at the top of the dashboard. With this option checked this toggle will be hidden.", + "label-annotation-controls-display": "Show annotation controls in", "label-color": "Color", "label-data-source": "Data source", "label-enabled": "Enabled", - "label-hidden": "Hidden", "label-name": "Name", "label-show-in": "Show in", "placeholder-choose-panels": "Choose panels", @@ -5874,6 +5889,17 @@ "label-value": "Value", "placeholder-your-metric-prefix": "Your metric prefix" }, + "conversion-warning-banner": { + "detail-conditional": "Show/hide rules will not work", + "detail-grids": "All auto-grids will be shown as custom grids", + "detail-tabs": "All tabs and rows will appear as classic rows", + "details": "During this period, please be aware of the following:", + "message": "The Dynamic Dashboard feature is temporarily disabled", + "read-less": "Read less", + "read-more": "Read more", + "recommendation": "Once the feature is enabled again, your dashboards will render normally in their Dynamic Dashboard format. Because of this, we strongly recommend not making changes to these dashboards until the feature is turned back on, as edits made in classic mode may lead to unexpected results. Alternatively, you can save a copy of the dashboard using the \"Save as copy\" option, in the save dashboard menu.", + "save-warning": "Any dashboard created as or converted to a Dynamic Dashboard will open as a classic dashboard. Saving the dashboard could lead to losing already set up Dynamic Dashboard features." + }, "custom-variable-form": { "custom-options": "Custom options", "name-values-separated-comma": "Values separated by comma", @@ -5887,6 +5913,7 @@ "label-open-link-in-new-tab": "Open link in new tab", "label-options": "Options", "label-show-as-dropdown": "Show as dropdown", + "label-show-in-controls-menu": "Show in controls menu", "label-title": "Title", "label-tooltip": "Tooltip", "label-type": "Type", @@ -6448,6 +6475,25 @@ "variable-controls": { "add-variable": "Add variable" }, + "variable-display-select": { + "label": "Display", + "options": { + "above-dashboard": { + "label": "Above dashboard" + }, + "controls-menu": { + "description": "Visible when the controls menu is open", + "label": "Controls menu" + }, + "hidden": { + "label": "Hidden" + }, + "hidden-label": { + "description": "Above the dashboard, but without showing the name of variable", + "label": "Above dashboard, label hidden" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Variable editor form", "back-to-list": "Back to list", @@ -6762,8 +6808,8 @@ "test": "Test" }, "cloud-info-box": { - "body-alert": "Or skip the effort and get {{mainDS}} (and {{extraDS}}) as fully-managed, scalable, and hosted data sources from Grafana Labs with the <6>free-forever Grafana Cloud plan.", - "title-alert": "Configure your {{mainDS}} data source below" + "body-alert": "Or skip the effort and get {{dsName}} as fully-managed, scalable, and hosted data source from Grafana Labs with the <4>free-forever Grafana Cloud plan.", + "title-alert": "Configure your {{dsName}} data source below" }, "dashboards-table": { "aria-label-delete-dashboard": "Delete dashboard", @@ -7302,6 +7348,14 @@ "title-failed-sample-query": "Failed to load logs sample for this query", "tooltip": "Show log lines that contributed to visualized metrics" }, + "logs-table": { + "action-buttons": { + "copy-link": "Copy link to log line", + "copy-to-clipboard": "Copy to Clipboard", + "inspect-value": "Inspect value", + "view-log-line": "View log line" + } + }, "logs-table-empty-fields": { "no-fields": "No fields" }, @@ -8210,6 +8264,12 @@ "nextNYears_other": "Next {{count}} years" } }, + "field": { + "fieldColor": { + "accessibleGroup": "Accessible", + "otherGroup": "Others" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9210,6 +9270,8 @@ "actions-confirmation-label": "Confirmation message", "actions-confirmation-message": "Provide a descriptive prompt to confirm or cancel the action.", "footer-add-annotation": "Add annotation", + "footer-apply-series-as-filter": "Apply as filter", + "footer-apply-series-as-inverse-filter": "Apply as inverse filter", "footer-click-to-action": "Click to {{actionTitle}}", "footer-click-to-navigate": "Click to open {{linkTitle}}", "footer-filter-for-value": "Filter for '{{value}}'", @@ -12356,7 +12418,8 @@ "bar-glow": "Bar glow", "center-glow": "Center glow", "rounded-bars": "Rounded bars", - "spotlight": "Spotlight" + "spotlight": "Spotlight", + "spotlight-tooltip": "Only visible in dark themes" }, "gradient": "Gradient", "gradient-auto": "Auto", diff --git a/public/locales/es-ES/grafana.json b/public/locales/es-ES/grafana.json index bc1ccea444c..dc07b47b5c6 100644 --- a/public/locales/es-ES/grafana.json +++ b/public/locales/es-ES/grafana.json @@ -2334,9 +2334,8 @@ "label-tenant-sources": "Fuentes de inquilinos" }, "rule-details-matching-instances": { - "showing-count": "Mostrando {{visibleItems}} de {{totalItems}} instancias", - "button-show-all_one": "Mostrar {{totalItems}} instancia de alerta", - "button-show-all_other": "Mostrar las {{totalItems}} instancias de alerta" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4811,7 +4810,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Valores separados por coma" }, @@ -5085,10 +5086,7 @@ "copy-or-duplicate": "Copiar o duplicar", "delete": "Eliminar", "duplicate": "Duplicar", - "group-layout": "Diseño del grupo", - "group-layout-disabled": "No existen grupos en este nivel", - "panel-layout": "Diseño del panel", - "panel-layout-disabled": "Selecciona una fila o pestaña para cambiar las opciones de diseño del panel" + "layout": "Diseño" }, "continue": "", "ungroup-nested-text": "", @@ -5827,14 +5825,26 @@ }, "annotation-settings-edit": { "back-to-list": "Regresar a la lista", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Eliminar", "description-color-annotation-event-markers": "Color que se utilizará para los marcadores de eventos de anotación", "description-enabled-annotation-query-issued-every-dashboard": "Cuando está habilitada, la consulta de anotación se emite cada vez que se actualiza el dashboard", - "description-hidden": "Las consultas de anotación se pueden activar o desactivar en la parte superior del dashboard. Con esta opción marcada, este conmutador se ocultará.", + "label-annotation-controls-display": "", "label-color": "Color", "label-data-source": "Fuente de datos", "label-enabled": "Activado", - "label-hidden": "Oculto", "label-name": "Nombre", "label-show-in": "Mostrar en", "placeholder-choose-panels": "Elegir paneles", @@ -5890,6 +5900,7 @@ "label-open-link-in-new-tab": "Abrir enlace en pestaña nueva", "label-options": "Opciones", "label-show-as-dropdown": "Mostrar como desplegable", + "label-show-in-controls-menu": "", "label-title": "Título", "label-tooltip": "Descripción emergente", "label-type": "Tipo", @@ -6451,6 +6462,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Formulario del editor de variables", "back-to-list": "Regresar a la lista", @@ -6559,7 +6589,7 @@ "delete-button": "Eliminar", "title": "Eliminar" }, - "delete-modal-restore-dashboards-text": "Esta acción marcará el panel de control para su eliminación en 30 días. El administrador de tu organización puede restaurarlo en cualquier momento antes de que transcurran los 30 días.", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "¿Quieres eliminar este panel de control?", "general": { "auto-refresh-description": "Define los intervalos de actualización automática que deben estar disponibles en la lista de actualización automática. Utiliza el formato «5 s» para los segundos, «1 m» para los minutos, «1 h» para las horas y «1 d» para los días (por ejemplo: «5 s, 10 s, 30 s, 1 m, 5 m, 15 m, 30 m, 1 h, 2 h, 1 d»).", @@ -6765,8 +6795,8 @@ "test": "Prueba" }, "cloud-info-box": { - "body-alert": "O ahórrate el esfuerzo y consigue {{mainDS}} (y{{extraDS}}) como fuentes de datos totalmente gestionadas, escalables y alojadas de Grafana Labs con el <6>plan Grafana Cloud gratuito para siempre.", - "title-alert": "Configura tu fuente de datos {{mainDS}} a continuación" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Eliminar panel de control", @@ -7305,6 +7335,14 @@ "title-failed-sample-query": "Error al cargar la muestra de logs para esta consulta", "tooltip": "Mostrar líneas de log que contribuyeron a las métricas visualizadas" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Ningún campo" }, @@ -8213,6 +8251,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9213,6 +9257,8 @@ "actions-confirmation-label": "Mensaje de confirmación", "actions-confirmation-message": "Proporciona un mensaje descriptivo para confirmar o cancelar la acción.", "footer-add-annotation": "Añadir anotación", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Haz clic para {{actionTitle}}", "footer-click-to-navigate": "Haz clic para abrir {{linkTitle}}", "footer-filter-for-value": "Filtrar por «{{value}}»", @@ -12359,7 +12405,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/fr-FR/grafana.json b/public/locales/fr-FR/grafana.json index 50f4e61edd0..4adc55064e4 100644 --- a/public/locales/fr-FR/grafana.json +++ b/public/locales/fr-FR/grafana.json @@ -2334,9 +2334,8 @@ "label-tenant-sources": "Sources du locataire" }, "rule-details-matching-instances": { - "showing-count": "Affichage de {{visibleItems}} sur {{totalItems}} instances", - "button-show-all_one": "Afficher toutes les {{totalItems}} instances d’alerte", - "button-show-all_other": "Afficher toutes les {{totalItems}} instances d’alerte" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4811,7 +4810,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Valeurs séparées par une virgule" }, @@ -5085,10 +5086,7 @@ "copy-or-duplicate": "Copier ou dupliquer", "delete": "Supprimer", "duplicate": "Dupliquer", - "group-layout": "Disposition du groupe", - "group-layout-disabled": "Aucun groupe n’existe à ce niveau", - "panel-layout": "Disposition des panneaux", - "panel-layout-disabled": "Sélectionnez une ligne ou un onglet pour modifier les options de disposition du panneau" + "layout": "Mise en page" }, "continue": "", "ungroup-nested-text": "", @@ -5827,14 +5825,26 @@ }, "annotation-settings-edit": { "back-to-list": "Retour à la liste", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Supprimer", "description-color-annotation-event-markers": "Couleur à utiliser pour les marqueurs d’événement d’annotation", "description-enabled-annotation-query-issued-every-dashboard": "Lorsque cette option est activée, la requête d’annotation est émise à chaque actualisation du tableau de bord", - "description-hidden": "Les requêtes d’annotation peuvent être activées ou désactivées en haut du tableau de bord. Lorsque cette option est cochée, ce bouton sera masqué.", + "label-annotation-controls-display": "", "label-color": "Couleur", "label-data-source": "Source de données", "label-enabled": "Activé", - "label-hidden": "Masqué", "label-name": "Nom", "label-show-in": "Afficher dans", "placeholder-choose-panels": "Choisir des panneaux", @@ -5890,6 +5900,7 @@ "label-open-link-in-new-tab": "Ouvrir le lien dans un nouvel onglet", "label-options": "Options", "label-show-as-dropdown": "Afficher sous forme de menu déroulant", + "label-show-in-controls-menu": "", "label-title": "Titre", "label-tooltip": "Infobulle", "label-type": "Type", @@ -6451,6 +6462,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Formulaire de l’éditeur de variables", "back-to-list": "Retour à la liste", @@ -6559,7 +6589,7 @@ "delete-button": "Supprimer", "title": "Supprimer" }, - "delete-modal-restore-dashboards-text": "Cette action marquera le tableau de bord pour suppression dans 30 jours. L'administrateur de votre organisation peut le restaurer à tout moment avant l'expiration des 30 jours.", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Voulez-vous vraiment supprimer ce tableau de bord ?", "general": { "auto-refresh-description": "Définissez les intervalles d'actualisation automatique qui doivent être disponibles dans la liste d'actualisation automatique. Utilisez le format « 5s » pour les secondes, « 1m » pour les minutes, « 1h » pour les heures et « 1d » pour les jours (par exemple : « 5s,10s,30s,1m,5m,15m,30m,1h,2h,1d »).", @@ -6765,8 +6795,8 @@ "test": "Test" }, "cloud-info-box": { - "body-alert": "Ou simplifiez-vous la tâche et obtenez {{mainDS}} (et {{extraDS}}) sous forme de sources de données entièrement gérées, évolutives et hébergées par Grafana Labs avec le <6>plan Grafana Cloud gratuit à vie.", - "title-alert": "Configurer la source de données {{mainDS}} ci-dessous" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Supprimer le tableau de bord", @@ -7305,6 +7335,14 @@ "title-failed-sample-query": "Échec du chargement de l’exemple de journaux pour cette requête", "tooltip": "Afficher les lignes de journal qui ont contribué aux métriques visualisées" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Aucun champ" }, @@ -8213,6 +8251,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9213,6 +9257,8 @@ "actions-confirmation-label": "Message de confirmation", "actions-confirmation-message": "Fournissez une invite descriptive pour confirmer ou annuler l'action.", "footer-add-annotation": "Ajouter une annotation", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Cliquez pour {{actionTitle}}", "footer-click-to-navigate": "Cliquez pour ouvrir {{linkTitle}}", "footer-filter-for-value": "Filtrer par « {{value}} »", @@ -12359,7 +12405,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/hu-HU/grafana.json b/public/locales/hu-HU/grafana.json index 47ccb2d223e..409c3249166 100644 --- a/public/locales/hu-HU/grafana.json +++ b/public/locales/hu-HU/grafana.json @@ -2334,9 +2334,8 @@ "label-tenant-sources": "Bérlői források" }, "rule-details-matching-instances": { - "showing-count": "{{totalItems}}/{{visibleItems}} példány megjelenítése", - "button-show-all_one": "Mind a(z) {{totalItems}} riasztáspéldány megjelenítése", - "button-show-all_other": "Mind a(z) {{totalItems}} riasztáspéldány megjelenítése" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4811,7 +4810,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Értékek vesszővel elválasztva" }, @@ -5085,10 +5086,7 @@ "copy-or-duplicate": "Másolás vagy duplikálás", "delete": "Törlés", "duplicate": "Duplikálás", - "group-layout": "Csoport elrendezése", - "group-layout-disabled": "Ezen a szinten nincsenek csoportok", - "panel-layout": "Panel elrendezése", - "panel-layout-disabled": "Jelöljön ki egy sort vagy lapot a panel elrendezési beállításainak módosításához" + "layout": "Elrendezés" }, "continue": "", "ungroup-nested-text": "", @@ -5827,14 +5825,26 @@ }, "annotation-settings-edit": { "back-to-list": "Vissza a listához", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Törlés", "description-color-annotation-event-markers": "A jegyzetesemény-jelölőkhöz használandó szín", "description-enabled-annotation-query-issued-every-dashboard": "Ha engedélyezve van, a jegyzetlekérdezés az irányítópult minden frissítésekor megjelenik", - "description-hidden": "A jegyzetlekérdezések be- és kikapcsolhatók az irányítópult tetején. Ha ez a lehetőség be van jelölve, ez a kapcsoló el lesz rejtve.", + "label-annotation-controls-display": "", "label-color": "Szín", "label-data-source": "Adatforrás", "label-enabled": "Engedélyezve", - "label-hidden": "Rejtett", "label-name": "Név", "label-show-in": "Megjelenítés itt:", "placeholder-choose-panels": "Válassza ki a paneleket", @@ -5890,6 +5900,7 @@ "label-open-link-in-new-tab": "Hivatkozás megnyitása új lapon", "label-options": "Beállítások", "label-show-as-dropdown": "Megjelenítés legördülő menüként", + "label-show-in-controls-menu": "", "label-title": "Cím", "label-tooltip": "Elemleírás", "label-type": "Típus", @@ -6451,6 +6462,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Változószerkesztő űrlap", "back-to-list": "Vissza a listához", @@ -6559,7 +6589,7 @@ "delete-button": "Törlés", "title": "Törlés" }, - "delete-modal-restore-dashboards-text": "Ez a művelet 30 napon belüli törlésre jelöli meg az irányítópultot. A szervezeti rendszergazda a 30 nap lejárta előtt bármikor visszaállíthatja.", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Biztosan törli ezt az irányítópultot?", "general": { "auto-refresh-description": "Határozza meg az automatikus frissítési intervallumokat, amelyeknek elérhetőnek kell lenniük az automatikus frissítési listában. Használja az „5s” formátumot a másodpercekhez, az „1m” formátumot a percekhez, az „1h” formátumot az órákhoz és az „1d” formátumot a napokhoz (pl.: „5s ,10s ,30s ,1m,5m,15m,30m,1h,2h,1d”).", @@ -6765,8 +6795,8 @@ "test": "Teszt" }, "cloud-info-box": { - "body-alert": "Vagy hagyja ki a próbálkozást, és szerezze be a(z) {{mainDS}} adatforrást (és {{extraDS}}) a Grafana Labs teljes körűen felügyelt, skálázható és hosztolt adatforrásait az <6>örökre ingyenes Grafana Cloud-előfizetéssel.", - "title-alert": "Konfigurálja {{mainDS}} adatforrását alább" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Irányítópult törlése", @@ -7305,6 +7335,14 @@ "title-failed-sample-query": "A lekérdezés naplómintájának betöltése nem sikerült", "tooltip": "A vizualizált metrikákhoz hozzájáruló naplósorok megjelenítése" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Nincsenek mezők" }, @@ -8213,6 +8251,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9213,6 +9257,8 @@ "actions-confirmation-label": "Megerősítési üzenet", "actions-confirmation-message": "Adjon meg egy leíró kérdést a művelet megerősítéséhez vagy visszavonásához.", "footer-add-annotation": "Jegyzet hozzáadása", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Kattintson ehhez: {{actionTitle}}", "footer-click-to-navigate": "Kattintson a következő megnyitásához: {{linkTitle}}", "footer-filter-for-value": "Szűrés „{{value}}” szerint", @@ -12359,7 +12405,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/id-ID/grafana.json b/public/locales/id-ID/grafana.json index 516ecb7f2a0..75f6c32dcba 100644 --- a/public/locales/id-ID/grafana.json +++ b/public/locales/id-ID/grafana.json @@ -2326,8 +2326,8 @@ "label-tenant-sources": "Sumber tenant" }, "rule-details-matching-instances": { - "showing-count": "Menampilkan {{visibleItems}} dari {{totalItems}} instans", - "button-show-all_other": "Tampilkan semua {{totalItems}} instans peringatan" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4791,7 +4791,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Nilai dipisahkan dengan koma" }, @@ -5065,10 +5067,7 @@ "copy-or-duplicate": "Salin atau Duplikasikan", "delete": "Hapus", "duplicate": "Duplikasikan", - "group-layout": "Tata letak grup", - "group-layout-disabled": "Tidak ada grup di level ini", - "panel-layout": "Tata letak panel", - "panel-layout-disabled": "Pilih baris atau tab untuk mengubah opsi tata letak panel" + "layout": "Tata Letak" }, "continue": "", "ungroup-nested-text": "", @@ -5805,14 +5804,26 @@ }, "annotation-settings-edit": { "back-to-list": "Kembali ke daftar", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Hapus", "description-color-annotation-event-markers": "Warna yang akan digunakan untuk penanda peristiwa anotasi", "description-enabled-annotation-query-issued-every-dashboard": "Ketika diaktifkan, kueri anotasi dikeluarkan setiap muat ulang dasbor", - "description-hidden": "Kueri anotasi dapat diaktifkan atau dinonaktifkan di bagian atas dasbor. Dengan mencentang opsi ini, tombol ini akan disembunyikan.", + "label-annotation-controls-display": "", "label-color": "Warna", "label-data-source": "Sumber data", "label-enabled": "Aktif", - "label-hidden": "Tersembunyi", "label-name": "Nama", "label-show-in": "Tampilkan di", "placeholder-choose-panels": "Pilih panel", @@ -5868,6 +5879,7 @@ "label-open-link-in-new-tab": "Buka tautan di tab baru", "label-options": "Opsi", "label-show-as-dropdown": "Tampilkan sebagai dropdown", + "label-show-in-controls-menu": "", "label-title": "Judul", "label-tooltip": "Tooltip", "label-type": "Jenis", @@ -6427,6 +6439,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Formulir editor variabel", "back-to-list": "Kembali ke daftar", @@ -6535,7 +6566,7 @@ "delete-button": "Hapus", "title": "Hapus" }, - "delete-modal-restore-dashboards-text": "Tindakan ini akan menandai dasbor untuk dihapus dalam 30 hari. Administrator organisasi Anda dapat memulihkannya kapan saja sebelum 30 hari kedaluwarsa.", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Apa Anda ingin menghapus dasbor ini?", "general": { "auto-refresh-description": "Tentukan interval muat ulang otomatis yang seharusnya tersedia dalam daftar muat ulang otomatis. Gunakan format '5d' untuk detik, '1m' untuk menit, '1j' untuk jam, dan '1h' untuk hari (misalnya: '5d, 10d, 30d, 1m, 5m, 15m, 30m,1j, 2j, 1h').", @@ -6741,8 +6772,8 @@ "test": "Tes" }, "cloud-info-box": { - "body-alert": "Atau lewati proses dan dapatkan {{mainDS}} (dan {{extraDS}}) sebagai sumber data yang dikelola sepenuhnya, dapat diskalakan, dan di-host dari Grafana Labs dengan <6>paket Grafana Cloud gratis selamanya.", - "title-alert": "Konfigurasikan sumber data {{mainDS}} Anda di bawah ini" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Hapus dasbor", @@ -7281,6 +7312,14 @@ "title-failed-sample-query": "Gagal memuat sampel log untuk kueri ini", "tooltip": "Tampilkan baris log yang berkontribusi pada metrik yang divisualisasikan" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Tidak ada bidang" }, @@ -8177,6 +8216,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9177,6 +9222,8 @@ "actions-confirmation-label": "Pesan konfirmasi", "actions-confirmation-message": "Berikan petunjuk deskriptif untuk mengonfirmasi atau membatalkan tindakan.", "footer-add-annotation": "Tambahkan anotasi", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Klik untuk {{actionTitle}} ", "footer-click-to-navigate": "Klik untuk membuka {{linkTitle}}", "footer-filter-for-value": "Filter untuk '{{value}}'", @@ -12306,7 +12353,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/it-IT/grafana.json b/public/locales/it-IT/grafana.json index b5fc787b5de..aa13b629973 100644 --- a/public/locales/it-IT/grafana.json +++ b/public/locales/it-IT/grafana.json @@ -2334,9 +2334,8 @@ "label-tenant-sources": "Origini tenant" }, "rule-details-matching-instances": { - "showing-count": "Mostra {{visibleItems}} di {{totalItems}} istanze", - "button-show-all_one": "Mostra tutte le {{totalItems}} istanze di avviso", - "button-show-all_other": "Mostra tutte le {{totalItems}} istanze di avviso" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4811,7 +4810,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Valori separati da virgola" }, @@ -5085,10 +5086,7 @@ "copy-or-duplicate": "Copia o duplica", "delete": "Elimina", "duplicate": "Duplica", - "group-layout": "Layout gruppo", - "group-layout-disabled": "Non esistono gruppi a questo livello", - "panel-layout": "Layout del pannello", - "panel-layout-disabled": "Seleziona una riga o una scheda per modificare le opzioni di layout del pannello" + "layout": "Layout" }, "continue": "", "ungroup-nested-text": "", @@ -5827,14 +5825,26 @@ }, "annotation-settings-edit": { "back-to-list": "Torna all'elenco", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Elimina", "description-color-annotation-event-markers": "Colore da utilizzare per gli indicatori degli eventi di annotazione", "description-enabled-annotation-query-issued-every-dashboard": "Se abilitata, la query di annotazione viene emessa a ogni aggiornamento della dashboard", - "description-hidden": "Le query di annotazione possono essere attivate o disattivate nella parte superiore della dashboard. Se questa opzione è selezionata, il toggle verrà nascosto.", + "label-annotation-controls-display": "", "label-color": "Colore", "label-data-source": "Sorgente dati", "label-enabled": "Abilitato", - "label-hidden": "Nascosto", "label-name": "Nome", "label-show-in": "Mostra in", "placeholder-choose-panels": "Scegli i pannelli", @@ -5890,6 +5900,7 @@ "label-open-link-in-new-tab": "Apri link in un nuova scheda", "label-options": "Opzioni", "label-show-as-dropdown": "Mostra come menu a discesa", + "label-show-in-controls-menu": "", "label-title": "Titolo", "label-tooltip": "Suggerimento", "label-type": "Tipo", @@ -6451,6 +6462,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Modulo di modifica delle variabili", "back-to-list": "Torna all'elenco", @@ -6559,7 +6589,7 @@ "delete-button": "Elimina", "title": "Elimina" }, - "delete-modal-restore-dashboards-text": "Questa azione contrassegnerà il dashboard affinché venga eliminato tra 30 giorni. L'amministratore dell'organizzazione può ripristinarlo in qualsiasi momento prima della scadenza dei 30 giorni. ", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Vuoi eliminare questo dashboard?", "general": { "auto-refresh-description": "Definisci gli intervalli di aggiornamento automatico che dovrebbero essere disponibili nell'elenco di aggiornamento automatico. Utilizza il formato \"5s\" per i secondi, \"1m\" per i minuti, \"1h\" per le ore e \"1d\" per i giorni (ad esempio: \"5s,10s,30s,1m,5m,15m,30m,1h,2h,1d\").", @@ -6765,8 +6795,8 @@ "test": "Prova" }, "cloud-info-box": { - "body-alert": "Oppure puoi ignorare tutto e utilizzare {{mainDS}} (e {{extraDS}}) come origini dei dati completamente gestite, scalabili e ospitate da Grafana Labs con il <6>piano Grafana Cloud gratuito per sempre.", - "title-alert": "Configura la tua origine dei dati {{mainDS}} qui sotto" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Elimina dashboard", @@ -7305,6 +7335,14 @@ "title-failed-sample-query": "Impossibile caricare alcun esempio di registri per questa query", "tooltip": "Mostra le righe del registro che hanno contribuito alle metriche visualizzate" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Nessun campo" }, @@ -8213,6 +8251,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9213,6 +9257,8 @@ "actions-confirmation-label": "Messaggio di conferma", "actions-confirmation-message": "Fornisci un prompt descrittivo per confermare o annullare l'azione.", "footer-add-annotation": "Aggiungi annotazione", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Fai clic per {{actionTitle}}", "footer-click-to-navigate": "Fai clic per aprire {{linkTitle}}", "footer-filter-for-value": "Filtra per \"{{value}}\"", @@ -12359,7 +12405,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/ja-JP/grafana.json b/public/locales/ja-JP/grafana.json index a99080cb0f4..f24c3eaa678 100644 --- a/public/locales/ja-JP/grafana.json +++ b/public/locales/ja-JP/grafana.json @@ -2326,8 +2326,8 @@ "label-tenant-sources": "テナントソース" }, "rule-details-matching-instances": { - "showing-count": "{{totalItems}}件中{{visibleItems}}件のインスタンスを表示", - "button-show-all_other": "すべてのアラートインスタンス({{totalItems}}件)を表示" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4791,7 +4791,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "カンマで区切った値" }, @@ -5065,10 +5067,7 @@ "copy-or-duplicate": "コピーまたは複製", "delete": "削除", "duplicate": "複製", - "group-layout": "グループレイアウト", - "group-layout-disabled": "このレベルにグループはありません", - "panel-layout": "パネルレイアウト", - "panel-layout-disabled": "パネルレイアウトオプションを変更するには、行またはタブを選択してください" + "layout": "レイアウト" }, "continue": "", "ungroup-nested-text": "", @@ -5805,14 +5804,26 @@ }, "annotation-settings-edit": { "back-to-list": "一覧に戻る", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "削除", "description-color-annotation-event-markers": "注釈イベントマーカーに使用する色", "description-enabled-annotation-query-issued-every-dashboard": "有効にすると、ダッシュボードの更新ごとに注釈クエリが発行されます", - "description-hidden": "ダッシュボード上部で、注釈クエリのオン/オフを切り替えられます。このオプションをオンにすると、このトグルは非表示になります。", + "label-annotation-controls-display": "", "label-color": "色", "label-data-source": "データソース", "label-enabled": "有効化", - "label-hidden": "非表示", "label-name": "名前", "label-show-in": "表示先", "placeholder-choose-panels": "パネルを選択", @@ -5868,6 +5879,7 @@ "label-open-link-in-new-tab": "リンクを新しいタブで開く", "label-options": "オプション", "label-show-as-dropdown": "ドロップダウンリストとして表示", + "label-show-in-controls-menu": "", "label-title": "タイトル", "label-tooltip": "ツールチップ", "label-type": "タイプ", @@ -6427,6 +6439,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "変数エディタフォーム", "back-to-list": "一覧に戻る", @@ -6535,7 +6566,7 @@ "delete-button": "削除", "title": "削除" }, - "delete-modal-restore-dashboards-text": "このアクションにより、ダッシュボードは30日後に削除されます。組織の管理者は、30日が経過する前であればいつでもそれを復元できます。", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "このダッシュボードを削除しますか?", "general": { "auto-refresh-description": "自動更新リストで使用可能な自動更新間隔を定義します。秒には「5s」、分には「1m」、時間には「1h」、日には「1d」の形式を使用します(例:「5s、10s、30s、1m、5m、15m、30m、1h、2h、1d」)。", @@ -6741,8 +6772,8 @@ "test": "テスト" }, "cloud-info-box": { - "body-alert": "または、<6>永久無料のGrafana Cloudプランで、Grafana Labsからフルマネージドでスケーラブルなホスト済みデータソースの{{mainDS}}(および{{extraDS}})を入手して、手間を省くことも可能です。", - "title-alert": "以下で{{mainDS}}データソースを設定します" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "ダッシュボードを削除する", @@ -7281,6 +7312,14 @@ "title-failed-sample-query": "このクエリのログサンプルの読み込みに失敗しました", "tooltip": "視覚化されたメトリックに関連するログ行を表示" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "フィールドなし" }, @@ -8177,6 +8216,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9177,6 +9222,8 @@ "actions-confirmation-label": "確認メッセージ", "actions-confirmation-message": "操作を確認またはキャンセルするための説明的なプロンプトを提供します。", "footer-add-annotation": "注釈を追加", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "クリックして{{actionTitle}}", "footer-click-to-navigate": "クリックして{{linkTitle}}を開く", "footer-filter-for-value": "{{value}}値でフィルタリング", @@ -12306,7 +12353,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/ko-KR/grafana.json b/public/locales/ko-KR/grafana.json index 82f4cf39e1b..51978f07fb9 100644 --- a/public/locales/ko-KR/grafana.json +++ b/public/locales/ko-KR/grafana.json @@ -2326,8 +2326,8 @@ "label-tenant-sources": "테넌트 소스" }, "rule-details-matching-instances": { - "showing-count": "{{totalItems}}개 인스턴스 중 {{visibleItems}}개 표시 중", - "button-show-all_other": "모든 {{totalItems}} 경고 인스턴스 표시" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4791,7 +4791,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "쉼표로 구분된 값" }, @@ -5065,10 +5067,7 @@ "copy-or-duplicate": "복사 또는 복제", "delete": "삭제", "duplicate": "복제", - "group-layout": "그룹 레이아웃", - "group-layout-disabled": "이 레벨에는 그룹이 존재하지 않습니다", - "panel-layout": "패널 레이아웃", - "panel-layout-disabled": "패널 레이아웃 옵션을 변경하려면 행 또는 탭을 선택하세요" + "layout": "레이아웃" }, "continue": "", "ungroup-nested-text": "", @@ -5805,14 +5804,26 @@ }, "annotation-settings-edit": { "back-to-list": "목록으로 돌아가기", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "삭제", "description-color-annotation-event-markers": "주석 이벤트 마커에 사용할 색상", "description-enabled-annotation-query-issued-every-dashboard": "활성화되면 대시보드를 새로 고칠 때마다 주석 쿼리가 실행됩니다", - "description-hidden": "주석 쿼리는 대시보드 상단에서 토글하여 켜거나 끌 수 있습니다. 이 옵션을 선택하면 이 토글이 숨겨집니다.", + "label-annotation-controls-display": "", "label-color": "색상", "label-data-source": "데이터 소스", "label-enabled": "활성화됨", - "label-hidden": "숨김", "label-name": "이름", "label-show-in": "표시 위치", "placeholder-choose-panels": "패널 선택", @@ -5868,6 +5879,7 @@ "label-open-link-in-new-tab": "새 탭에서 링크 열기", "label-options": "옵션", "label-show-as-dropdown": "드롭다운으로 표시", + "label-show-in-controls-menu": "", "label-title": "제목", "label-tooltip": "툴팁", "label-type": "유형", @@ -6427,6 +6439,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "변수 편집기 양식", "back-to-list": "목록으로 돌아가기", @@ -6535,7 +6566,7 @@ "delete-button": "삭제", "title": "삭제" }, - "delete-modal-restore-dashboards-text": "이 작업을 수행하면 30일 후에 대시보드가 삭제됩니다. 조직 관리자는 30일이 만료되기 전에 언제든지 복구할 수 있습니다.", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "이 대시보드를 삭제하시겠어요?", "general": { "auto-refresh-description": "자동 새로 고침 목록에서 사용할 수 있는 자동 새로 고침 간격을 정의하세요. 초 단위는 '5s', 분 단위는 '1m', 시간 단위는 '1h', 일 단위는 '1d' 형식을 사용하세요(예: '5s, 10s, 30s, 1m, 5m, 15m, 30m, 1h, 2h, 1d').", @@ -6741,8 +6772,8 @@ "test": "테스트" }, "cloud-info-box": { - "body-alert": "또는 이 작업을 건너뛰고 <6>Grafana Cloud 평생 무료 플랜을 통해 Grafana Labs에서 완전 관리되고 확장 가능하며 호스팅되는 데이터 소스인 {{mainDS}}(및 {{extraDS}})을(를) 받으세요.", - "title-alert": "아래에서 {{mainDS}} 데이터 소스를 구성하세요" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "대시보드 삭제", @@ -7281,6 +7312,14 @@ "title-failed-sample-query": "이 쿼리에 대한 로그 샘플 로딩 실패", "tooltip": "시각화된 메트릭에 기여한 로그 줄 표시" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "필드 없음" }, @@ -8177,6 +8216,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9177,6 +9222,8 @@ "actions-confirmation-label": "확인 메시지", "actions-confirmation-message": "작업을 확인하거나 취소하기 위한 설명 프롬프트를 제공합니다.", "footer-add-annotation": "주석 추가", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "클릭하여 {{actionTitle}} 작업 수행", "footer-click-to-navigate": "클릭하여 {{linkTitle}} 열기", "footer-filter-for-value": "'{{value}}'으(로) 필터링", @@ -12306,7 +12353,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/nl-NL/grafana.json b/public/locales/nl-NL/grafana.json index 332e058e99e..96765f7630e 100644 --- a/public/locales/nl-NL/grafana.json +++ b/public/locales/nl-NL/grafana.json @@ -2334,9 +2334,8 @@ "label-tenant-sources": "Tenantbronnen" }, "rule-details-matching-instances": { - "showing-count": "{{visibleItems}} van {{totalItems}} instanties worden weergegeven", - "button-show-all_one": "Alle {{totalItems}} waarschuwingsinstanties weergeven", - "button-show-all_other": "Alle {{totalItems}} waarschuwingsinstanties weergeven" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4811,7 +4810,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Waarden gescheiden door komma" }, @@ -5085,10 +5086,7 @@ "copy-or-duplicate": "Kopiëren of dupliceren", "delete": "Verwijderen", "duplicate": "Dupliceren", - "group-layout": "Indeling van de groep", - "group-layout-disabled": "Er bestaan geen groepen op dit niveau", - "panel-layout": "Paneelindeling", - "panel-layout-disabled": "Selecteer een rij of tabblad om de indelingsopties van het paneel te wijzigen" + "layout": "Indeling" }, "continue": "", "ungroup-nested-text": "", @@ -5827,14 +5825,26 @@ }, "annotation-settings-edit": { "back-to-list": "Terug naar lijst", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Verwijderen", "description-color-annotation-event-markers": "Te gebruiken kleur voor het markeren van gebeurtenisannotaties", "description-enabled-annotation-query-issued-every-dashboard": "Wanneer ingeschakeld, wordt de annotatiequery elke dashboardvernieuwing uitgegeven", - "description-hidden": "Annotatiequery's kunnen bovenaan het dashboard worden in- of uitgeschakeld. Als deze optie is aangevinkt, wordt deze schakelaar verborgen.", + "label-annotation-controls-display": "", "label-color": "Kleur", "label-data-source": "Gegevensbron", "label-enabled": "Ingeschakeld", - "label-hidden": "Verborgen", "label-name": "Naam", "label-show-in": "Weergeven in", "placeholder-choose-panels": "Panelen kiezen", @@ -5890,6 +5900,7 @@ "label-open-link-in-new-tab": "Koppeling openen in nieuw tabblad", "label-options": "Opties", "label-show-as-dropdown": "Weergeven als dropdown", + "label-show-in-controls-menu": "", "label-title": "Titel", "label-tooltip": "Tooltip", "label-type": "Type", @@ -6451,6 +6462,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Formulier variabele bewerker", "back-to-list": "Terug naar lijst", @@ -6559,7 +6589,7 @@ "delete-button": "Verwijderen", "title": "Verwijderen" }, - "delete-modal-restore-dashboards-text": "Deze actie markeert het dashboard voor verwijdering over 30 dagen. Je organisatiebeheerder kan de dashboards op elk moment herstellen voordat de 30 dagen verlopen.", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Wil je dit dashboard verwijderen?", "general": { "auto-refresh-description": "Definieer de intervallen voor automatisch vernieuwen die beschikbaar moeten zijn in de lijst voor automatisch vernieuwen. Gebruik de notatie '5s' voor seconden, '1m' voor minuten, '1h' voor uren en '1d' voor dagen (bijvoorbeeld: '5s, 10s, 30s, 1m, 5m, 15m, 30m, 1h, 2h, 1d').", @@ -6765,8 +6795,8 @@ "test": "Testen" }, "cloud-info-box": { - "body-alert": "Of bespaar je de moeite en krijg {{mainDS}} (en {{extraDS}}) als volledig beheerde, schaalbare en gehoste gegevensbronnen van Grafana Labs met het <6>altijd gratis Grafana Cloud-abonnement.", - "title-alert": "Configureer hieronder je gegevensbron voor {{mainDS}}" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Dashboard verwijderen", @@ -7305,6 +7335,14 @@ "title-failed-sample-query": "Kan logvoorbeeld voor deze query niet laden", "tooltip": "Loglijnen weergeven die hebben bijgedragen aan gevisualiseerde statistieken" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Geen velden" }, @@ -8213,6 +8251,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9213,6 +9257,8 @@ "actions-confirmation-label": "Bevestigingsbericht", "actions-confirmation-message": "Geef een beschrijvende prompt om de actie te bevestigen of te annuleren.", "footer-add-annotation": "Annotatie toevoegen", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Klik om te {{actionTitle}}", "footer-click-to-navigate": "Klik om {{linkTitle}} te openen", "footer-filter-for-value": "Filteren op '{{value}}'", @@ -12359,7 +12405,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/pl-PL/grafana.json b/public/locales/pl-PL/grafana.json index e3c3dc215c4..96fe66f6ae0 100644 --- a/public/locales/pl-PL/grafana.json +++ b/public/locales/pl-PL/grafana.json @@ -2350,11 +2350,8 @@ "label-tenant-sources": "Źródła najemców" }, "rule-details-matching-instances": { - "showing-count": "Wyświetlanie {{visibleItems}} z {{totalItems}} instancji", - "button-show-all_one": "Pokaż wszystkie {{totalItems}} instancji alertów", - "button-show-all_few": "Pokaż wszystkie {{totalItems}} instancji alertów", - "button-show-all_many": "Pokaż wszystkie {{totalItems}} instancji alertów", - "button-show-all_other": "Pokaż wszystkie {{totalItems}} instancji alertów" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4851,7 +4848,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Wartości rozdzielone przecinkami" }, @@ -5125,10 +5124,7 @@ "copy-or-duplicate": "Kopiuj lub duplikuj", "delete": "Usuń", "duplicate": "Duplikuj", - "group-layout": "Układ grupy", - "group-layout-disabled": "Brak grup na tym poziomie", - "panel-layout": "Układ panelu", - "panel-layout-disabled": "Wybierz wiersz lub kartę, aby zmienić opcje układu panelu" + "layout": "Układ" }, "continue": "", "ungroup-nested-text": "", @@ -5871,14 +5867,26 @@ }, "annotation-settings-edit": { "back-to-list": "Powrót do listy", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Usuń", "description-color-annotation-event-markers": "Kolor używany dla znaczników zdarzeń związanych z adnotacją", "description-enabled-annotation-query-issued-every-dashboard": "Po włączeniu zapytanie dotyczące adnotacji jest wysyłane przy każdym odświeżeniu pulpitu", - "description-hidden": "Zapytania dotyczące adnotacji można włączyć lub wyłączyć u góry pulpitu. Po zaznaczeniu tej opcji przełącznik zostanie ukryty.", + "label-annotation-controls-display": "", "label-color": "Kolor", "label-data-source": "Źródło danych", "label-enabled": "Włączone", - "label-hidden": "Ukryte", "label-name": "Imię", "label-show-in": "Pokaż w", "placeholder-choose-panels": "Wybierz panele", @@ -5934,6 +5942,7 @@ "label-open-link-in-new-tab": "Otwórz link w nowej karcie", "label-options": "Opcje", "label-show-as-dropdown": "Pokaż jako listę rozwijaną", + "label-show-in-controls-menu": "", "label-title": "Tytuł", "label-tooltip": "Podpowiedź", "label-type": "Typ", @@ -6499,6 +6508,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Formularz edytora zmiennych", "back-to-list": "Powrót do listy", @@ -6607,7 +6635,7 @@ "delete-button": "Usuń", "title": "Usuń" }, - "delete-modal-restore-dashboards-text": "To działanie spowoduje oznaczenie pulpitu do usunięcia za 30 dni. Administrator organizacji może go przywrócić w dowolnym momencie przed upływem 30 dni.", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Czy chcesz usunąć ten pulpit?", "general": { "auto-refresh-description": "Zdefiniuj interwały automatycznego odświeżania, które będą dostępne na liście automatycznego odświeżania. Użyj formatu „5s” dla sekund, „1m” dla minut, „1h” dla godzin i „1d” dla dni (np.: „5s,10s,30s,1m,5m,15m,30m,1h,2h,1d”).", @@ -6813,8 +6841,8 @@ "test": "Test" }, "cloud-info-box": { - "body-alert": "Możesz ułatwić sobie życie i wybrać {{mainDS}} (oraz {{extraDS}}) jako w pełni zarządzane, skalowalne źródła danych hostowane przez Grafana Labs w ramach <6>planu Grafana Cloud, który będzie zawsze bezpłatny.", - "title-alert": "Skonfiguruj źródło danych {{mainDS}} poniżej" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Usuń pulpit", @@ -7353,6 +7381,14 @@ "title-failed-sample-query": "Nie udało się załadować próbki logów dla tego zapytania", "tooltip": "Pokaż wiersze logów, które przyczyniły się do wizualizacji metryk" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Brak pól" }, @@ -8285,6 +8321,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9285,6 +9327,8 @@ "actions-confirmation-label": "Wiadomość z potwierdzeniem", "actions-confirmation-message": "Wyślij prośbę o potwierdzenie lub anulowanie działania.", "footer-add-annotation": "Dodaj komentarz", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Kliknij, aby podjąć działanie: {{actionTitle}}", "footer-click-to-navigate": "Kliknij, aby otworzyć {{linkTitle}}", "footer-filter-for-value": "Filtruj wg wartości „{{value}}”", @@ -12465,7 +12509,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/pt-BR/grafana.json b/public/locales/pt-BR/grafana.json index c74388e4232..dc5bd71fadc 100644 --- a/public/locales/pt-BR/grafana.json +++ b/public/locales/pt-BR/grafana.json @@ -2334,9 +2334,8 @@ "label-tenant-sources": "Fontes de locatários" }, "rule-details-matching-instances": { - "showing-count": "Mostrando {{visibleItems}} de {{totalItems}} instâncias", - "button-show-all_one": "Exibir {{totalItems}} instância de alerta", - "button-show-all_other": "Exibir {{totalItems}} instância de alerta" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4811,7 +4810,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Valores separados por vírgula" }, @@ -5085,10 +5086,7 @@ "copy-or-duplicate": "Copiar ou duplicar", "delete": "Excluir", "duplicate": "Duplicar", - "group-layout": "Layout de grupo", - "group-layout-disabled": "Não há grupos neste nível", - "panel-layout": "Layout do painel", - "panel-layout-disabled": "Selecione uma linha ou aba para alterar as opções de layout do painel" + "layout": "Layout" }, "continue": "", "ungroup-nested-text": "", @@ -5827,14 +5825,26 @@ }, "annotation-settings-edit": { "back-to-list": "Voltar para a lista", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Excluir", "description-color-annotation-event-markers": "Cor que será usada para os marcadores de evento de anotação", "description-enabled-annotation-query-issued-every-dashboard": "Quando ativada, a consulta de anotação é emitida a cada atualização do painel", - "description-hidden": "As consultas de anotação podem ser ativadas ou desativadas na parte superior do painel. Com esta opção marcada, este botão de alternância ficará oculto.", + "label-annotation-controls-display": "", "label-color": "Cor", "label-data-source": "Fonte de dados", "label-enabled": "Ativado", - "label-hidden": "Oculto", "label-name": "Nome", "label-show-in": "Exibir em", "placeholder-choose-panels": "Escolher painéis", @@ -5890,6 +5900,7 @@ "label-open-link-in-new-tab": "Abrir link em nova aba", "label-options": "Opções", "label-show-as-dropdown": "Exibir como menu suspenso", + "label-show-in-controls-menu": "", "label-title": "Título", "label-tooltip": "Dica de uso", "label-type": "Tipo", @@ -6451,6 +6462,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Formulário do editor de variáveis", "back-to-list": "Voltar para a lista", @@ -6559,7 +6589,7 @@ "delete-button": "Excluir", "title": "Excluir" }, - "delete-modal-restore-dashboards-text": "Esta ação marcará o painel de controle para exclusão em 30 dias. O administrador da sua organização pode restaurá-lo a qualquer momento antes do término do prazo de 30 dias.", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Deseja excluir este painel de controle?", "general": { "auto-refresh-description": "Defina os intervalos de atualização automática disponíveis na lista de atualização automática. Use o formato '5s' para segundos, '1m' para minutos, '1h' para horas e '1d' para dias (por exemplo: '5s,10s,30s,1m,5m,15m,30m,1h,2h,1d').", @@ -6765,8 +6795,8 @@ "test": "Teste" }, "cloud-info-box": { - "body-alert": "Ou evite essa tarefa e obtenha {{mainDS}} (e {{extraDS}}) como fontes de dados totalmente gerenciadas, escaláveis e hospedadas da Grafana Labs com o <6>plano gratuito vitalício da Grafana Cloud.", - "title-alert": "Configure sua fonte de {{mainDS}} dados abaixo" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Excluir painel de controle", @@ -7305,6 +7335,14 @@ "title-failed-sample-query": "Falha ao carregar a amostra de logs para esta consulta", "tooltip": "Exibir linhas de log que contribuíram para as métricas visualizadas" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Sem campos" }, @@ -8213,6 +8251,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9213,6 +9257,8 @@ "actions-confirmation-label": "Mensagem de confirmação", "actions-confirmation-message": "Forneça um prompt descritivo para confirmar ou cancelar a ação.", "footer-add-annotation": "Adicionar anotação", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Clique para {{actionTitle}}", "footer-click-to-navigate": "Clique para abrir {{linkTitle}}", "footer-filter-for-value": "Filtrar por \"{{value}}\"", @@ -12359,7 +12405,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/pt-PT/grafana.json b/public/locales/pt-PT/grafana.json index a82cfe5b432..cfe6b435e73 100644 --- a/public/locales/pt-PT/grafana.json +++ b/public/locales/pt-PT/grafana.json @@ -2334,9 +2334,8 @@ "label-tenant-sources": "Origens de inquilinos" }, "rule-details-matching-instances": { - "showing-count": "A mostrar {{visibleItems}} de {{totalItems}} instâncias", - "button-show-all_one": "Mostrar todas as instâncias de alerta {{totalItems}}", - "button-show-all_other": "Mostrar todas as instâncias de alerta {{totalItems}}" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4811,7 +4810,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Valores separados por vírgulas" }, @@ -5085,10 +5086,7 @@ "copy-or-duplicate": "Copiar ou duplicar", "delete": "Eliminar", "duplicate": "Duplicar", - "group-layout": "Disposição do grupo", - "group-layout-disabled": "Não existem grupos neste nível", - "panel-layout": "Disposição do painel", - "panel-layout-disabled": "Selecione uma linha ou um separador para alterar as opções de disposição do painel" + "layout": "Layout" }, "continue": "", "ungroup-nested-text": "", @@ -5827,14 +5825,26 @@ }, "annotation-settings-edit": { "back-to-list": "Voltar à lista", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Eliminar", "description-color-annotation-event-markers": "Cor a utilizar para os marcadores de eventos de anotação", "description-enabled-annotation-query-issued-every-dashboard": "Quando esta opção está ativada, a consulta de anotação é emitida a cada atualização do painel de controlo", - "description-hidden": "As consultas de anotação podem ser ativadas ou desativadas na parte superior do painel de controlo. Com esta opção marcada, esta alternância ficará oculta.", + "label-annotation-controls-display": "", "label-color": "Cor", "label-data-source": "Origem dos dados", "label-enabled": "Ativado", - "label-hidden": "Oculto", "label-name": "Nome", "label-show-in": "Mostrar em", "placeholder-choose-panels": "Escolher painéis", @@ -5890,6 +5900,7 @@ "label-open-link-in-new-tab": "Abrir o link num novo separador", "label-options": "Opções", "label-show-as-dropdown": "Mostrar como menu suspenso", + "label-show-in-controls-menu": "", "label-title": "Título", "label-tooltip": "Descrição", "label-type": "Tipo", @@ -6451,6 +6462,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Formulário do editor de variáveis", "back-to-list": "Voltar à lista", @@ -6559,7 +6589,7 @@ "delete-button": "Eliminar", "title": "Eliminar" }, - "delete-modal-restore-dashboards-text": "Esta ação marcará o painel de controlo para eliminação em 30 dias. O administrador da sua organização pode restaurar os painéis de controlo a qualquer momento antes dos 30 dias expirarem. ", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Pretende eliminar este painel de controlo?", "general": { "auto-refresh-description": "Defina os intervalos de atualização automática que devem estar disponíveis na lista de atualização automática. Utilize o formato '5s' para segundos, '1m' para minutos, '1h' para horas e '1d' para dias (por ex.: '5s,10s,30s,1m,5m,15m,30m,1h,2h,1d').", @@ -6765,8 +6795,8 @@ "test": "Teste" }, "cloud-info-box": { - "body-alert": "Ou evite o esforço e obtenha {{mainDS}} (e {{extraDS}}) como origens de dados totalmente geridas, escaláveis e hospedadas da Grafana Labs com o <6>plano Grafana Cloud gratuito para sempre.", - "title-alert": "Configurar a sua origem de dados {{mainDS}} abaixo" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Eliminar painel de controlo", @@ -7305,6 +7335,14 @@ "title-failed-sample-query": "Falha ao carregar a amostra de registos para esta consulta", "tooltip": "Mostrar linhas de registo que contribuíram para as métricas visualizadas" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Nenhum campo" }, @@ -8213,6 +8251,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9213,6 +9257,8 @@ "actions-confirmation-label": "Mensagem de confirmação", "actions-confirmation-message": "Forneça uma mensagem descritiva para confirmar ou cancelar a ação.", "footer-add-annotation": "Adicionar anotação", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Clique para {{actionTitle}}", "footer-click-to-navigate": "Clique para abrir {{linkTitle}}", "footer-filter-for-value": "Filtrar por \"{{value}}\"", @@ -12359,7 +12405,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/ru-RU/grafana.json b/public/locales/ru-RU/grafana.json index d9de61dde42..56fc00e836c 100644 --- a/public/locales/ru-RU/grafana.json +++ b/public/locales/ru-RU/grafana.json @@ -2350,11 +2350,8 @@ "label-tenant-sources": "Источники клиента" }, "rule-details-matching-instances": { - "showing-count": "Показаны {{visibleItems}} из {{totalItems}} экземпляров", - "button-show-all_one": "Показать все {{totalItems}} экземпляр оповещения", - "button-show-all_few": "Показать все {{totalItems}} экземпляра оповещения", - "button-show-all_many": "Показать все {{totalItems}} экземпляров оповещения", - "button-show-all_other": "Показать все {{totalItems}} экземпляра оповещения" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4851,7 +4848,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Значения, разделенные запятыми" }, @@ -5125,10 +5124,7 @@ "copy-or-duplicate": "Копировать или дублировать", "delete": "Удалить", "duplicate": "Дублировать", - "group-layout": "Макет группы", - "group-layout-disabled": "На этом уровне нет групп", - "panel-layout": "Расположение панелей", - "panel-layout-disabled": "Выбрать строку или вкладку для изменения макета панели" + "layout": "Расположение" }, "continue": "", "ungroup-nested-text": "", @@ -5871,14 +5867,26 @@ }, "annotation-settings-edit": { "back-to-list": "Назад к списку", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Удалить", "description-color-annotation-event-markers": "Цвет, который будет использоваться для маркеров событий аннотаций.", "description-enabled-annotation-query-issued-every-dashboard": "Если этот параметр включен, запрос аннотации выдается при каждом обновлении панели.", - "description-hidden": "Запросы аннотаций можно включать или отключать в верхней части панели. Если установлен этот параметр, переключатель будет скрыт.", + "label-annotation-controls-display": "", "label-color": "Цвет", "label-data-source": "Источник данных", "label-enabled": "Включено", - "label-hidden": "Скрыто", "label-name": "Имя", "label-show-in": "Показать в", "placeholder-choose-panels": "Выбрать панели", @@ -5934,6 +5942,7 @@ "label-open-link-in-new-tab": "Открыть ссылку в новой вкладке", "label-options": "Параметры", "label-show-as-dropdown": "Показывать как раскрывающийся список", + "label-show-in-controls-menu": "", "label-title": "Название", "label-tooltip": "Подсказка", "label-type": "Тип", @@ -6499,6 +6508,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Форма редактора переменных", "back-to-list": "Назад к списку", @@ -6607,7 +6635,7 @@ "delete-button": "Удалить", "title": "Удаление" }, - "delete-modal-restore-dashboards-text": "Это действие пометит дашборд для удаления через 30 дней. Администратор вашей организации может восстановить его в любое время в течение указанных 30 дней.", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Действительно удалить дашборд?", "general": { "auto-refresh-description": "Задайте интервалы автообновления, которые должны быть доступны в соответствующем списке. Используйте формат «5 с» для секунд, «1 м» для минут, «1 ч» для часов и «1 д» для дней (например, «5 с, 10 с, 30 с, 1 м, 5 м, 15 м, 30 м, 1 ч, 2 ч, 1 д»).", @@ -6813,8 +6841,8 @@ "test": "Тестирование" }, "cloud-info-box": { - "body-alert": "Или не тратьте время и получите {{mainDS}} (и {{extraDS}}) в качестве полностью управляемых, масштабируемых и размещенных источников данных от Grafana Labs с <6>бессрочным бесплатным планом Grafana Cloud.", - "title-alert": "Настройте свой источник данных {{mainDS}} ниже" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Удалить дашборд", @@ -7353,6 +7381,14 @@ "title-failed-sample-query": "Не удалось загрузить пример журналов для этого запроса", "tooltip": "Показать строки журнала, которые оказали влияние на визуализированные метрики" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Нет полей" }, @@ -8285,6 +8321,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9285,6 +9327,8 @@ "actions-confirmation-label": "Сообщение о подтверждении", "actions-confirmation-message": "Предоставляет описательную подсказку для подтверждения или отмены действия.", "footer-add-annotation": "Добавить аннотацию", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Нажмите, чтобы {{actionTitle}}", "footer-click-to-navigate": "Нажмите, чтобы открыть {{linkTitle}}", "footer-filter-for-value": "Фильтр по «{{value}}»", @@ -12465,7 +12509,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/sv-SE/grafana.json b/public/locales/sv-SE/grafana.json index 37702588d0a..ed1313039a7 100644 --- a/public/locales/sv-SE/grafana.json +++ b/public/locales/sv-SE/grafana.json @@ -2334,9 +2334,8 @@ "label-tenant-sources": "Klientkällor" }, "rule-details-matching-instances": { - "showing-count": "Visar {{visibleItems}} av {{totalItems}} instanser", - "button-show-all_one": "Visa alla {{totalItems}} larminstanser", - "button-show-all_other": "Visa alla {{totalItems}} larminstanser" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4811,7 +4810,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Värden åtskilda med kommatecken" }, @@ -5085,10 +5086,7 @@ "copy-or-duplicate": "Kopiera eller duplicera", "delete": "Ta bort", "duplicate": "Dubblett", - "group-layout": "Grupplayout", - "group-layout-disabled": "Det finns inga grupper på den här nivån", - "panel-layout": "Panellayout", - "panel-layout-disabled": "Välj en rad eller flik för att ändra alternativ för panellayout" + "layout": "Layout" }, "continue": "", "ungroup-nested-text": "", @@ -5827,14 +5825,26 @@ }, "annotation-settings-edit": { "back-to-list": "Tillbaka till listan", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Ta bort", "description-color-annotation-event-markers": "Färg som ska användas för kommentarshändelsemarkörer", "description-enabled-annotation-query-issued-every-dashboard": "När aktiverat utfärdas kommentarsfrågan vid varje uppdatering av instrumentpanelen", - "description-hidden": "Frågor om kommentarer kan aktiveras eller inaktiveras högst upp på instrumentpanelen. Med det här alternativet markerat kommer denna växel att döljas.", + "label-annotation-controls-display": "", "label-color": "Färg", "label-data-source": "Datakälla", "label-enabled": "Aktiverad", - "label-hidden": "Dolt", "label-name": "Namn", "label-show-in": "Visa i", "placeholder-choose-panels": "Välj paneler", @@ -5890,6 +5900,7 @@ "label-open-link-in-new-tab": "Öppna länken i en ny flik", "label-options": "Alternativ", "label-show-as-dropdown": "Visa som rullgardinsmeny", + "label-show-in-controls-menu": "", "label-title": "Titel", "label-tooltip": "Verktygstips", "label-type": "Typ", @@ -6451,6 +6462,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Formulär för variabelsredigering", "back-to-list": "Tillbaka till listan", @@ -6559,7 +6589,7 @@ "delete-button": "Ta bort", "title": "Ta bort" }, - "delete-modal-restore-dashboards-text": "Denna åtgärd markerar instrumentpanelen för radering om 30 dagar. Din organisationsadministratör kan återställa den när som helst innan de 30 dagarna löper ut. ", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Vill du radera denna instrumentpanel?", "general": { "auto-refresh-description": "Definiera de automatiska uppdateringsintervallen som ska vara tillgängliga i listan över automatiska uppdateringar. Använd formatet ”5s” för sekunder, ”1m” för minuter, ”1h” för timmar och ”1d” för dagar (t.ex.: ”5s,10s,30s,1m,5m,15m,30m,1h,2h,1d”).", @@ -6765,8 +6795,8 @@ "test": "Test" }, "cloud-info-box": { - "body-alert": "Eller hoppa över ansträngningen och få {{mainDS}} (och {{extraDS}}) som fullt hanterade, skalbara och värdbaserade datakällor från Grafana Labs med <6>Grafana Cloud-prenumerationen gratis för alltid.", - "title-alert": "Konfigurera din {{mainDS}}-datakälla nedan" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Ta bort instrumentpanel", @@ -7305,6 +7335,14 @@ "title-failed-sample-query": "Det gick inte att ladda loggprov för denna fråga", "tooltip": "Visa loggrader som bidrog till visualiserade mätvärden" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Inga fält" }, @@ -8213,6 +8251,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9213,6 +9257,8 @@ "actions-confirmation-label": "Bekräftelsemeddelande", "actions-confirmation-message": "Tillhandahåll en beskrivande prompt för att bekräfta eller avbryta åtgärden.", "footer-add-annotation": "Lägg till kommentar", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "Klicka för att {{actionTitle}}", "footer-click-to-navigate": "Klicka för att öppna {{linkTitle}}", "footer-filter-for-value": "Filtrera för ”{{value}}”", @@ -12359,7 +12405,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/tr-TR/grafana.json b/public/locales/tr-TR/grafana.json index ea77d97bfd9..8f574384a75 100644 --- a/public/locales/tr-TR/grafana.json +++ b/public/locales/tr-TR/grafana.json @@ -2334,9 +2334,8 @@ "label-tenant-sources": "Kiracı kaynakları" }, "rule-details-matching-instances": { - "showing-count": "{{visibleItems}}/{{totalItems}} örnek gösteriliyor", - "button-show-all_one": "{{totalItems}} uyarı örneğinin tamamını göster", - "button-show-all_other": "{{totalItems}} uyarı örneğinin tamamını göster" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4811,7 +4810,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "Virgülle ayrılmış değerler" }, @@ -5085,10 +5086,7 @@ "copy-or-duplicate": "Kopyala veya Çoğalt", "delete": "Sil", "duplicate": "Çoğalt", - "group-layout": "Grup düzeni", - "group-layout-disabled": "Bu seviyede hiçbir grup yok", - "panel-layout": "Panel yazı tipi", - "panel-layout-disabled": "Panel düzeni seçeneklerini değiştirmek için bir satır veya sekme seçin" + "layout": "Düzen" }, "continue": "", "ungroup-nested-text": "", @@ -5827,14 +5825,26 @@ }, "annotation-settings-edit": { "back-to-list": "Listeye geri dön", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "Sil", "description-color-annotation-event-markers": "Ek açıklama olay işaretçileri için kullanılacak renk", "description-enabled-annotation-query-issued-every-dashboard": "Etkinleştirildiğinde her pano yenilemesinde açıklama sorgusu çalıştırılır", - "description-hidden": "Ek açıklama sorguları, panonun üst kısmından açılabilir veya kapatılabilir. Bu seçenek işaretlendiğinde bu açma/kapama gizlenecektir.", + "label-annotation-controls-display": "", "label-color": "Renk", "label-data-source": "Veri kaynağı", "label-enabled": "Etkin", - "label-hidden": "Gizli", "label-name": "Ad", "label-show-in": "Şurada göster:", "placeholder-choose-panels": "Panel seçin", @@ -5890,6 +5900,7 @@ "label-open-link-in-new-tab": "Bağlantıyı yeni sekmede aç", "label-options": "Seçenekler", "label-show-as-dropdown": "Açılır menü olarak göster", + "label-show-in-controls-menu": "", "label-title": "Başlık", "label-tooltip": "Araç ipucu", "label-type": "Tür", @@ -6451,6 +6462,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "Değişken düzenleyici formu", "back-to-list": "Listeye geri dön", @@ -6559,7 +6589,7 @@ "delete-button": "Sil", "title": "Sil" }, - "delete-modal-restore-dashboards-text": "Bu işlem, panoyu 30 gün içinde silinmek üzere işaretleyecektir. Kuruluş yöneticiniz, 30 günlük süre dolmadan panoyu istediği zaman geri yükleyebilir.", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "Bu panoyu silmek istiyor musunuz?", "general": { "auto-refresh-description": "Otomatik yenileme listesinde bulunması gereken otomatik yenileme aralıklarını tanımlayın. Saniyeler için \"5s\", dakikalar için \"1m\", saatler için \"1h\" ve günler için \"1d\" biçimini kullanın (örneğin: \"5s,10s,30s,1m,5m,15m,30m,1h,2h,1d'\").", @@ -6765,8 +6795,8 @@ "test": "Test" }, "cloud-info-box": { - "body-alert": "Veya uğraşmadan {{mainDS}} (ve {{extraDS}}) veri kaynaklarını Grafana Labs'tan tamamen yönetilen, ölçeklenebilir ve barındırılan <6>daima ücretsiz Grafana Cloud planıyla edinin.", - "title-alert": "Aşağıdan {{mainDS}} veri kaynağınızı yapılandırın" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "Panoyu sil", @@ -7305,6 +7335,14 @@ "title-failed-sample-query": "Bu sorgu için günlük kaydı örneği yüklenemedi", "tooltip": "Görselleştirilen metriklere katkıda bulunan günlük kayıtlarını göster" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "Alan yok" }, @@ -8213,6 +8251,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9213,6 +9257,8 @@ "actions-confirmation-label": "Onay mesajı", "actions-confirmation-message": "İşlemi onaylamak veya iptal etmek için açıklayıcı bir istem sağlayın.", "footer-add-annotation": "Ek açıklama ekle", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "{{actionTitle}} için tıklayın", "footer-click-to-navigate": "{{linkTitle}} ögesini açmak için tıklayın", "footer-filter-for-value": "'{{value}}' değerine göre filtrele", @@ -12359,7 +12405,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/zh-Hans/grafana.json b/public/locales/zh-Hans/grafana.json index 950acdeadbb..302ea2645f3 100644 --- a/public/locales/zh-Hans/grafana.json +++ b/public/locales/zh-Hans/grafana.json @@ -2326,8 +2326,8 @@ "label-tenant-sources": "租户源" }, "rule-details-matching-instances": { - "showing-count": "显示 {{visibleItems}} 个实例,共 {{totalItems}} 个", - "button-show-all_other": "显示所有 {{totalItems}} 个警报实例" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4791,7 +4791,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "以逗号分隔的值" }, @@ -5065,10 +5067,7 @@ "copy-or-duplicate": "复制或拷贝", "delete": "删除", "duplicate": "复制", - "group-layout": "组布局", - "group-layout-disabled": "此级别上不存在组", - "panel-layout": "面板布局", - "panel-layout-disabled": "选择一行或选项卡以更改面板布局选项" + "layout": "布局" }, "continue": "", "ungroup-nested-text": "", @@ -5805,14 +5804,26 @@ }, "annotation-settings-edit": { "back-to-list": "回到列表", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "删除", "description-color-annotation-event-markers": "用于注释事件标记的颜色", "description-enabled-annotation-query-issued-every-dashboard": "启用后,每次数据面板刷新时都会发出注释查询", - "description-hidden": "可在数据面板顶部打开或关闭注释查询。选中此选项后,此切换开关将被隐藏。", + "label-annotation-controls-display": "", "label-color": "颜色", "label-data-source": "数据源", "label-enabled": "已启用", - "label-hidden": "隐藏", "label-name": "名称", "label-show-in": "显示于", "placeholder-choose-panels": "选择面板", @@ -5868,6 +5879,7 @@ "label-open-link-in-new-tab": "在新选项卡中打开链接", "label-options": "选项", "label-show-as-dropdown": "显示为下拉", + "label-show-in-controls-menu": "", "label-title": "标题", "label-tooltip": "工具提示", "label-type": "类型", @@ -6427,6 +6439,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "变量编辑器表单", "back-to-list": "回到列表", @@ -6535,7 +6566,7 @@ "delete-button": "删除", "title": "删除" }, - "delete-modal-restore-dashboards-text": "此操作会将数据面板标记为在 30 天后删除。您的组织管理员可以在 30 天期限内随时还原。", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "您要删除这个数据面板吗?", "general": { "auto-refresh-description": "定义应显示于自动刷新列表中的自动刷新间隔。使用格式“5s”表示秒,“1m”表示分,“1h”表示小时,“1d”表示天(例如:“5s,10s,30s,1m,5m,15m,30m,1h,2h,1d”)。", @@ -6741,8 +6772,8 @@ "test": "测试" }, "cloud-info-box": { - "body-alert": "您也可以省去这些步骤,通过<6>永久免费的 Grafana Cloud 计划,从 Grafana Labs 获取完全托管、可扩展和托管式数据源 {{mainDS}}(和 {{extraDS}})。", - "title-alert": "在下方配置您的 {{mainDS}} 数据源" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "删除数据面板", @@ -7281,6 +7312,14 @@ "title-failed-sample-query": "加载此查询的日志示例失败", "tooltip": "显示有助于实现可视化指标的日志行" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "没有字段" }, @@ -8177,6 +8216,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9177,6 +9222,8 @@ "actions-confirmation-label": "确认消息", "actions-confirmation-message": "提供描述性提示以确认或取消操作。", "footer-add-annotation": "添加注释", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "点击以 {{actionTitle}}", "footer-click-to-navigate": "点击打开 {{linkTitle}}", "footer-filter-for-value": "筛选“{{value}}”", @@ -12306,7 +12353,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/locales/zh-Hant/grafana.json b/public/locales/zh-Hant/grafana.json index f4cdba753fd..a0beece480a 100644 --- a/public/locales/zh-Hant/grafana.json +++ b/public/locales/zh-Hant/grafana.json @@ -2326,8 +2326,8 @@ "label-tenant-sources": "租用戶來源" }, "rule-details-matching-instances": { - "showing-count": "顯示 {{visibleItems}} 個執行個體,共 {{totalItems}} 個", - "button-show-all_other": "顯示所有 {{totalItems}} 個警報執行個體" + "button-show-all": "", + "showing-count": "" }, "rule-editor": { "get-content": { @@ -4791,7 +4791,9 @@ }, "variable": { "custom-options": { - "close": "", + "apply": "", + "change-value": "", + "discard": "", "modal-title": "", "values": "以逗號分隔的值" }, @@ -5065,10 +5067,7 @@ "copy-or-duplicate": "複製或重複", "delete": "刪除", "duplicate": "重複", - "group-layout": "群組版面配置", - "group-layout-disabled": "此層級上不存在群組", - "panel-layout": "面板版面配置", - "panel-layout-disabled": "選擇一列或分頁以變更面板版面配置選項" + "layout": "版面配置" }, "continue": "", "ungroup-nested-text": "", @@ -5805,14 +5804,26 @@ }, "annotation-settings-edit": { "back-to-list": "返回清單", + "control-display-options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "description": "", + "label": "" + } + }, "delete": "刪除", "description-color-annotation-event-markers": "用於註解事件標記的顏色", "description-enabled-annotation-query-issued-every-dashboard": "啟用後,每次儀表板重新整理時都會發出註解查詢", - "description-hidden": "可以在儀表板頂部開啟或關閉註解查詢。選擇此選項後,此切換選項將被隱藏。", + "label-annotation-controls-display": "", "label-color": "顏色", "label-data-source": "資料來源", "label-enabled": "已啟用", - "label-hidden": "隱藏", "label-name": "名稱(名字)", "label-show-in": "顯示在", "placeholder-choose-panels": "選擇面板", @@ -5868,6 +5879,7 @@ "label-open-link-in-new-tab": "用新分頁開啟連結", "label-options": "選項", "label-show-as-dropdown": "顯示為下拉式", + "label-show-in-controls-menu": "", "label-title": "標題", "label-tooltip": "提示", "label-type": "類型", @@ -6427,6 +6439,25 @@ "variable-controls": { "add-variable": "" }, + "variable-display-select": { + "label": "", + "options": { + "above-dashboard": { + "label": "" + }, + "controls-menu": { + "description": "", + "label": "" + }, + "hidden": { + "label": "" + }, + "hidden-label": { + "description": "", + "label": "" + } + } + }, "variable-editor-form": { "aria-label-variable-editor-form": "變數編輯器表單", "back-to-list": "返回清單", @@ -6535,7 +6566,7 @@ "delete-button": "刪除", "title": "刪除" }, - "delete-modal-restore-dashboards-text": "此動作會標記儀表板,以便在 30 天後刪除。您的組織管理員可以在 30 天到期之前隨時還原。", + "delete-modal-restore-dashboards-text": "", "delete-modal-text": "您要刪除此儀表板嗎?", "general": { "auto-refresh-description": "定義自動重新整理清單中應該可用的自動重新整理間隔。使用格式「5s」表示秒,「1m」表示分鐘,「1h」表示小時,「1d」表示天(例如:「5s、10s、30s、1m、5m、15m、30m、1h、2h、1d」)。", @@ -6741,8 +6772,8 @@ "test": "測試" }, "cloud-info-box": { - "body-alert": "或者,跳過這個步驟,並透過<6>永久免費的 Grafana Cloud 方案,從 Grafana Labs 取得完全受控、可擴展及託管的資料來源 {{mainDS}}(和 {{extraDS}})。", - "title-alert": "在下方設定您的 {{mainDS}} 資料來源" + "body-alert": "", + "title-alert": "" }, "dashboards-table": { "aria-label-delete-dashboard": "刪除儀表板", @@ -7281,6 +7312,14 @@ "title-failed-sample-query": "無法載入此查詢的紀錄樣本", "tooltip": "顯示對可視化指標有貢獻的紀錄行" }, + "logs-table": { + "action-buttons": { + "copy-link": "", + "copy-to-clipboard": "", + "inspect-value": "", + "view-log-line": "" + } + }, "logs-table-empty-fields": { "no-fields": "沒有欄位" }, @@ -8177,6 +8216,12 @@ "nextNYears_other": "" } }, + "field": { + "fieldColor": { + "accessibleGroup": "", + "otherGroup": "" + } + }, "valueFormats": { "categories": { "acceleration": { @@ -9177,6 +9222,8 @@ "actions-confirmation-label": "確認訊息", "actions-confirmation-message": "提供描述性提示以確認或取消動作。", "footer-add-annotation": "新增注釋", + "footer-apply-series-as-filter": "", + "footer-apply-series-as-inverse-filter": "", "footer-click-to-action": "點選以{{actionTitle}}", "footer-click-to-navigate": "點選以開啟「{{linkTitle}}」", "footer-filter-for-value": "篩選值「{{value}}」", @@ -12306,7 +12353,8 @@ "bar-glow": "", "center-glow": "", "rounded-bars": "", - "spotlight": "" + "spotlight": "", + "spotlight-tooltip": "" }, "gradient": "", "gradient-auto": "", diff --git a/public/openapi3.json b/public/openapi3.json index e775ea14d2c..546f15a7a86 100644 --- a/public/openapi3.json +++ b/public/openapi3.json @@ -7612,7 +7612,7 @@ "type": "integer" }, "key": { - "example": "glsa_yscW25imSKJIuav8zF37RZmnbiDvB05G_fcaaf58a", + "example": "glsa_iNValIdinValiDinvalidinvalidinva_5b582697", "type": "string" }, "name": { diff --git a/scripts/grafana-server/custom.ini b/scripts/grafana-server/custom.ini index 5bc9fc49e2c..40b884190be 100644 --- a/scripts/grafana-server/custom.ini +++ b/scripts/grafana-server/custom.ini @@ -24,7 +24,7 @@ stack_id = 12345 enable_alpha = true [plugins] -allow_loading_unsigned_plugins=grafana-extensionstest-app,grafana-extensionexample1-app,grafana-extensionexample2-app,grafana-extensionexample3-app,grafana-e2etest-datasource +allow_loading_unsigned_plugins=grafana-extensionstest-app,grafana-extensionexample1-app,grafana-extensionexample2-app,grafana-extensionexample3-app,grafana-e2etest-datasource,grafana-e2etest-panel [database] type=sqlite3 diff --git a/yarn.lock b/yarn.lock index cb495d132ca..057e3613d68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1473,7 +1473,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.5, @babel/runtime@npm:^7.24.7, @babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.25.6, @babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.26.10, @babel/runtime@npm:^7.26.7, @babel/runtime@npm:^7.27.0, @babel/runtime@npm:^7.27.6, @babel/runtime@npm:^7.28.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.7": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.24.5, @babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.25.6, @babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.26.10, @babel/runtime@npm:^7.26.7, @babel/runtime@npm:^7.27.0, @babel/runtime@npm:^7.27.6, @babel/runtime@npm:^7.28.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.7": version: 7.28.4 resolution: "@babel/runtime@npm:7.28.4" checksum: 10/6c9a70452322ea80b3c9b2a412bcf60771819213a67576c8cec41e88a95bb7bf01fc983754cda35dc19603eef52df22203ccbf7777b9d6316932f9fb77c25163 @@ -3445,17 +3445,17 @@ __metadata: languageName: unknown linkType: soft -"@grafana/plugin-e2e@npm:^3.0.1": - version: 3.0.1 - resolution: "@grafana/plugin-e2e@npm:3.0.1" +"@grafana/plugin-e2e@npm:^3.0.3": + version: 3.0.3 + resolution: "@grafana/plugin-e2e@npm:3.0.3" dependencies: - "@grafana/e2e-selectors": "npm:^12.2.0-255920" + "@grafana/e2e-selectors": "npm:^12.4.0-19890644192" semver: "npm:^7.5.4" uuid: "npm:^13.0.0" yaml: "npm:^2.3.4" peerDependencies: "@playwright/test": ^1.52.0 - checksum: 10/1cd95c1e4365f93e884d7ae4d77961e038cd4fcc235e313dd9f96bd0e21090c5aa26a765bedf45cc13cc0dc913da79007172fd9680088b356ef485672ce34681 + checksum: 10/d9247d52cc5b65c91983212790610b0c2470d705fa4e37178d04cbf681c4fc80bb08b2c39ea6f0061cb0d78242f108a5c8e6fa1ad2f2209d6f15d34000cb1d00 languageName: node linkType: hard @@ -3782,6 +3782,10 @@ __metadata: "@hello-pangea/dnd": "npm:18.0.1" "@monaco-editor/react": "npm:4.7.0" "@popperjs/core": "npm:2.11.8" + "@rc-component/drawer": "npm:1.3.0" + "@rc-component/picker": "npm:1.7.1" + "@rc-component/slider": "npm:1.0.1" + "@rc-component/tooltip": "npm:1.4.0" "@react-aria/dialog": "npm:3.5.31" "@react-aria/focus": "npm:3.21.2" "@react-aria/overlays": "npm:3.30.0" @@ -3863,10 +3867,6 @@ __metadata: prismjs: "npm:1.30.0" process: "npm:^0.11.10" rc-cascader: "npm:3.34.0" - rc-drawer: "npm:7.3.0" - rc-picker: "npm:4.11.3" - rc-slider: "npm:11.1.9" - rc-tooltip: "npm:6.4.0" react: "npm:18.3.1" react-calendar: "npm:^6.0.0" react-colorful: "npm:5.6.1" @@ -6789,7 +6789,64 @@ __metadata: languageName: node linkType: hard -"@rc-component/portal@npm:^1.1.0, @rc-component/portal@npm:^1.1.1": +"@rc-component/drawer@npm:1.3.0": + version: 1.3.0 + resolution: "@rc-component/drawer@npm:1.3.0" + dependencies: + "@rc-component/motion": "npm:^1.1.4" + "@rc-component/portal": "npm:^2.0.0" + "@rc-component/util": "npm:^1.2.1" + clsx: "npm:^2.1.1" + peerDependencies: + react: ">=18.0.0" + react-dom: ">=18.0.0" + checksum: 10/55bd6e2aac3d0bbe04f9e79c5cf60bbb3291a32eeaf9e2cbcad7ec360543d5c44efdc8f0d49ba420f05c11866c7b263029c60ecab8bbce5fcab860e552a13e1a + languageName: node + linkType: hard + +"@rc-component/motion@npm:^1.0.0, @rc-component/motion@npm:^1.1.4": + version: 1.1.5 + resolution: "@rc-component/motion@npm:1.1.5" + dependencies: + "@rc-component/util": "npm:^1.2.0" + clsx: "npm:^2.1.1" + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: 10/61993afa6aca1353ac1200c042450e7439ee5638f7542838bf741aaac0eaa0584b45150902379da1e0352db4b30d95c2d3d5477e1a217b526eb033c4acb91558 + languageName: node + linkType: hard + +"@rc-component/picker@npm:1.7.1": + version: 1.7.1 + resolution: "@rc-component/picker@npm:1.7.1" + dependencies: + "@rc-component/resize-observer": "npm:^1.0.0" + "@rc-component/trigger": "npm:^3.6.15" + "@rc-component/util": "npm:^1.3.0" + clsx: "npm:^2.1.1" + rc-overflow: "npm:^1.3.2" + peerDependencies: + date-fns: ">= 2.x" + dayjs: ">= 1.x" + luxon: ">= 3.x" + moment: ">= 2.x" + react: ">=16.9.0" + react-dom: ">=16.9.0" + peerDependenciesMeta: + date-fns: + optional: true + dayjs: + optional: true + luxon: + optional: true + moment: + optional: true + checksum: 10/dd52cc7492071b5f609d712db2c66a9b4a807112d1bcad4561ad385f7597bb853b79263dc863416fa70f91da6c2c7e1b738fd649487a1e3783f1b6f96c0b8073 + languageName: node + linkType: hard + +"@rc-component/portal@npm:^1.1.0": version: 1.1.1 resolution: "@rc-component/portal@npm:1.1.1" dependencies: @@ -6803,7 +6860,74 @@ __metadata: languageName: node linkType: hard -"@rc-component/trigger@npm:^2.0.0, @rc-component/trigger@npm:^2.1.1": +"@rc-component/portal@npm:^2.0.0": + version: 2.0.1 + resolution: "@rc-component/portal@npm:2.0.1" + dependencies: + "@rc-component/util": "npm:^1.2.1" + clsx: "npm:^2.1.1" + peerDependencies: + react: ">=18.0.0" + react-dom: ">=18.0.0" + checksum: 10/c53df9c27b65f2f4fc8e9952f1b7fe9aa70b284541881296149bef5eb899d77cbc75e1dcfb477cb08751817644da2e731b273a11eb4cf772173c0228d4190532 + languageName: node + linkType: hard + +"@rc-component/resize-observer@npm:^1.0.0, @rc-component/resize-observer@npm:^1.0.1": + version: 1.0.1 + resolution: "@rc-component/resize-observer@npm:1.0.1" + dependencies: + "@rc-component/util": "npm:^1.2.0" + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: 10/a6d12d72c0e029f7599955e66cba041b21fe23965e02b289b6f5bef1ad24e5fe2eb18c7f5255ad87cc2e658a7c8a5daa30417992e08d5d7442dc8bcdc81772e6 + languageName: node + linkType: hard + +"@rc-component/slider@npm:1.0.1": + version: 1.0.1 + resolution: "@rc-component/slider@npm:1.0.1" + dependencies: + "@rc-component/util": "npm:^1.3.0" + clsx: "npm:^2.1.1" + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: 10/23ee6d696e7e60fa0d707ef0d58aba7892e4e3630b0f466b4ffda374210be0cd2e63fff034fcfcf11f72c03d4a4e980560ab5be3807f441cf8e20280793ba33e + languageName: node + linkType: hard + +"@rc-component/tooltip@npm:1.4.0": + version: 1.4.0 + resolution: "@rc-component/tooltip@npm:1.4.0" + dependencies: + "@rc-component/trigger": "npm:^3.7.1" + "@rc-component/util": "npm:^1.3.0" + clsx: "npm:^2.1.1" + peerDependencies: + react: ">=18.0.0" + react-dom: ">=18.0.0" + checksum: 10/2e81bc4b15afaef66f7c7ad4cf1b21cf900ea221bbfc78995a3bea7da33491654ab7f2368ae9b39d9a3d14cfeb7639420506cdbd642c7539b43ad1021c72f8ee + languageName: node + linkType: hard + +"@rc-component/tree@npm:1.1.0": + version: 1.1.0 + resolution: "@rc-component/tree@npm:1.1.0" + dependencies: + "@rc-component/motion": "npm:^1.0.0" + "@rc-component/util": "npm:^1.2.1" + "@rc-component/virtual-list": "npm:^1.0.1" + clsx: "npm:^2.1.1" + peerDependencies: + react: "*" + react-dom: "*" + checksum: 10/2195332316b95501d0afad15d2edeaddd1eb6ccf98f1c46588750ad6911d1692b64279a46e4cba7c2a202f170d4363a3a3411819bc3087e5a8d99323acb5056f + languageName: node + linkType: hard + +"@rc-component/trigger@npm:^2.1.1": version: 2.2.0 resolution: "@rc-component/trigger@npm:2.2.0" dependencies: @@ -6820,6 +6944,50 @@ __metadata: languageName: node linkType: hard +"@rc-component/trigger@npm:^3.6.15, @rc-component/trigger@npm:^3.7.1": + version: 3.7.1 + resolution: "@rc-component/trigger@npm:3.7.1" + dependencies: + "@rc-component/motion": "npm:^1.1.4" + "@rc-component/portal": "npm:^2.0.0" + "@rc-component/resize-observer": "npm:^1.0.0" + "@rc-component/util": "npm:^1.2.1" + clsx: "npm:^2.1.1" + peerDependencies: + react: ">=18.0.0" + react-dom: ">=18.0.0" + checksum: 10/d788d03b4525dc1f4ab4f9797995e4b4041ee24e6fc5d12b3f9308560228c18823ccdacee0efd3f0399bf7bf0318afccfd7d3b899e29a7d44c4fe4086f2e31cd + languageName: node + linkType: hard + +"@rc-component/util@npm:^1.2.0, @rc-component/util@npm:^1.2.1, @rc-component/util@npm:^1.3.0, @rc-component/util@npm:^1.4.0": + version: 1.4.0 + resolution: "@rc-component/util@npm:1.4.0" + dependencies: + is-mobile: "npm:^5.0.0" + react-is: "npm:^18.2.0" + peerDependencies: + react: ">=18.0.0" + react-dom: ">=18.0.0" + checksum: 10/dc74487289ffdf83b854d9511b5be2a2400ac08a3c51645f0d2afaf90e991e8f9d244690a0ef246fb07fb0bccdcc3c913950b159b204b832ceae8f19534cb263 + languageName: node + linkType: hard + +"@rc-component/virtual-list@npm:^1.0.1": + version: 1.0.2 + resolution: "@rc-component/virtual-list@npm:1.0.2" + dependencies: + "@babel/runtime": "npm:^7.20.0" + "@rc-component/resize-observer": "npm:^1.0.1" + "@rc-component/util": "npm:^1.4.0" + clsx: "npm:^2.1.1" + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + checksum: 10/a0e0e730e4ba362b1c4c52977b952a8d056235b232c4f2d73f66b2d0639ed7a3d6eb1faa3c2d835f77fa793b5dbab8b6093240477433098162abc8b0c3cdae7f + languageName: node + linkType: hard + "@reach/observe-rect@npm:^1.1.0": version: 1.2.0 resolution: "@reach/observe-rect@npm:1.2.0" @@ -9408,6 +9576,7 @@ __metadata: dependencies: "@emotion/css": "npm:11.11.2" "@grafana/data": "workspace:*" + "@grafana/i18n": "workspace:*" "@grafana/plugin-configs": "workspace:*" "@grafana/runtime": "workspace:*" "@grafana/schema": "workspace:*" @@ -9420,6 +9589,7 @@ __metadata: "@types/semver": "npm:7.5.8" "@types/uuid": "npm:9.0.8" glob: "npm:10.5.0" + i18next-cli: "npm:^1.24.22" react: "npm:18.3.1" react-dom: "npm:18.3.1" react-router-dom: "npm:^6.22.0" @@ -9440,6 +9610,7 @@ __metadata: dependencies: "@emotion/css": "npm:11.11.2" "@grafana/data": "workspace:*" + "@grafana/i18n": "workspace:*" "@grafana/plugin-configs": "workspace:*" "@grafana/runtime": "workspace:*" "@grafana/schema": "workspace:*" @@ -9452,6 +9623,41 @@ __metadata: "@types/semver": "npm:7.5.8" "@types/uuid": "npm:9.0.8" glob: "npm:10.4.1" + i18next-cli: "npm:^1.24.22" + react: "npm:18.3.1" + react-dom: "npm:18.3.1" + react-router-dom: "npm:^6.22.0" + rxjs: "npm:7.8.1" + ts-node: "npm:10.9.2" + tslib: "npm:2.6.3" + typescript: "npm:5.5.4" + webpack: "npm:5.95.0" + webpack-merge: "npm:5.10.0" + peerDependencies: + "@grafana/runtime": "*" + languageName: unknown + linkType: soft + +"@test-plugins/grafana-e2etest-panel@workspace:e2e-playwright/test-plugins/grafana-test-panel": + version: 0.0.0-use.local + resolution: "@test-plugins/grafana-e2etest-panel@workspace:e2e-playwright/test-plugins/grafana-test-panel" + dependencies: + "@emotion/css": "npm:11.11.2" + "@grafana/data": "workspace:*" + "@grafana/i18n": "workspace:*" + "@grafana/plugin-configs": "workspace:*" + "@grafana/runtime": "workspace:*" + "@grafana/schema": "workspace:*" + "@grafana/ui": "workspace:*" + "@types/lodash": "npm:4.17.7" + "@types/node": "npm:24.9.2" + "@types/prismjs": "npm:1.26.4" + "@types/react": "npm:18.3.18" + "@types/react-dom": "npm:18.3.5" + "@types/semver": "npm:7.5.8" + "@types/uuid": "npm:9.0.8" + glob: "npm:10.4.1" + i18next-cli: "npm:^1.24.22" react: "npm:18.3.1" react-dom: "npm:18.3.1" react-router-dom: "npm:^6.22.0" @@ -19231,7 +19437,7 @@ __metadata: "@grafana/llm": "npm:0.22.1" "@grafana/monaco-logql": "npm:^0.0.8" "@grafana/o11y-ds-frontend": "workspace:*" - "@grafana/plugin-e2e": "npm:^3.0.1" + "@grafana/plugin-e2e": "npm:^3.0.3" "@grafana/plugin-ui": "npm:^0.11.1" "@grafana/prometheus": "workspace:*" "@grafana/runtime": "workspace:*" @@ -19262,6 +19468,8 @@ __metadata: "@playwright/test": "npm:1.56.1" "@pmmmwh/react-refresh-webpack-plugin": "npm:0.6.1" "@popperjs/core": "npm:2.11.8" + "@rc-component/slider": "npm:1.0.1" + "@rc-component/tree": "npm:1.1.0" "@react-aria/dialog": "npm:3.5.31" "@react-aria/focus": "npm:3.21.2" "@react-aria/overlays": "npm:3.30.0" @@ -19472,8 +19680,6 @@ __metadata: prismjs: "npm:1.30.0" prom-client: "npm:^15.1.3" publint: "npm:^0.3.12" - rc-slider: "npm:11.1.9" - rc-tree: "npm:5.13.1" re-resizable: "npm:6.11.2" react: "npm:18.3.1" react-diff-viewer-continued: "npm:^3.4.0" @@ -21135,6 +21341,13 @@ __metadata: languageName: node linkType: hard +"is-mobile@npm:^5.0.0": + version: 5.0.0 + resolution: "is-mobile@npm:5.0.0" + checksum: 10/426f6bacfffa4166e9af49a915f3389d27c4cbc5cdce1585c3f5f11a0c2983c6d3d2c739985c32f948c0fe4f6b66fc88f71d8f79802608be232d799a27615a37 + languageName: node + linkType: hard + "is-module@npm:^1.0.0": version: 1.0.0 resolution: "is-module@npm:1.0.0" @@ -27932,23 +28145,7 @@ __metadata: languageName: node linkType: hard -"rc-drawer@npm:7.3.0": - version: 7.3.0 - resolution: "rc-drawer@npm:7.3.0" - dependencies: - "@babel/runtime": "npm:^7.23.9" - "@rc-component/portal": "npm:^1.1.1" - classnames: "npm:^2.2.6" - rc-motion: "npm:^2.6.1" - rc-util: "npm:^5.38.1" - peerDependencies: - react: ">=16.9.0" - react-dom: ">=16.9.0" - checksum: 10/99dd1dd51abd21ae1b7b12a1f32a1509fac5d1d9e4719b77e5354cae98fe14fb21dde382c9552cdb21fba07505d3bfbab490b04fb97df709f4efe0b352f129e1 - languageName: node - linkType: hard - -"rc-motion@npm:^2.0.0, rc-motion@npm:^2.0.1, rc-motion@npm:^2.6.1": +"rc-motion@npm:^2.0.0, rc-motion@npm:^2.0.1": version: 2.6.2 resolution: "rc-motion@npm:2.6.2" dependencies: @@ -27977,37 +28174,7 @@ __metadata: languageName: node linkType: hard -"rc-picker@npm:4.11.3": - version: 4.11.3 - resolution: "rc-picker@npm:4.11.3" - dependencies: - "@babel/runtime": "npm:^7.24.7" - "@rc-component/trigger": "npm:^2.0.0" - classnames: "npm:^2.2.1" - rc-overflow: "npm:^1.3.2" - rc-resize-observer: "npm:^1.4.0" - rc-util: "npm:^5.43.0" - peerDependencies: - date-fns: ">= 2.x" - dayjs: ">= 1.x" - luxon: ">= 3.x" - moment: ">= 2.x" - react: ">=16.9.0" - react-dom: ">=16.9.0" - peerDependenciesMeta: - date-fns: - optional: true - dayjs: - optional: true - luxon: - optional: true - moment: - optional: true - checksum: 10/e1e3236338e2ff0d0fa6fcde568457f7dd6ad13a88d870db8fca1de39f452463c26be71a565c1ee7557a2a109bb4737816b8a729f404169403daec8f8a014fff - languageName: node - linkType: hard - -"rc-resize-observer@npm:^1.0.0, rc-resize-observer@npm:^1.3.1, rc-resize-observer@npm:^1.4.0": +"rc-resize-observer@npm:^1.0.0, rc-resize-observer@npm:^1.3.1": version: 1.4.3 resolution: "rc-resize-observer@npm:1.4.3" dependencies: @@ -28040,36 +28207,7 @@ __metadata: languageName: node linkType: hard -"rc-slider@npm:11.1.9": - version: 11.1.9 - resolution: "rc-slider@npm:11.1.9" - dependencies: - "@babel/runtime": "npm:^7.10.1" - classnames: "npm:^2.2.5" - rc-util: "npm:^5.36.0" - peerDependencies: - react: ">=16.9.0" - react-dom: ">=16.9.0" - checksum: 10/b9b1c5b9e690db565a09fde0d6cc9b8562cbb15dd8a0d1eb0a7039c4fcb6c4307ba1cb58047322b8be518a6eb226af9db5c7d974d6ff197fe07f0db84d56cc5e - languageName: node - linkType: hard - -"rc-tooltip@npm:6.4.0": - version: 6.4.0 - resolution: "rc-tooltip@npm:6.4.0" - dependencies: - "@babel/runtime": "npm:^7.11.2" - "@rc-component/trigger": "npm:^2.0.0" - classnames: "npm:^2.3.1" - rc-util: "npm:^5.44.3" - peerDependencies: - react: ">=16.9.0" - react-dom: ">=16.9.0" - checksum: 10/3d0502136f352fda261827974aa08c46d7ace4b7b246940cecea87fe6a1a7c360f0897c233be7ea8aeddcb1aef4e20fdac081356e8dfdf0e4c176a56b5bbc79b - languageName: node - linkType: hard - -"rc-tree@npm:5.13.1, rc-tree@npm:~5.13.0": +"rc-tree@npm:~5.13.0": version: 5.13.1 resolution: "rc-tree@npm:5.13.1" dependencies: @@ -28085,7 +28223,7 @@ __metadata: languageName: node linkType: hard -"rc-util@npm:^5.15.0, rc-util@npm:^5.16.1, rc-util@npm:^5.21.0, rc-util@npm:^5.24.4, rc-util@npm:^5.36.0, rc-util@npm:^5.37.0, rc-util@npm:^5.38.0, rc-util@npm:^5.38.1, rc-util@npm:^5.43.0, rc-util@npm:^5.44.1, rc-util@npm:^5.44.3": +"rc-util@npm:^5.15.0, rc-util@npm:^5.16.1, rc-util@npm:^5.21.0, rc-util@npm:^5.24.4, rc-util@npm:^5.37.0, rc-util@npm:^5.38.0, rc-util@npm:^5.43.0, rc-util@npm:^5.44.1": version: 5.44.3 resolution: "rc-util@npm:5.44.3" dependencies: