Compare commits

...

13 Commits

Author SHA1 Message Date
Jev Forsberg
ccd7b6ce7e Chore: Add bash to dagger env and fix rgm tag step (#108349)
Some checks failed
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
CodeQL checks / Analyze (actions) (push) Has been cancelled
CodeQL checks / Analyze (go) (push) Has been cancelled
CodeQL checks / Analyze (javascript) (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Integration Tests / Sqlite (1/8) (push) Has been cancelled
Integration Tests / Sqlite (2/8) (push) Has been cancelled
Integration Tests / Sqlite (3/8) (push) Has been cancelled
Integration Tests / Sqlite (4/8) (push) Has been cancelled
Integration Tests / Sqlite (5/8) (push) Has been cancelled
Integration Tests / Sqlite (6/8) (push) Has been cancelled
Integration Tests / Sqlite (7/8) (push) Has been cancelled
Integration Tests / Sqlite (8/8) (push) Has been cancelled
Integration Tests / MySQL (1/8) (push) Has been cancelled
Integration Tests / MySQL (2/8) (push) Has been cancelled
Integration Tests / MySQL (3/8) (push) Has been cancelled
Integration Tests / MySQL (4/8) (push) Has been cancelled
Integration Tests / MySQL (5/8) (push) Has been cancelled
Integration Tests / MySQL (6/8) (push) Has been cancelled
Integration Tests / MySQL (7/8) (push) Has been cancelled
Integration Tests / MySQL (8/8) (push) Has been cancelled
Integration Tests / Postgres (1/8) (push) Has been cancelled
Integration Tests / Postgres (2/8) (push) Has been cancelled
Integration Tests / Postgres (3/8) (push) Has been cancelled
Integration Tests / Postgres (4/8) (push) Has been cancelled
Integration Tests / Postgres (5/8) (push) Has been cancelled
Integration Tests / Postgres (6/8) (push) Has been cancelled
Integration Tests / Postgres (7/8) (push) Has been cancelled
Integration Tests / Postgres (8/8) (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Betterer (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / dashboards-suite (push) Has been cancelled
End-to-end tests / panels-suite (push) Has been cancelled
End-to-end tests / smoke-tests-suite (push) Has been cancelled
End-to-end tests / various-suite (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Unit tests (1 / 8) (push) Has been cancelled
Frontend tests / Unit tests (2 / 8) (push) Has been cancelled
Frontend tests / Unit tests (3 / 8) (push) Has been cancelled
Frontend tests / Unit tests (4 / 8) (push) Has been cancelled
Frontend tests / Unit tests (5 / 8) (push) Has been cancelled
Frontend tests / Unit tests (6 / 8) (push) Has been cancelled
Frontend tests / Unit tests (7 / 8) (push) Has been cancelled
Frontend tests / Unit tests (8 / 8) (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
baldm0mma/ add bash and fix rgm tag step
2025-07-18 14:18:43 -06:00
grafana-delivery-bot[bot]
1fdeca1015 [release-12.1.0] Security: Fixes for CVE-2025-6197 and CVE-2025-6023 (#108333)
Some checks failed
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
CodeQL checks / Analyze (actions) (push) Has been cancelled
CodeQL checks / Analyze (go) (push) Has been cancelled
CodeQL checks / Analyze (javascript) (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Betterer (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / dashboards-suite (push) Has been cancelled
End-to-end tests / panels-suite (push) Has been cancelled
End-to-end tests / smoke-tests-suite (push) Has been cancelled
End-to-end tests / various-suite (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Unit tests (1 / 8) (push) Has been cancelled
Frontend tests / Unit tests (2 / 8) (push) Has been cancelled
Frontend tests / Unit tests (3 / 8) (push) Has been cancelled
Frontend tests / Unit tests (4 / 8) (push) Has been cancelled
Frontend tests / Unit tests (5 / 8) (push) Has been cancelled
Frontend tests / Unit tests (6 / 8) (push) Has been cancelled
Frontend tests / Unit tests (7 / 8) (push) Has been cancelled
Frontend tests / Unit tests (8 / 8) (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Integration Tests / Sqlite (1/8) (push) Has been cancelled
Integration Tests / Sqlite (2/8) (push) Has been cancelled
Integration Tests / Sqlite (3/8) (push) Has been cancelled
Integration Tests / Sqlite (4/8) (push) Has been cancelled
Integration Tests / Sqlite (5/8) (push) Has been cancelled
Integration Tests / Sqlite (6/8) (push) Has been cancelled
Integration Tests / Sqlite (7/8) (push) Has been cancelled
Integration Tests / Sqlite (8/8) (push) Has been cancelled
Integration Tests / MySQL (1/8) (push) Has been cancelled
Integration Tests / MySQL (2/8) (push) Has been cancelled
Integration Tests / MySQL (3/8) (push) Has been cancelled
Integration Tests / MySQL (4/8) (push) Has been cancelled
Integration Tests / MySQL (5/8) (push) Has been cancelled
Integration Tests / MySQL (6/8) (push) Has been cancelled
Integration Tests / MySQL (7/8) (push) Has been cancelled
Integration Tests / MySQL (8/8) (push) Has been cancelled
Integration Tests / Postgres (1/8) (push) Has been cancelled
Integration Tests / Postgres (2/8) (push) Has been cancelled
Integration Tests / Postgres (3/8) (push) Has been cancelled
Integration Tests / Postgres (4/8) (push) Has been cancelled
Integration Tests / Postgres (5/8) (push) Has been cancelled
Integration Tests / Postgres (6/8) (push) Has been cancelled
Integration Tests / Postgres (7/8) (push) Has been cancelled
Integration Tests / Postgres (8/8) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
Security: Fixes for CVE-2025-6197 and CVE-2025-6023 (#108330)

apply security patch: main/439-202506251632.patch

(cherry picked from commit 7f3977c54548dc82d9b2c44c125b30b3dbc2069a)


(cherry picked from commit 4669b586e9)

Co-authored-by: Misi <mgyongyosi@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-07-18 16:24:10 +01:00
grafana-delivery-bot[bot]
6be2d4128f [release-12.1.0] Chore: Update supported versions doc (#108234)
Some checks failed
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Betterer (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / dashboards-suite (push) Has been cancelled
End-to-end tests / panels-suite (push) Has been cancelled
End-to-end tests / smoke-tests-suite (push) Has been cancelled
End-to-end tests / various-suite (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Unit tests (1 / 8) (push) Has been cancelled
Frontend tests / Unit tests (2 / 8) (push) Has been cancelled
Frontend tests / Unit tests (3 / 8) (push) Has been cancelled
Frontend tests / Unit tests (4 / 8) (push) Has been cancelled
Frontend tests / Unit tests (5 / 8) (push) Has been cancelled
Frontend tests / Unit tests (6 / 8) (push) Has been cancelled
Frontend tests / Unit tests (7 / 8) (push) Has been cancelled
Frontend tests / Unit tests (8 / 8) (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Integration Tests / Sqlite (1/8) (push) Has been cancelled
Integration Tests / Sqlite (2/8) (push) Has been cancelled
Integration Tests / Sqlite (3/8) (push) Has been cancelled
Integration Tests / Sqlite (4/8) (push) Has been cancelled
Integration Tests / Sqlite (5/8) (push) Has been cancelled
Integration Tests / Sqlite (6/8) (push) Has been cancelled
Integration Tests / Sqlite (7/8) (push) Has been cancelled
Integration Tests / Sqlite (8/8) (push) Has been cancelled
Integration Tests / MySQL (1/8) (push) Has been cancelled
Integration Tests / MySQL (2/8) (push) Has been cancelled
Integration Tests / MySQL (3/8) (push) Has been cancelled
Integration Tests / MySQL (4/8) (push) Has been cancelled
Integration Tests / MySQL (5/8) (push) Has been cancelled
Integration Tests / MySQL (6/8) (push) Has been cancelled
Integration Tests / MySQL (7/8) (push) Has been cancelled
Integration Tests / MySQL (8/8) (push) Has been cancelled
Integration Tests / Postgres (1/8) (push) Has been cancelled
Integration Tests / Postgres (2/8) (push) Has been cancelled
Integration Tests / Postgres (3/8) (push) Has been cancelled
Integration Tests / Postgres (4/8) (push) Has been cancelled
Integration Tests / Postgres (5/8) (push) Has been cancelled
Integration Tests / Postgres (6/8) (push) Has been cancelled
Integration Tests / Postgres (7/8) (push) Has been cancelled
Integration Tests / Postgres (8/8) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
publish-technical-documentation-release / sync (push) Has been cancelled
Co-authored-by: Jev Forsberg <46619047+baldm0mma@users.noreply.github.com>
2025-07-17 14:03:08 +01:00
grafana-delivery-bot[bot]
1194671ac0 [release-12.1.0] Docs: Remove references to DD feature toggle (#108183)
Some checks failed
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Betterer (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / dashboards-suite (push) Has been cancelled
End-to-end tests / panels-suite (push) Has been cancelled
End-to-end tests / smoke-tests-suite (push) Has been cancelled
End-to-end tests / various-suite (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Unit tests (1 / 8) (push) Has been cancelled
Frontend tests / Unit tests (2 / 8) (push) Has been cancelled
Frontend tests / Unit tests (3 / 8) (push) Has been cancelled
Frontend tests / Unit tests (4 / 8) (push) Has been cancelled
Frontend tests / Unit tests (5 / 8) (push) Has been cancelled
Frontend tests / Unit tests (6 / 8) (push) Has been cancelled
Frontend tests / Unit tests (7 / 8) (push) Has been cancelled
Frontend tests / Unit tests (8 / 8) (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Integration Tests / Sqlite (1/8) (push) Has been cancelled
Integration Tests / Sqlite (2/8) (push) Has been cancelled
Integration Tests / Sqlite (3/8) (push) Has been cancelled
Integration Tests / Sqlite (4/8) (push) Has been cancelled
Integration Tests / Sqlite (5/8) (push) Has been cancelled
Integration Tests / Sqlite (6/8) (push) Has been cancelled
Integration Tests / Sqlite (7/8) (push) Has been cancelled
Integration Tests / Sqlite (8/8) (push) Has been cancelled
Integration Tests / MySQL (1/8) (push) Has been cancelled
Integration Tests / MySQL (2/8) (push) Has been cancelled
Integration Tests / MySQL (3/8) (push) Has been cancelled
Integration Tests / MySQL (4/8) (push) Has been cancelled
Integration Tests / MySQL (5/8) (push) Has been cancelled
Integration Tests / MySQL (6/8) (push) Has been cancelled
Integration Tests / MySQL (7/8) (push) Has been cancelled
Integration Tests / MySQL (8/8) (push) Has been cancelled
Integration Tests / Postgres (1/8) (push) Has been cancelled
Integration Tests / Postgres (2/8) (push) Has been cancelled
Integration Tests / Postgres (3/8) (push) Has been cancelled
Integration Tests / Postgres (4/8) (push) Has been cancelled
Integration Tests / Postgres (5/8) (push) Has been cancelled
Integration Tests / Postgres (6/8) (push) Has been cancelled
Integration Tests / Postgres (7/8) (push) Has been cancelled
Integration Tests / Postgres (8/8) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
publish-technical-documentation-release / sync (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com>
2025-07-16 10:29:35 -04:00
grafana-delivery-bot[bot]
bd602fd6d9 [release-12.1.0] Docs: Update actions with variables (#108151)
Some checks failed
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Betterer (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / dashboards-suite (push) Has been cancelled
End-to-end tests / panels-suite (push) Has been cancelled
End-to-end tests / smoke-tests-suite (push) Has been cancelled
End-to-end tests / various-suite (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Unit tests (1 / 8) (push) Has been cancelled
Frontend tests / Unit tests (2 / 8) (push) Has been cancelled
Frontend tests / Unit tests (3 / 8) (push) Has been cancelled
Frontend tests / Unit tests (4 / 8) (push) Has been cancelled
Frontend tests / Unit tests (5 / 8) (push) Has been cancelled
Frontend tests / Unit tests (6 / 8) (push) Has been cancelled
Frontend tests / Unit tests (7 / 8) (push) Has been cancelled
Frontend tests / Unit tests (8 / 8) (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Integration Tests / Sqlite (1/8) (push) Has been cancelled
Integration Tests / Sqlite (2/8) (push) Has been cancelled
Integration Tests / Sqlite (3/8) (push) Has been cancelled
Integration Tests / Sqlite (4/8) (push) Has been cancelled
Integration Tests / Sqlite (5/8) (push) Has been cancelled
Integration Tests / Sqlite (6/8) (push) Has been cancelled
Integration Tests / Sqlite (7/8) (push) Has been cancelled
Integration Tests / Sqlite (8/8) (push) Has been cancelled
Integration Tests / MySQL (1/8) (push) Has been cancelled
Integration Tests / MySQL (2/8) (push) Has been cancelled
Integration Tests / MySQL (3/8) (push) Has been cancelled
Integration Tests / MySQL (4/8) (push) Has been cancelled
Integration Tests / MySQL (5/8) (push) Has been cancelled
Integration Tests / MySQL (6/8) (push) Has been cancelled
Integration Tests / MySQL (7/8) (push) Has been cancelled
Integration Tests / MySQL (8/8) (push) Has been cancelled
Integration Tests / Postgres (1/8) (push) Has been cancelled
Integration Tests / Postgres (2/8) (push) Has been cancelled
Integration Tests / Postgres (3/8) (push) Has been cancelled
Integration Tests / Postgres (4/8) (push) Has been cancelled
Integration Tests / Postgres (5/8) (push) Has been cancelled
Integration Tests / Postgres (6/8) (push) Has been cancelled
Integration Tests / Postgres (7/8) (push) Has been cancelled
Integration Tests / Postgres (8/8) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
publish-technical-documentation-release / sync (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
Co-authored-by: Adela Almasan <88068998+adela-almasan@users.noreply.github.com>
2025-07-15 15:36:41 -04:00
Jack Baldry
f1c1311961 Revert "Docs: Reporting redesign docs (#105078)" (#108136) 2025-07-15 16:53:36 +01:00
grafana-delivery-bot[bot]
ea7eb59bac [release-12.1.0] Docs: Fix format of quick_ranges (#108133)
Some checks failed
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Betterer (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / dashboards-suite (push) Has been cancelled
End-to-end tests / panels-suite (push) Has been cancelled
End-to-end tests / smoke-tests-suite (push) Has been cancelled
End-to-end tests / various-suite (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Unit tests (1 / 8) (push) Has been cancelled
Frontend tests / Unit tests (2 / 8) (push) Has been cancelled
Frontend tests / Unit tests (3 / 8) (push) Has been cancelled
Frontend tests / Unit tests (4 / 8) (push) Has been cancelled
Frontend tests / Unit tests (5 / 8) (push) Has been cancelled
Frontend tests / Unit tests (6 / 8) (push) Has been cancelled
Frontend tests / Unit tests (7 / 8) (push) Has been cancelled
Frontend tests / Unit tests (8 / 8) (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Integration Tests / Sqlite (1/8) (push) Has been cancelled
Integration Tests / Sqlite (2/8) (push) Has been cancelled
Integration Tests / Sqlite (3/8) (push) Has been cancelled
Integration Tests / Sqlite (4/8) (push) Has been cancelled
Integration Tests / Sqlite (5/8) (push) Has been cancelled
Integration Tests / Sqlite (6/8) (push) Has been cancelled
Integration Tests / Sqlite (7/8) (push) Has been cancelled
Integration Tests / Sqlite (8/8) (push) Has been cancelled
Integration Tests / MySQL (1/8) (push) Has been cancelled
Integration Tests / MySQL (2/8) (push) Has been cancelled
Integration Tests / MySQL (3/8) (push) Has been cancelled
Integration Tests / MySQL (4/8) (push) Has been cancelled
Integration Tests / MySQL (5/8) (push) Has been cancelled
Integration Tests / MySQL (6/8) (push) Has been cancelled
Integration Tests / MySQL (7/8) (push) Has been cancelled
Integration Tests / MySQL (8/8) (push) Has been cancelled
Integration Tests / Postgres (1/8) (push) Has been cancelled
Integration Tests / Postgres (2/8) (push) Has been cancelled
Integration Tests / Postgres (3/8) (push) Has been cancelled
Integration Tests / Postgres (4/8) (push) Has been cancelled
Integration Tests / Postgres (5/8) (push) Has been cancelled
Integration Tests / Postgres (6/8) (push) Has been cancelled
Integration Tests / Postgres (7/8) (push) Has been cancelled
Integration Tests / Postgres (8/8) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
publish-technical-documentation-release / sync (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
Co-authored-by: Josh Hunt <joshhunt@users.noreply.github.com>
Fix format of quick_ranges (#107973)
2025-07-15 16:42:59 +02:00
grafana-delivery-bot[bot]
0b985cfd8d [release-12.1.0] Alerting: Fix flakey test for group loader (#108038)
Alerting: Fix flakey test for group loader (#107909)

(cherry picked from commit 889cf57055)

Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
2025-07-11 19:12:22 +01:00
grafana-delivery-bot[bot]
7d65c5c2a6 [release-12.1.0] docs: Clarifying the support level of SCIM (#108040)
Co-authored-by: Jacob Valdez <jacob.valdez@grafana.com>
2025-07-11 13:09:58 -05:00
Stephanie Hingtgen
df07305465 Revert: Future-proofing query and data source model in Dashboard Sche… (#107985)
Some checks failed
CodeQL checks / Analyze (actions) (push) Has been cancelled
CodeQL checks / Analyze (go) (push) Has been cancelled
CodeQL checks / Analyze (javascript) (push) Has been cancelled
* Revert: Future-proofing query and data source model in Dashboard Schema v2

---------

Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
2025-07-10 15:13:14 -05:00
Stephanie Hingtgen
f25d2fe7e2 Revert "Schema V2: Simplify annotations v1<->v2 conversions" (#107984)
Revert "Schema V2: Simplify annotations v1<->v2 conversions (#107390)"

This reverts commit d5a1781fb6.
2025-07-10 15:13:13 -05:00
Gabriel MABILLE
0417533b61 iam: add description field to roles (#107888)
* iam: add description field to roles

* Openapi gen

* Revert launch change
2025-07-10 15:13:13 -05:00
Nathan Verzemnieks
6d4a443aaf Prometheus: use patched grafana-aws-sdk middleware for panic handling 2025-07-10 18:59:18 +02:00
63 changed files with 1037 additions and 2532 deletions

View File

@@ -193,7 +193,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
@@ -661,7 +661,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
@@ -1757,7 +1757,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- export GRAFANA_DIR=$$(pwd)
- export GITHUB_TOKEN=$(cat /github-app/token)
- ./pkg/build/daggerbuild/scripts/drone_build_main.sh
@@ -1831,13 +1831,30 @@ platform:
os: linux
services: []
steps:
- commands:
- echo $(/usr/bin/github-app-external-token) > /github-app/token
environment:
GITHUB_APP_ID:
from_secret: github-app-app-id
GITHUB_APP_INSTALLATION_ID:
from_secret: github-app-installation-id
GITHUB_APP_PRIVATE_KEY:
from_secret: github-app-private-key
failure: ignore
image: us-docker.pkg.dev/grafanalabs-global/docker-deployment-tools-prod/github-app-secret-writer:2024-11-05-v11688112090.1-83920c59
name: github-app-generate-token
volumes:
- name: github-app
path: /github-app
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- export GRAFANA_DIR=$$(pwd)
- export GITHUB_TOKEN=$(cat /github-app/token)
- ./pkg/build/daggerbuild/scripts/drone_build_tag_grafana.sh
depends_on:
- github-app-generate-token
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
@@ -1889,6 +1906,10 @@ volumes:
- host:
path: /var/run/docker.sock
name: docker
- name: github-app
path: /github-app
- name: github-app
temp: {}
---
clone:
retries: 3
@@ -1953,7 +1974,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- export GRAFANA_DIR=$$(pwd)
- export GITHUB_TOKEN=$(cat /github-app/token)
- ./pkg/build/daggerbuild/scripts/drone_build_tag_grafana.sh
@@ -2060,7 +2081,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- export GRAFANA_DIR=$$(pwd)
- export GITHUB_TOKEN=$(cat /github-app/token)
- ./pkg/build/daggerbuild/scripts/drone_build_nightly_grafana.sh
@@ -2204,7 +2225,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- export GRAFANA_DIR=$$(pwd)
- export GITHUB_TOKEN=$(cat /github-app/token)
- ./pkg/build/daggerbuild/scripts/drone_publish_nightly_grafana.sh
@@ -2333,7 +2354,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- export GITHUB_TOKEN=$(cat /github-app/token)
- dagger run --silent go run ./pkg/build/cmd artifacts -a $${ARTIFACTS} --grafana-ref=$${GRAFANA_REF}
--enterprise-ref=$${ENTERPRISE_REF} --grafana-repo=$${GRAFANA_REPO} --build-id=$${DRONE_BUILD_NUMBER}
@@ -2986,6 +3007,6 @@ kind: secret
name: gcr_credentials
---
kind: signature
hmac: 1198b1489e48a9ced211633a0325d112814553246847fc7320fb5ac2bcb32b7d
hmac: dce4ef9b8d45f32e1b2153b8418f668144325ed9fc0c51f2f8245fb091a4cba2
...

View File

@@ -19,6 +19,9 @@ update-app-sdk: ## Update the Grafana App SDK dependency in go.mod
go mod tidy
.PHONY: generate
generate: install-app-sdk update-app-sdk
generate: do-generate ## Run Grafana App SDK code generation
.PHONY: do-generate
do-generate: install-app-sdk update-app-sdk
## --defencoding=none and noschemasinmanifest are needed to avoid infinite loop while generating recursive models (see routingtree.cue)
@$(APP_SDK_BIN) generate --grouping=group --gogenpath=./pkg/apis --defencoding=none --postprocess --noschemasinmanifest

View File

@@ -1,4 +1,4 @@
APP_SDK_VERSION := v0.39.2
APP_SDK_VERSION := v0.39.0
APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION)
APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk

View File

@@ -111,8 +111,6 @@ DashboardLink: {
keepTime: bool | *false
}
// Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec
// This type is widely used in the codebase and changing it will have a big impact
DataSourceRef: {
// The plugin type-id
type?: string
@@ -387,14 +385,15 @@ VizConfigKind: {
}
AnnotationQuerySpec: {
query: DataQueryKind
datasource?: DataSourceRef
query?: DataQueryKind
enable: bool
hide: bool
iconColor: string
name: string
builtIn?: bool | *false
filter?: AnnotationPanelFilter
legacyOptions?: [string]: _ // Catch-all field for datasource-specific properties. Should not be available in as code tooling.
legacyOptions?: [string]: _ //Catch-all field for datasource-specific properties
}
AnnotationQueryKind: {
@@ -413,19 +412,15 @@ QueryOptionsSpec: {
}
DataQueryKind: {
kind: "DataQuery"
group: string
version: string | *"v0"
// New type for datasource reference
// Not 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.
datasource?: {
name?: string
}
// The kind of a DataQueryKind is the datasource type
kind: string
spec: [string]: _
}
PanelQuerySpec: {
query: DataQueryKind
datasource?: DataSourceRef
refId: string
hidden: bool
}
@@ -728,6 +723,7 @@ QueryVariableSpec: {
refresh: VariableRefresh
skipUrlSync: bool | *false
description?: string
datasource?: DataSourceRef
query: DataQueryKind
regex: string | *""
sort: VariableSort

View File

@@ -115,8 +115,6 @@ DashboardLink: {
keepTime: bool | *false
}
// Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec
// This type is widely used in the codebase and changing it will have a big impact
DataSourceRef: {
// The plugin type-id
type?: string
@@ -391,14 +389,15 @@ VizConfigKind: {
}
AnnotationQuerySpec: {
query: DataQueryKind
datasource?: DataSourceRef
query?: DataQueryKind
enable: bool
hide: bool
iconColor: string
name: string
builtIn?: bool | *false
filter?: AnnotationPanelFilter
legacyOptions?: [string]: _ // Catch-all field for datasource-specific properties. Should not be available in as code tooling.
legacyOptions?: [string]: _ //Catch-all field for datasource-specific properties
}
AnnotationQueryKind: {
@@ -417,19 +416,15 @@ QueryOptionsSpec: {
}
DataQueryKind: {
kind: "DataQuery"
group: string
version: string | *"v0"
// New type for datasource reference
// Not 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.
datasource?: {
name?: string
}
// The kind of a DataQueryKind is the datasource type
kind: string
spec: [string]: _
}
PanelQuerySpec: {
query: DataQueryKind
datasource?: DataSourceRef
refId: string
hidden: bool
}
@@ -732,6 +727,7 @@ QueryVariableSpec: {
refresh: VariableRefresh
skipUrlSync: bool | *false
description?: string
datasource?: DataSourceRef
query: DataQueryKind
regex: string | *""
sort: VariableSort

View File

@@ -23,42 +23,49 @@ func NewDashboardAnnotationQueryKind() *DashboardAnnotationQueryKind {
// +k8s:openapi-gen=true
type DashboardAnnotationQuerySpec struct {
Query DashboardDataQueryKind `json:"query"`
Enable bool `json:"enable"`
Hide bool `json:"hide"`
IconColor string `json:"iconColor"`
Name string `json:"name"`
BuiltIn *bool `json:"builtIn,omitempty"`
Filter *DashboardAnnotationPanelFilter `json:"filter,omitempty"`
// Catch-all field for datasource-specific properties. Should not be available in as code tooling.
Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
Query *DashboardDataQueryKind `json:"query,omitempty"`
Enable bool `json:"enable"`
Hide bool `json:"hide"`
IconColor string `json:"iconColor"`
Name string `json:"name"`
BuiltIn *bool `json:"builtIn,omitempty"`
Filter *DashboardAnnotationPanelFilter `json:"filter,omitempty"`
// Catch-all field for datasource-specific properties
LegacyOptions map[string]interface{} `json:"legacyOptions,omitempty"`
}
// NewDashboardAnnotationQuerySpec creates a new DashboardAnnotationQuerySpec object.
func NewDashboardAnnotationQuerySpec() *DashboardAnnotationQuerySpec {
return &DashboardAnnotationQuerySpec{
Query: *NewDashboardDataQueryKind(),
BuiltIn: (func(input bool) *bool { return &input })(false),
}
}
// +k8s:openapi-gen=true
type DashboardDataSourceRef struct {
// The plugin type-id
Type *string `json:"type,omitempty"`
// Specific datasource instance
Uid *string `json:"uid,omitempty"`
}
// NewDashboardDataSourceRef creates a new DashboardDataSourceRef object.
func NewDashboardDataSourceRef() *DashboardDataSourceRef {
return &DashboardDataSourceRef{}
}
// +k8s:openapi-gen=true
type DashboardDataQueryKind struct {
Kind string `json:"kind"`
Group string `json:"group"`
Version string `json:"version"`
// New type for datasource reference
// Not 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.
Datasource *DashboardV2alpha1DataQueryKindDatasource `json:"datasource,omitempty"`
Spec map[string]interface{} `json:"spec"`
// The kind of a DataQueryKind is the datasource type
Kind string `json:"kind"`
Spec map[string]interface{} `json:"spec"`
}
// NewDashboardDataQueryKind creates a new DashboardDataQueryKind object.
func NewDashboardDataQueryKind() *DashboardDataQueryKind {
return &DashboardDataQueryKind{
Kind: "DataQuery",
Version: "v0",
Spec: map[string]interface{}{},
Spec: map[string]interface{}{},
}
}
@@ -192,9 +199,10 @@ func NewDashboardPanelQueryKind() *DashboardPanelQueryKind {
// +k8s:openapi-gen=true
type DashboardPanelQuerySpec struct {
Query DashboardDataQueryKind `json:"query"`
RefId string `json:"refId"`
Hidden bool `json:"hidden"`
Query DashboardDataQueryKind `json:"query"`
Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
RefId string `json:"refId"`
Hidden bool `json:"hidden"`
}
// NewDashboardPanelQuerySpec creates a new DashboardPanelQuerySpec object.
@@ -755,9 +763,7 @@ type DashboardRepeatOptions struct {
// NewDashboardRepeatOptions creates a new DashboardRepeatOptions object.
func NewDashboardRepeatOptions() *DashboardRepeatOptions {
return &DashboardRepeatOptions{
Mode: DashboardRepeatMode,
}
return &DashboardRepeatOptions{}
}
// other repeat modes will be added in the future: label, frame
@@ -932,9 +938,7 @@ type DashboardRowRepeatOptions struct {
// NewDashboardRowRepeatOptions creates a new DashboardRowRepeatOptions object.
func NewDashboardRowRepeatOptions() *DashboardRowRepeatOptions {
return &DashboardRowRepeatOptions{
Mode: DashboardRepeatMode,
}
return &DashboardRowRepeatOptions{}
}
// +k8s:openapi-gen=true
@@ -1007,9 +1011,7 @@ type DashboardAutoGridRepeatOptions struct {
// NewDashboardAutoGridRepeatOptions creates a new DashboardAutoGridRepeatOptions object.
func NewDashboardAutoGridRepeatOptions() *DashboardAutoGridRepeatOptions {
return &DashboardAutoGridRepeatOptions{
Mode: DashboardRepeatMode,
}
return &DashboardAutoGridRepeatOptions{}
}
// +k8s:openapi-gen=true
@@ -1075,9 +1077,7 @@ type DashboardTabRepeatOptions struct {
// NewDashboardTabRepeatOptions creates a new DashboardTabRepeatOptions object.
func NewDashboardTabRepeatOptions() *DashboardTabRepeatOptions {
return &DashboardTabRepeatOptions{
Mode: DashboardRepeatMode,
}
return &DashboardTabRepeatOptions{}
}
// Links with references to other dashboards or external resources
@@ -1221,6 +1221,7 @@ type DashboardQueryVariableSpec struct {
Refresh DashboardVariableRefresh `json:"refresh"`
SkipUrlSync bool `json:"skipUrlSync"`
Description *string `json:"description,omitempty"`
Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
Query DashboardDataQueryKind `json:"query"`
Regex string `json:"regex"`
Sort DashboardVariableSort `json:"sort"`
@@ -1626,21 +1627,6 @@ func NewDashboardGroupByVariableSpec() *DashboardGroupByVariableSpec {
}
}
// Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec
// This type is widely used in the codebase and changing it will have a big impact
// +k8s:openapi-gen=true
type DashboardDataSourceRef struct {
// The plugin type-id
Type *string `json:"type,omitempty"`
// Specific datasource instance
Uid *string `json:"uid,omitempty"`
}
// NewDashboardDataSourceRef creates a new DashboardDataSourceRef object.
func NewDashboardDataSourceRef() *DashboardDataSourceRef {
return &DashboardDataSourceRef{}
}
// Adhoc variable kind
// +k8s:openapi-gen=true
type DashboardAdhocVariableKind struct {
@@ -1701,9 +1687,7 @@ type DashboardAdHocFilterWithLabels struct {
// NewDashboardAdHocFilterWithLabels creates a new DashboardAdHocFilterWithLabels object.
func NewDashboardAdHocFilterWithLabels() *DashboardAdHocFilterWithLabels {
return &DashboardAdHocFilterWithLabels{
Origin: DashboardFilterOrigin,
}
return &DashboardAdHocFilterWithLabels{}
}
// Determine the origin of the adhoc variable filter
@@ -1774,16 +1758,6 @@ func NewDashboardSpec() *DashboardSpec {
}
}
// +k8s:openapi-gen=true
type DashboardV2alpha1DataQueryKindDatasource struct {
Name *string `json:"name,omitempty"`
}
// NewDashboardV2alpha1DataQueryKindDatasource creates a new DashboardV2alpha1DataQueryKindDatasource object.
func NewDashboardV2alpha1DataQueryKindDatasource() *DashboardV2alpha1DataQueryKindDatasource {
return &DashboardV2alpha1DataQueryKindDatasource{}
}
// +k8s:openapi-gen=true
type DashboardV2alpha1FieldConfigSourceOverrides struct {
Matcher DashboardMatcherConfig `json:"matcher"`

View File

@@ -109,7 +109,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardTimeRangeOption": schema_pkg_apis_dashboard_v2alpha1_DashboardTimeRangeOption(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardTimeSettingsSpec": schema_pkg_apis_dashboard_v2alpha1_DashboardTimeSettingsSpec(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardTransformationKind": schema_pkg_apis_dashboard_v2alpha1_DashboardTransformationKind(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1DataQueryKindDatasource": schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1DataQueryKindDatasource(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1FieldConfigSourceOverrides": schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1FieldConfigSourceOverrides(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1RangeMapOptions": schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1RangeMapOptions(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1RegexMapOptions": schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1RegexMapOptions(ref),
@@ -596,10 +595,14 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardAnnotationQuerySpec(ref common.
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"datasource": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"),
},
},
"query": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"),
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"),
},
},
"enable": {
@@ -643,7 +646,7 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardAnnotationQuerySpec(ref common.
},
"legacyOptions": {
SchemaProps: spec.SchemaProps{
Description: "Catch-all field for datasource-specific properties. Should not be available in as code tooling.",
Description: "Catch-all field for datasource-specific properties",
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
@@ -657,11 +660,11 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardAnnotationQuerySpec(ref common.
},
},
},
Required: []string{"query", "enable", "hide", "iconColor", "name"},
Required: []string{"enable", "hide", "iconColor", "name"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardAnnotationPanelFilter", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"},
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardAnnotationPanelFilter", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"},
}
}
@@ -1502,29 +1505,10 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardDataQueryKind(ref common.Refere
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"group": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"version": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"datasource": {
SchemaProps: spec.SchemaProps{
Description: "New type for datasource reference Not 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.",
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1DataQueryKindDatasource"),
Description: "The kind of a DataQueryKind is the datasource type",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"spec": {
@@ -1542,11 +1526,9 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardDataQueryKind(ref common.Refere
},
},
},
Required: []string{"kind", "group", "version", "spec"},
Required: []string{"kind", "spec"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1DataQueryKindDatasource"},
}
}
@@ -1554,8 +1536,7 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardDataSourceRef(ref common.Refere
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec This type is widely used in the codebase and changing it will have a big impact",
Type: []string{"object"},
Type: []string{"object"},
Properties: map[string]spec.Schema{
"type": {
SchemaProps: spec.SchemaProps{
@@ -2909,6 +2890,11 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardPanelQuerySpec(ref common.Refer
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"),
},
},
"datasource": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"),
},
},
"refId": {
SchemaProps: spec.SchemaProps{
Default: "",
@@ -2928,7 +2914,7 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardPanelQuerySpec(ref common.Refer
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"},
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"},
}
}
@@ -3264,6 +3250,11 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardQueryVariableSpec(ref common.Re
Format: "",
},
},
"datasource": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"),
},
},
"query": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
@@ -3341,7 +3332,7 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardQueryVariableSpec(ref common.Re
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardVariableOption"},
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardVariableOption"},
}
}
@@ -4329,24 +4320,6 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardTransformationKind(ref common.R
}
}
func schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1DataQueryKindDatasource(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{
Type: []string{"string"},
Format: "",
},
},
},
},
},
}
}
func schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1FieldConfigSourceOverrides(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{

View File

@@ -10,6 +10,7 @@ RoleSpec: {
// Display name of the role
title: string
description: string
version: int
group: string

View File

@@ -18,9 +18,10 @@ func NewCoreRolespecPermission() *CoreRolespecPermission {
// +k8s:openapi-gen=true
type CoreRoleSpec struct {
// Display name of the role
Title string `json:"title"`
Version int64 `json:"version"`
Group string `json:"group"`
Title string `json:"title"`
Description string `json:"description"`
Version int64 `json:"version"`
Group string `json:"group"`
// TODO:
// delegatable?: bool
// created?

View File

@@ -18,9 +18,10 @@ func NewGlobalRolespecPermission() *GlobalRolespecPermission {
// +k8s:openapi-gen=true
type GlobalRoleSpec struct {
// Display name of the role
Title string `json:"title"`
Version int64 `json:"version"`
Group string `json:"group"`
Title string `json:"title"`
Description string `json:"description"`
Version int64 `json:"version"`
Group string `json:"group"`
// TODO:
// delegatable?: bool
// created?

View File

@@ -18,9 +18,10 @@ func NewRolespecPermission() *RolespecPermission {
// +k8s:openapi-gen=true
type RoleSpec struct {
// Display name of the role
Title string `json:"title"`
Version int64 `json:"version"`
Group string `json:"group"`
Title string `json:"title"`
Description string `json:"description"`
Version int64 `json:"version"`
Group string `json:"group"`
// TODO:
// delegatable?: bool
// created?

View File

@@ -186,6 +186,13 @@ func schema_pkg_apis_iam_v0alpha1_CoreRoleSpec(ref common.ReferenceCallback) com
Format: "",
},
},
"description": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"version": {
SchemaProps: spec.SchemaProps{
Default: 0,
@@ -215,7 +222,7 @@ func schema_pkg_apis_iam_v0alpha1_CoreRoleSpec(ref common.ReferenceCallback) com
},
},
},
Required: []string{"title", "version", "group", "permissions"},
Required: []string{"title", "description", "version", "group", "permissions"},
},
},
Dependencies: []string{
@@ -740,6 +747,13 @@ func schema_pkg_apis_iam_v0alpha1_GlobalRoleSpec(ref common.ReferenceCallback) c
Format: "",
},
},
"description": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"version": {
SchemaProps: spec.SchemaProps{
Default: 0,
@@ -769,7 +783,7 @@ func schema_pkg_apis_iam_v0alpha1_GlobalRoleSpec(ref common.ReferenceCallback) c
},
},
},
Required: []string{"title", "version", "group", "permissions"},
Required: []string{"title", "description", "version", "group", "permissions"},
},
},
Dependencies: []string{
@@ -1600,6 +1614,13 @@ func schema_pkg_apis_iam_v0alpha1_RoleSpec(ref common.ReferenceCallback) common.
Format: "",
},
},
"description": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"version": {
SchemaProps: spec.SchemaProps{
Default: 0,
@@ -1629,7 +1650,7 @@ func schema_pkg_apis_iam_v0alpha1_RoleSpec(ref common.ReferenceCallback) common.
},
},
},
Required: []string{"title", "version", "group", "permissions"},
Required: []string{"title", "description", "version", "group", "permissions"},
},
},
Dependencies: []string{

View File

@@ -14,6 +14,8 @@ import (
v0alpha1 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1"
)
var ()
var appManifestData = app.ManifestData{
AppName: "iam",
Group: "iam.grafana.app",

View File

@@ -1,257 +0,0 @@
{
"kind": "Dashboard",
"apiVersion": "dashboard.grafana.app/v1beta1",
"metadata": {
"name": "test-v1-annotations",
"annotations": {
"hello": "world"
},
"labels": {
"region": "west"
}
},
"spec": {
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": false,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & 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"
}
},
{
"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"
}
},
{
"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": [
{
"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,
"links": [],
"panels": [
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "PD8C576611E62080A"
},
"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"
}
},
"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.1.0-pre",
"targets": [
{
"refId": "A"
}
],
"title": "New panel",
"type": "timeseries"
}
],
"preload": false,
"schemaVersion": 41,
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "browser",
"title": "Test: V1 dashboard with annotations",
"version": 8
}
}

View File

@@ -10,44 +10,14 @@
"kind": "AnnotationQuery",
"spec": {
"builtIn": true,
"enable": true,
"filter": {
"exclude": false,
"ids": [1]
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations \u0026 Alerts",
"query": {
"group": "grafana",
"kind": "DataQuery",
"spec": {},
"version": "v0"
}
}
},
{
"kind": "AnnotationQuery",
"spec": {
"query": {
"kind": "DataQuery",
"group": "grafana-testdata-datasource",
"version": "v0",
"spec": {
"lines": 10,
"refId": "Anno",
"scenarioId": "annotations"
}
},
"enable": true,
"hide": false,
"iconColor": "red",
"name": "Test data annotations",
"builtIn": false,
"filter": {
"exclude": false,
"ids": [1]
}
"name": "Annotations \u0026 Alerts"
}
}
],
@@ -67,16 +37,8 @@
"spec": {
"hidden": false,
"query": {
"datasource": {
"name": "gdev-testdata"
},
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {
"scenarioId": "random_walk",
"seriesCount": 3
},
"version": "v0"
"kind": "grafana-testdata-datasource",
"spec": {}
},
"refId": "A"
}
@@ -89,7 +51,7 @@
"description": "",
"id": 1,
"links": [],
"title": "Simple timeseries (WITH DS REF)",
"title": "Simle timeseries",
"vizConfig": {
"kind": "timeseries",
"spec": {
@@ -131,12 +93,12 @@
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
"color": "green"
},
{
"color": "red",
@@ -160,7 +122,7 @@
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
"pluginVersion": "12.0.0-pre"
}
}
}
@@ -177,13 +139,8 @@
"spec": {
"hidden": false,
"query": {
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {
"scenarioId": "random_walk",
"seriesCount": 4
},
"version": "v0"
"kind": "grafana-testdata-datasource",
"spec": {}
},
"refId": "A"
}
@@ -196,7 +153,7 @@
"description": "",
"id": 2,
"links": [],
"title": "Simple stat (NO DS REF)",
"title": "Simple stat",
"vizConfig": {
"kind": "stat",
"spec": {
@@ -205,12 +162,12 @@
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
"color": "green"
},
{
"color": "red",
@@ -236,496 +193,7 @@
"textMode": "auto",
"wideLayout": true
},
"pluginVersion": "12.1.0-pre"
}
}
}
},
"panel-3": {
"kind": "Panel",
"spec": {
"data": {
"kind": "QueryGroup",
"spec": {
"queries": [
{
"kind": "PanelQuery",
"spec": {
"hidden": false,
"query": {
"group": "prometheus",
"kind": "DataQuery",
"spec": {
"disableTextWrap": false,
"editorMode": "builder",
"expr": "rate(counters_requests[$__rate_interval])",
"fullMetaSearch": false,
"includeNullMetadata": false,
"instant": false,
"legendFormat": "__auto",
"range": true,
"useBackend": false
},
"version": "v0"
},
"refId": "A"
}
}
],
"queryOptions": {},
"transformations": []
}
},
"description": "",
"id": 3,
"links": [],
"title": "Panel with NO REF to gdev-prometheus",
"vizConfig": {
"kind": "timeseries",
"spec": {
"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
}
]
}
},
"overrides": []
},
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
}
}
}
},
"panel-4": {
"kind": "Panel",
"spec": {
"data": {
"kind": "QueryGroup",
"spec": {
"queries": [
{
"kind": "PanelQuery",
"spec": {
"hidden": false,
"query": {
"datasource": {
"name": "gdev-prometheus"
},
"group": "prometheus",
"kind": "DataQuery",
"spec": {
"disableTextWrap": false,
"editorMode": "builder",
"expr": "rate(counters_requests[$__rate_interval])",
"fullMetaSearch": false,
"includeNullMetadata": false,
"instant": false,
"legendFormat": "__auto",
"range": true,
"useBackend": false
},
"version": "v0"
},
"refId": "A"
}
}
],
"queryOptions": {},
"transformations": []
}
},
"description": "",
"id": 4,
"links": [],
"title": "Panel with ref to gdev-prometheus",
"vizConfig": {
"kind": "timeseries",
"spec": {
"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
}
]
}
},
"overrides": []
},
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
}
}
}
},
"panel-5": {
"kind": "Panel",
"spec": {
"data": {
"kind": "QueryGroup",
"spec": {
"queries": [
{
"kind": "PanelQuery",
"spec": {
"hidden": false,
"query": {
"datasource": {
"name": "gdev-prometheus"
},
"group": "prometheus",
"kind": "DataQuery",
"spec": {
"disableTextWrap": false,
"editorMode": "builder",
"expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])",
"fullMetaSearch": false,
"includeNullMetadata": false,
"legendFormat": "__auto",
"range": true,
"useBackend": false
},
"version": "v0"
},
"refId": "A"
}
},
{
"kind": "PanelQuery",
"spec": {
"hidden": false,
"query": {
"datasource": {
"name": "gdev-testdata"
},
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
"version": "v0"
},
"refId": "B"
}
}
],
"queryOptions": {},
"transformations": []
}
},
"description": "",
"id": 5,
"links": [],
"title": "Mixed DS WITH REFS",
"vizConfig": {
"kind": "timeseries",
"spec": {
"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
}
]
}
},
"overrides": []
},
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
}
}
}
},
"panel-6": {
"kind": "Panel",
"spec": {
"data": {
"kind": "QueryGroup",
"spec": {
"queries": [
{
"kind": "PanelQuery",
"spec": {
"hidden": false,
"query": {
"group": "prometheus",
"kind": "DataQuery",
"spec": {
"disableTextWrap": false,
"editorMode": "builder",
"expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])",
"fullMetaSearch": false,
"includeNullMetadata": false,
"legendFormat": "__auto",
"range": true,
"useBackend": false
},
"version": "v0"
},
"refId": "A"
}
},
{
"kind": "PanelQuery",
"spec": {
"hidden": false,
"query": {
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
"version": "v0"
},
"refId": "B"
}
}
],
"queryOptions": {},
"transformations": []
}
},
"description": "",
"id": 6,
"links": [],
"title": "Mixed DS WITHOUT REFS",
"vizConfig": {
"kind": "timeseries",
"spec": {
"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
}
]
}
},
"overrides": []
},
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
"pluginVersion": "12.0.0-pre"
}
}
}
@@ -736,24 +204,6 @@
"spec": {
"columnWidthMode": "standard",
"items": [
{
"kind": "AutoGridLayoutItem",
"spec": {
"element": {
"kind": "ElementReference",
"name": "panel-3"
}
}
},
{
"kind": "AutoGridLayoutItem",
"spec": {
"element": {
"kind": "ElementReference",
"name": "panel-4"
}
}
},
{
"kind": "AutoGridLayoutItem",
"spec": {
@@ -771,24 +221,6 @@
"name": "panel-1"
}
}
},
{
"kind": "AutoGridLayoutItem",
"spec": {
"element": {
"kind": "ElementReference",
"name": "panel-5"
}
}
},
{
"kind": "AutoGridLayoutItem",
"spec": {
"element": {
"kind": "ElementReference",
"name": "panel-6"
}
}
}
],
"maxColumnCount": 3,
@@ -803,7 +235,7 @@
"autoRefresh": "",
"autoRefreshIntervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
"fiscalYearStartMonth": 0,
"from": "now-5m",
"from": "now-6h",
"hideTimepicker": false,
"timezone": "browser",
"to": "now"

View File

@@ -78,18 +78,10 @@ refs:
# Create and manage reports
{{< admonition type="note" >}}
The redesigned reporting feature is currently in public preview. Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available. To use this feature, enable the `newShareReportDrawer` feature toggle in your Grafana configuration file or, for Grafana Cloud, contact Support.
{{< /admonition >}}
**Reporting** allows you to send automated and scheduled emails from any of your dashboards.
You can configure several elements of these reports and generate PDFs and CSV files.
You can configure several elements of these reports and generate PDFs, CSV files, and embedded images.
Any changes you make to a dashboard used in a report are reflected the next time the report is sent.
{{< figure src="/media/docs/grafana/dashboards/screenshot-report-config-v12.0.png" max-width="600px" alt="The report configuration screen" >}}
## Requirements
For Grafana Enterprise, the Reporting feature has the following requirements:
@@ -116,89 +108,28 @@ Refer to specific guides to understand what permissions are required.
## Create a report
The report creation process is multi-step, but you don't need to complete these steps in order.
The report creation process is multi-step, but you don't need to complete these steps in order and you can skip steps by clicking a step name at the top of the page.
You can also save the report as a draft at any point during the initial creation process.
You can also save the report as a draft at any step in the process:
You can create directly from a dashboard or from the **Reporting** page.
Select one of the following tabs for directions on each option.
![Reporting wizard](/media/docs/grafana/dashboards/screenshot-reporting-wizard-v11.5.png)
To create a report, follow these steps:
{{< tabs >}}
{{< tab-content name="Create a report directly from a dashboard" >}}
1. In the main menu, click **Dashboards**.
1. Navigate to the dashboard from which you want to create a report.
1. Click the **Share** drop-down list in the top-right corner of the dashboard.
1. Click **Schedule report**.
The **Schedule report** drawer opens. Any other reports using this dashboard are listed in the drawer. You can also click **See all reports** to navigate to **Reporting** for a full list of reports generated from all dashboards.
1. Click **+ Create a new report**.
1. Update the name of the report, if needed.
By default, the report name is the name of the dashboard.
1. Expand and complete each section of the report, as needed:
- [Dashboards](#1-dashboards)
- [Schedule](#2-schedule)
- [Email settings](#3-email-settings)
- [Recipients](#4-recipients)
- [Attachments](#5-attachments)
1. Click one of the following buttons at the bottom of the **Schedule report** drawer:
- The menu icon to access the following options:
- **Download CSV**
- **Preview PDF**
- **Report settings** - Takes you to **Reporting** in a new browser tab and opens the **Report template settings** drawer, where you can configure organization-level report settings.
- **Send preview** - Send a preview of the report to your desired recipient. You can choose to use the report recipients:
{{< figure src="/media/docs/grafana/dashboards/screenshot-send-preview-v12.0.png" max-width="350px" alt="The Send preview modal" >}}
- **Schedule report** - The report is sent according the schedule you've set.
- **Save draft** - You can save a draft at any point during the initial report creation process, even if it's missing required fields. The report won't be sent according to its schedule while it's a draft.
If you click the **x** at the top of the drawer without scheduling or saving the report as a draft, the report is discarded. This action can't be reversed.
1. When you finish configuring the report, click the **x** at the top of the **Schedule report** drawer to close it.
{{< /tab-content >}}
{{< tab-content name="Create a report from Reporting" >}}
1. In the main menu, click **Dashboards > Reporting**.
1. Click **+ Create a new report**.
1. Complete the report steps, as needed:
- [Select dashboard](#1-select-dashboard)
- [Format report](#2-format-report)
- [Schedule](#3-schedule)
- [Share](#4-share)
- [Confirm](#5-confirm)
1. Click one of the following buttons in the top-right corner of the screen:
- **Send now** or **Schedule send** - The report is sent according the schedule you've set.
- **Save as draft** - You can save a draft at any point during the report creation or update process, even if it's missing required fields. The report won't be sent according to its schedule while it's a draft.
- **Discard** - Delete the report draft. This action can't be reversed.
The **Schedule report** drawer opens.
1. Enter a name for the report.
1. Expand and complete each section of the report, as needed:
- [Dashboards](#1-dashboards)
- [Schedule](#2-schedule)
- [Email settings](#3-email-settings)
- [Recipients](#4-recipients)
- [Attachments](#5-attachments)
1. Click one of the following buttons at the bottom of the **Schedule report** drawer:
- The menu icon to access the following options:
- **Download CSV**
- **Preview PDF**
- **Report settings** - Opens the **Report template settings** drawer, where you can configure organization-level report settings.
- **Send preview** - Send a preview of the report to your desired recipient. You can choose to use the report recipients:
{{< figure src="/media/docs/grafana/dashboards/screenshot-send-preview-v12.0.png" max-width="350px" alt="The Send preview modal" >}}
- **Schedule report** - The report is sent according the schedule you've set.
- **Save draft** - Save a draft at any point during the initial report creation process, even if it's missing required fields. The report won't be sent according to its schedule while it's a draft.
If you click the **x** at the top of the drawer without scheduling or saving the report as a draft, the report is discarded. This action can't be reversed.
1. When you finish configuring the report, click the **x** at the top of the **Schedule report** drawer to close it.
{{< /tab-content >}}
{{< /tabs >}}
### 1. Dashboards
### 1. Select dashboard
At this step, select the dashboard or dashboards on which the report is based, as well as the variables and time ranges for those dashboards.
The options are:
@@ -207,53 +138,35 @@ The options are:
| Option | Description |
| ------ | ----------- |
| Source dashboard (required) | Select or update the dashboard from which you want to generate the report. If you've created your report directly from a dashboard, this field is already filled in with the name of the current dashboard. |
| [Time range](#time-range) | Update the report time range. If you've created the report directly from a dashboard, the default time range is that of the dashboard. Otherwise, the default time range is **Last 6 hours**. |
| [Customize template variables](#customize-template-variables) | Select and customize the variable values for the selected dashboard. This section is only displayed if the dashboard has variables. |
| + Add dashboard | Add more dashboards to the report. |
| Source dashboard (required) | Select the dashboard from which you want to generate the report. |
| [Template variables](#template-variables) | Select the variable values for the selected dashboard. This option is only displayed if the dashboard has variables. |
| [Time range](#time-range) | If you leave the field empty, reports use the saved time range of the dashboard. Optionally, you can change the time range of the report. |
| Add another dashboard | Add more dashboards to the report. |
<!-- prettier-ignore-end -->
#### Template variables
This option is only displayed if the dashboard has variables.
You can configure report-specific template variables for the dashboard on the report page.
The variables that you select override the variables from the dashboard.
For detailed information about using template variables, refer to [Variables](ref:templates-and-variables).
The query variables saved with a report might become out-of-date if the results of that query change.
For example, if your template variable queries for a list of hostnames and a new hostname is added, then it won't be included in the report.
If that occurs, the selected variables must be manually updated in the report.
If you select the **All** value for the template variable or if you keep the dashboard's original variable selection, then the report stays up-to-date as new values are added.
#### Time range
If you leave the **Time range** field empty, reports use the saved time range of the dashboard.
Optionally, you can change the time range of the report by setting it in the **Time range** field.
If specified, the custom time range overrides the time range from the report's dashboard.
#### Customize template variables
The page header of the report displays the time range for the dashboard's data queries.
Configure report-specific template variables for the dashboard.
The variables that you select override the variables from the dashboard.
For detailed information about using template variables, refer to [Variables](ref:templates-and-variables).
The query variables saved with a report might become out of date if the results of that query change.
For example, if your template variable queries for a list of hostnames and a new hostname is added, then it won't be included in the report.
If that occurs, the selected variables must be manually updated in the report.
If you select the **All** value for the template variable or if you keep the dashboard's original variable selection, then the report stays up-to-date as new values are added.
This option is only displayed if the dashboard has variables.
### 2. Schedule
At this step, set scheduling information.
Options vary depending on the frequency you select.
<!-- prettier-ignore-start -->
| Option | Description |
| ------ | ----------- |
| Schedule | Choose one of the following:<ul><li>**Send now** sends the report immediately after you save it. To stop sending the report at some point in the future, add an end date.</li><li>**Send later** schedules a report for a later date. When you select this option, the required **Start date**, **Start time**, and **Time zone** options are displayed.</li></ul> |
| Frequency | You can schedule reports to be sent once, repeated on an hourly, daily, weekly, or monthly basis, or sent at custom intervals. |
| Start date | Set the date when the report should start being sent. |
| Start time | Set the time when the report should start being sent. |
| [Time zone](#time-zone) | Set the time zone of the report. |
| End date | Set the date when the report should stop being sent. If you leave this field empty, the report is sent out indefinitely. |
| Send only from Monday to Friday | For reports that have an hourly or daily frequency, you can choose to send them only from Monday to Friday. |
| Send on the last day of the month | When you schedule a report with a monthly frequency, and set the start date between the 29th and the 31st of the month, the report is only sent during the months that have those dates. If you want the report to be sent every month, select the **Send on the last day of the month** option. This way, the report is sent on the last day of every month regardless of how many days there are in the month. |
<!-- prettier-ignore-end -->
#### Time zone
##### Report time zones
Reports use the time zone of the dashboard from which they're generated.
You can control the time zone for your reports by setting the dashboard to a specific time zone.
@@ -265,54 +178,34 @@ If you want to use a specific time zone, save the dashboard with a fixed time zo
Each dashboard's time zone setting is visible in the [time range controls](ref:time-range-controls).
### 3. Email settings
### 2. Format report
At this step, configure the report email:
<!-- vale Grafana.GoogleLyHyphens = NO -->
<!-- prettier-ignore-start -->
| Option | Description |
| ------ | ----------- |
| Email subject | If you leave this field empty, the report name is used as the email subject line. |
| Message | The body of the message in the report email. |
| Reply-to-email address | The address that appears in the **Reply to** field of the email. |
| Include a dashboard link | Include links to the dashboards in the report email. |
| Embed dashboard image | The report email is sent with an images of the dashboards embedded in it so recipients see them at a glance. |
<!-- prettier-ignore-end -->
<!-- vale Grafana.GoogleLyHyphens = YES -->
### 4. Recipients
Enter the email addresses of the people or teams that you want to receive the report, separated by commas or semicolons.
### 5. Attachments
At this step, select one or more report attachment options.
At this step, select one or more report formatting options.
You can select multiple options, but you must select _at least one_:
- **Attach the report as a PDF** - Attach the report as one PDF file.
- **[Attach a separate PDF of table data](#table-data-in-pdf)** - Attach a separate PDF file to the report email for each table panel on the selected dashboard. Public preview only.
- **Attach a CSV file of table panel data** - Attach a CSV file to the report email for each table panel on the selected dashboard.
- [Attach the report as a PDF](#attach-the-report-as-a-pdf)
- [Include table data as PDF appendix](#table-data-in-pdf) (Public preview only)
- [Embed a dashboard image in the email](#embed-a-dashboard-as-an-image-in-the-email)
- [Attach a CSV file of the table panel data](#attach-a-csv-file-of-the-table-panel-data)
- [Attach a separate PDF of table data](#table-data-in-pdf) (Public preview only)
#### PDF format
#### Attach the report as a PDF
If you selected a PDF attachment, configure the following formatting options:
If you selected the PDF format option under the **Style the PDF** section, you can configure the following options:
<!-- prettier-ignore-start -->
- **Configure multiple PDFs** - Click the **Combine all dashboard PDFs in one file** checkbox if you want to generate one PDF file for all the dashboards included in the report. This option is only displayed if your report includes multiple dashboards.
- **Configure report header** - Click the **Show template variables** checkbox to show dashboard variables.
- **Orientation** - Set the report orientation in **Portrait** or **Landscape**. Refer to the [Layout and orientation table](#layout-and-orientation) to see examples.
- **Layout** - Select one of the following:
| Option | Description |
|---------------------------------|-------------------------------------------------------------------------------------------------|
| Orientation | Set the report orientation in **Portrait** or **Landscape**. Refer to the [Layout and orientation table](#layout-and-orientation) to see examples. |
| Layout | Select one of the following:<ul><li>**Simple** - Renders each panel as full-width across the PDF.</li><li>**Grid** - Renders the PDF with the same panel arrangement and width as the source dashboard.</li></ul>Refer to the [Layout and orientation table](#layout-and-orientation) to see examples. |
| Zoom | Zoom in to enlarge text in your PDF or zoom out to see more data (like table columns) per panel. |
| Combine all dashboard PDFs in one file | Click the checkbox if you want to generate one PDF file for all the dashboards included in the report. This option is only displayed if there are multiple dashboards in the report. |
| Show template variables | Click the checkbox to show dashboard variables. This option is only displayed if the report contains variables. |
| [Include table data as PDF appendix](#table-data-in-pdf) | Add an appendix of the dashboard table data to the report PDF. This is useful when there's more data in your table visualization than can be shown in the dashboard PDF. _Public preview only._ |
<!-- prettier-ignore-end -->
- **Simple** - Renders each panel as full-width across the PDF.
- **Grid** - Renders the PDF with the same panel arrangement and width as the source dashboard.
Refer to the [Layout and orientation table](#layout-and-orientation) to see examples.
- **Zoom** - Zoom in to enlarge text in your PDF, or zoom out to see more data (like table columns) per panel.
Click **Preview PDF** in the top-right corner of the screen to view a rendered PDF with the options you selected.
##### Layout and orientation
@@ -327,6 +220,17 @@ If you selected a PDF attachment, configure the following formatting options:
<!-- prettier-ignore-end -->
#### Embed a dashboard as an image in the email
You can send a report email with an image of the dashboard embedded in the email.
This lets the email recipients see the dashboard at a glance.
#### Attach a CSV file of the table panel data
You can attach a CSV file to the report email for each table panel on the selected dashboard.
Click **Download CSV** in the top-right corner of the screen to download a zipped file of the CSV files for your selected dashboard.
#### Table data in PDF
{{< admonition type="note" >}}
@@ -338,66 +242,94 @@ When there's more data in your table visualizations than can be shown in the das
- **Include table data as PDF appendix** - Adds an appendix to the dashboard PDF.
- **Attach a separate PDF of table data** - Generates a separate PDF file.
### 3. Schedule
At this step, set scheduling information.
Options vary depending on the frequency you select.
<!-- prettier-ignore-start -->
| Option | Description |
| ------ | ----------- |
| Frequency | You can schedule reports to be sent once, or repeated on an hourly, daily, weekly, or monthly basis, or sent at custom intervals. You can also disable scheduling by selecting **Never**. For example, you might want to [send the report using the API](#send-a-report-using-the-api). |
| Time | Choose one of the following:<ul><li>**Send now** sends the report immediately after you save it. To stop sending the report at some point in the future, add an end date.</li><li>**Send later** schedules a report for a later date. When you select this option, the required **Start date**, **Start time**, and **Time zone** options are displayed.</li></ul> |
| End date | If you leave this field empty, the report is sent out indefinitely. |
| Send only from Monday to Friday | For reports that have an hourly or daily frequency, you can choose to send them only from Monday to Friday. |
| Send on the last day of the month | When you schedule a report with a monthly frequency, and set the start date between the 29th and the 31st of the month, the report is only sent during the months that have those dates. If you want the report to be sent every month, select the **Send on the last day of the month** option. This way, the report is sent on the last day of every month regardless of how many days there are in the month. |
<!-- prettier-ignore-end -->
### 4. Share
At this step, enter information related to sharing the report:
<!-- vale Grafana.GoogleLyHyphens = NO -->
<!-- prettier-ignore-start -->
| Option | Description |
| ------ | ----------- |
| Report name (required) | The name of the report as you want it to appear in the **Reports** list. The report name also populates the email subject line. |
| Recipients (required) | Enter the email addresses of the people or teams that you want to receive the report, separated by commas or semicolons. |
| Reply-to email address | The address that appears in the **Reply to** field of the email. |
| Message | The body of the message in the email with the report. |
| Include a dashboard link | Include a links to the dashboards in the report email. |
<!-- prettier-ignore-end -->
<!-- vale Grafana.GoogleLyHyphens = YES -->
Click **Send test email** in the top-right corner of the screen to verify that the configuration works as expected and to verify that emails are working.
You can choose to send this email to the recipients configured for the report, or to a different set of email addresses only used for testing.
### 5. Confirm
At this step, the confirmation page displays all the report settings.
Review them and confirm that they're correct or click the provided **Edit** links for each section to make updates.
Then, click **Send now** or **Schedule send**.
You can also save the report as a draft or discard it. Discarding the report is irreversible.
## Send a report using the API
You can send reports programmatically with the [send report](ref:send-report) endpoint using the HTTP API.
## Manage reports
You can view and manage all your reports, and create new ones, on the **Reporting** page:
On the **Reports** page, you can view and manage your existing reports or create new ones.
{{< figure src="/media/docs/grafana/dashboards/screenshot-reporting-page-v12.0.png" max-width="750px" alt="The Reporting page" >}}
Alternatively, from any dashboard you can view and manage any reports generated from that dashboard, as well as create a new report
You can also navigate to the list of all reports from the dashboard-specific list:
{{< figure src="/media/docs/grafana/dashboards/screenshot-report-drawer-v12.0.png" max-width="750px" alt="The open Report schedule drawer with an existing report" >}}
![Reports page](/media/docs/grafana/dashboards/screenshot-reports-page-v11.5.png)
### Edit reports
To edit a report, follow these steps:
1. Do one of the following:
- In the main menu, click **Dashboards > Reporting**.
- Navigate to the dashboard from which the report was generated and click **Share > Schedule report**.
1. In the main menu, click **Dashboards > Reporting**.
1. Click the row of the report you want to update.
1. Make the necessary changes.
1. Click the **Edit report** button in the top-right hand corner or click the **Edit** link for a specific section to go to that one directly.
1. When you've finished making changes, click **Confirm** at the top of the screen to go to the last step.
1. Click **Update report**.
1. Click the **x** at the top of the drawer to close it.
### Pause or resume reports
### Pause or resume reports {#pause-a-report}
You can pause and resume sending reports from the report list view.
To do this, follow these steps:
1. Do one of the following:
- In the main menu, click **Dashboards > Reporting**.
- Navigate to the dashboard from which the report was generated and click **Share > Schedule report**.
1. In the main menu, click **Dashboards > Reporting**.
1. On the row of the report you want to update, do one of the following:
- Click the pause icon - The report won't be sent according to its schedule until it's resumed.
- Click the resume icon - The report resumes on its previous schedule.
You can also pause or resume a report from **Update report** drawer.
### Delete reports
To delete a report, follow these steps:
1. Do one of the following:
- In the main menu, click **Dashboards > Reporting**.
- Navigate to the dashboard from which the report was generated and click **Share > Schedule report**.
1. In the main menu, click **Dashboards > Reporting**.
1. On the row of the report you want to update, click the trash can icon.
1. Click **Delete** to confirm.
You can also delete a report from **Update report** drawer.
Deleting a report is irreversible.
## Troubleshoot Reporting

View File

@@ -21,19 +21,8 @@ refs:
# Reporting settings
You can configure organization-wide report settings and branding options in **Dashboards > Reporting**.
These settings are applied to all the reports for the current organization.
To access the settings, go to **Dashboards > Reporting** and click the **Report settings** button.
This opens the **Report template settings** drawer, where you can make changes.
{{< admonition type="note" >}}
The redesigned reporting feature, including the report settings drawer, is currently in public preview. Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available. To use this feature, enable the `newShareReportDrawer` feature toggle in your Grafana configuration file or, for Grafana Cloud, contact Support.
{{< /admonition >}}
You can also navigate these settings from the **Schedule report** drawer that opens when you create a report directly from a dashboard.
You can configure organization-wide report settings and branding options in **Dashboards > Reporting > Settings**.
Settings are applied to all the reports for the current organization.
## Attachment settings

View File

@@ -20,7 +20,7 @@ weight: 200
{{< admonition type="caution" >}}
Dashboard JSON schema v2 is an experimental feature. Engineering and on-call support is not available. Documentation is either limited or not provided outside of code comments. No SLA is provided. Enable the `dashboardNewLayouts` feature toggle in Grafana to use this feature.
Dashboard JSON schema v2 is an [experimental](https://grafana.com/docs/release-life-cycle/) feature. Engineering and on-call support is not available. Documentation is either limited or not provided outside of code comments. No SLA is provided. To get early access to this feature, request it through [this form](https://docs.google.com/forms/d/e/1FAIpQLSd73nQzuhzcHJOrLFK4ef_uMxHAQiPQh1-rsQUT2MRqbeMLpg/viewform?usp=dialog).
**Do not enable this feature in production environments as it may result in the irreversible loss of data.**
@@ -32,7 +32,8 @@ Observability as Code works with all versions of the JSON model, and it's fully
## Before you begin
Schema v2 is automatically enabled with the Dynamic Dashboards feature toggle, `dashboardNewLayouts`.
Schema v2 is automatically enabled with the Dynamic Dashboards feature toggle.
To get early access to this feature, request it through [this form](https://docs.google.com/forms/d/e/1FAIpQLSd73nQzuhzcHJOrLFK4ef_uMxHAQiPQh1-rsQUT2MRqbeMLpg/viewform?usp=dialog).
It also requires the new dashboards API feature toggle, `kubernetesDashboards`, to be enabled as well.
For more information on how dashboards behave depending on your feature flag configuration, refer to [Notes and limitations](#notes-and-limitations).
@@ -217,18 +218,18 @@ Upon saving, theyll be updated to the new schema where you can take advantage
### Dashboard behavior with disabled feature flags
If you disable the `dashboardNewLayouts` or `kubernetesDashboards` feature flags, you should be aware of how dashboards will behave.
If you disable the Dynamic dashboards or `kubernetesDashboards` feature flags, you should be aware of how dashboards will behave.
#### Disable `dashboardNewLayouts`
#### Disable Dynamic dashboards
If `dashboardNewLayouts` feature toggle is disabled, depending on how the dashboard was built, it will behave differently:
If the Dynamic dashboards feature toggle is disabled, depending on how the dashboard was built, it will behave differently:
- Dashboards built on the new schema through the UI - View only
- Dashboards built on Schema v1 - View and edit
- Dashboards built on the new schema by way of Terraform or the CLI - View and edit
- Provisioned dashboards built on the new schema - View and edit, but the edit experience will be the old experience
#### Disable `dashboardNewLayouts` and `kubernetesDashboards`
#### Disable Dynamic dashboards and `kubernetesDashboards`
Youll be unable to view or edit dashboards created or updated in the new schema.

View File

@@ -2838,22 +2838,14 @@ For example:
```ini
[time_picker]
quick_ranges = [
{
"display": "Last 5 minutes",
"from": "now-5m",
"to": "now",
},
{
"display": "Yesterday",
"from": "now-1d/d",
},
{
"display": "Today so far",
"from": "now/d",
"to": "now",
}
]
quick_ranges = """[
{"from":"now-6s","to":"now","display":"Last 6 seconds"},
{"from":"now-10m","to":"now","display":"Last 10 minutes"},
{"from":"now-25h","to":"now","display":"Last 24 hours"},
{"from":"now/w","to":"now/w","display":"This week"},
{"from":"now-1w/w","to":"now-1w/w","display":"Last week"},
{"from":"now-10d","to":"now","display":"Last 10 days"}
]"""
```
### `[expressions]`

View File

@@ -20,7 +20,8 @@ weight: 300
System for Cross-domain Identity Management (SCIM) is an open standard that allows automated user provisioning and management. With SCIM, you can automate the provisioning of users and groups from your identity provider to Grafana.
{{< admonition type="note" >}}
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/) in [public preview](https://grafana.com/docs/release-life-cycle/).
Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
{{< /admonition >}}
{{< admonition type="note" >}}

View File

@@ -26,6 +26,7 @@ For each action, define the following API call settings:
| Confirmation message | A descriptive prompt to confirm or cancel the action. |
| Method | Select from **POST**, **PUT**, or **GET**. |
| URL | The request URL.</p><p>To add a variable, click in the **URL** field and enter `$` or press Ctrl+Space or Cmd+Space to see a list of available variables. |
| Variables | **Key** and **Name** pairs with a type selection. Click the **+** icon to add as many variables as you need. To add a variable to the request, prefix the key with `$`. You can set the values for the variables when performing an action. |
| Query parameters | **Key** and **Value** pairs. Click the **+** icon to add as many key/value pairs as you need. |
| Headers | Comprised of **Key** and **Value** pairs and a **Content-Type**.</p><p>Click the **+** icon to add as many key/value pairs as you need. |
| Content-Type | Select from the following: **application/json**, **text/plain**, **application/XML**, and **application/x-www-form-urlencoded**. |

View File

@@ -28,6 +28,7 @@ For each action, define the following API call settings:
| Confirmation message | A descriptive prompt to confirm or cancel the action. |
| Method | Select from **POST**, **PUT**, or **GET**. |
| URL | The request URL.</p><p>To add a variable, click in the **URL** field and enter `$` or press Ctrl+Space or Cmd+Space to see a list of available variables. |
| Variables | **Key** and **Name** pairs with a type selection. Click the **+** icon to add as many variables as you need. To add a variable to the request, prefix the key with `$`. You can set the values for the variables when performing an action. |
| Query parameters | **Key** and **Value** pairs. Click the **+** icon to add as many key/value pairs as you need. |
| Headers | Comprised of **Key** and **Value** pairs and a **Content-Type**.</p><p>Click the **+** icon to add as many key/value pairs as you need. |
| Content-Type | Select from the following: **application/json**, **text/plain**, **application/XML**, and **application/x-www-form-urlencoded**. |

View File

@@ -96,27 +96,24 @@ For self-managed Grafana (both Enterprise and OSS), the support for versions fol
- Each minor release is supported for 9 months after its release date
- The last minor release of a major version receives extended support for 15 months after its release date
- Support levels change as new versions are released:
- **Full Support**: The most recently released major/minor (and the last minor of the previous major) version receive full support including new features, bug fixes, and security patches
- **Security & Critical Bugs Only**: Versions that are not the most recently released major/minor (or the last minor of the previous major) version, but still within their support period, receive only security patches and critical bug fixes
- **Full Support**: The most recently released major/minor version receive full support including new features, bug fixes, and security patches
- **Security & Critical Bugs Only**: Versions that are outside of the most recently released major/minor version, but still within their support period, receive only security patches and critical bug fixes
- **Not Supported**: Versions beyond their support period receive no updates
Here is an overview of version support through 2026:
| **Version** | **Release date** | **Support end date** | **Support level** |
| ------------------------- | ------------------ | -------------------- | ----------------------------- |
| 9.5.x (Last minor of 9) | April 26, 2023 | July 26, 2024 | Supported for Azure Only |
| 10.0.x | June 13, 2023 | March 13, 2024 | Not Supported |
| 10.1.x | August 22, 2023 | May 22, 2024 | Not Supported |
| 10.2.x | October 24, 2023 | July 24, 2024 | Not Supported |
| 10.3.x | January 23, 2024 | October 23, 2024 | Not Supported |
| 10.4.x (Last minor of 10) | March 5, 2024 | June 5, 2025 | Security & Critical Bugs Only |
| 11.0.x | May 14, 2024 | February 14, 2025 | Security & Critical Bugs Only |
| 11.1.x | June 25, 2024 | April 23, 2025 | Security & Critical Bugs Only |
| 11.2.x | August 27, 2024 | May 27, 2025 | Security & Critical Bugs Only |
| 10.4.x (Last minor of 10) | March 5, 2024 | June 5, 2025 | Not Supported |
| 11.0.x | May 14, 2024 | February 14, 2025 | Not Supported |
| 11.1.x | June 25, 2024 | April 23, 2025 | Not Supported |
| 11.2.x | August 27, 2024 | May 27, 2025 | Not Supported |
| 11.3.x | October 22, 2024 | July 22, 2025 | Security & Critical Bugs Only |
| 11.4.x | December 5, 2024 | September 5, 2025 | Security & Critical Bugs Only |
| 11.5.x | January 28, 2025 | October 28, 2025 | Security & Critical Bugs Only |
| 11.6.x (Last minor of 11) | March 25, 2025 | May 25, 2026 | Full Support |
| 11.6.x (Last minor of 11) | March 25, 2025 | May 25, 2026 | Security & Critical Bugs Only |
| 12.0.x | May 5, 2025 | February 5, 2026 | Full Support until next minor |
| 12.1.x | July 22, 2025 | April 22, 2026 | Full Support until next minor |
| 12.2.x | September 23, 2025 | June 23, 2026 | Full Support until next minor |

View File

@@ -2,11 +2,21 @@
"apiVersion": "dashboard.grafana.app/v2alpha1",
"kind": "Dashboard",
"metadata": {
"name": "fa400625-2a44-4add-a369-e6c972eb4bd6",
"name": "admjzp8",
"namespace": "default",
"uid": "hrbekBWXeM7nC7GtouIbcngFyuqt8Xx7KlE4AnTwV7AX",
"resourceVersion": "1",
"generation": 1,
"creationTimestamp": "2025-05-27T11:40:22Z",
"labels": {},
"annotations": {}
"creationTimestamp": "2025-05-16T09:41:56Z",
"labels": {
"grafana.app/deprecatedInternalID": "182"
},
"annotations": {
"grafana.app/createdBy": "user:cejvsh18uudxcf",
"grafana.app/updatedBy": "user:cejvsh18uudxcf",
"grafana.app/updatedTimestamp": "2025-05-16T09:41:56Z",
"grafana.app/folder": ""
}
},
"spec": {
"annotations": [
@@ -14,20 +24,19 @@
"kind": "AnnotationQuery",
"spec": {
"builtIn": true,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"query": {
"group": "grafana",
"kind": "DataQuery",
"spec": {},
"version": "v0"
}
"name": "Annotations & Alerts"
}
}
],
"cursorSync": "Off",
"description": "",
"editable": true,
"elements": {
"panel-1": {
@@ -40,12 +49,14 @@
{
"kind": "PanelQuery",
"spec": {
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "PD8C576611E62080A"
},
"hidden": false,
"query": {
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
"version": "v0"
"kind": "grafana-testdata-datasource",
"spec": {}
},
"refId": "A"
}
@@ -144,12 +155,14 @@
{
"kind": "PanelQuery",
"spec": {
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "PD8C576611E62080A"
},
"hidden": false,
"query": {
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
"version": "v0"
"kind": "grafana-testdata-datasource",
"spec": {}
},
"refId": "A"
}
@@ -248,12 +261,14 @@
{
"kind": "PanelQuery",
"spec": {
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "PD8C576611E62080A"
},
"hidden": false,
"query": {
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
"version": "v0"
"kind": "grafana-testdata-datasource",
"spec": {}
},
"refId": "A"
}
@@ -365,7 +380,7 @@
"spec": {
"element": {
"kind": "ElementReference",
"name": "panel-3"
"name": "panel-2"
},
"height": 8,
"width": 12,
@@ -378,7 +393,7 @@
"spec": {
"element": {
"kind": "ElementReference",
"name": "panel-2"
"name": "panel-3"
},
"height": 8,
"width": 12,
@@ -402,7 +417,7 @@
"timezone": "browser",
"to": "now"
},
"title": "Test V2 Dashboard",
"title": "New Test V2 Dashboard",
"variables": []
},
"status": {}

View File

@@ -17,9 +17,5 @@ export const importV2Dashboard = ({ title }: ImportDashboardConfig) => {
if (title) {
e2e.components.ImportDashboardForm.name().clear().type(title);
}
e2e.components.DataSourcePicker.inputV2().click();
cy.get('div[data-testid="data-source-card"]').first().click();
e2e.components.ImportDashboardForm.submit().click();
};

2
go.mod
View File

@@ -99,7 +99,7 @@ require (
github.com/grafana/grafana-api-golang-client v0.27.0 // @grafana/alerting-backend
github.com/grafana/grafana-app-sdk v0.39.2 // @grafana/grafana-app-platform-squad
github.com/grafana/grafana-app-sdk/logging v0.39.1 // @grafana/grafana-app-platform-squad
github.com/grafana/grafana-aws-sdk v1.0.3 // @grafana/aws-datasources
github.com/grafana/grafana-aws-sdk v1.0.4 // @grafana/aws-datasources
github.com/grafana/grafana-azure-sdk-go/v2 v2.1.6 // @grafana/partner-datasources
github.com/grafana/grafana-cloud-migration-snapshot v1.6.0 // @grafana/grafana-operator-experience-squad
github.com/grafana/grafana-google-sdk-go v0.4.1 // @grafana/partner-datasources

4
go.sum
View File

@@ -1610,8 +1610,8 @@ github.com/grafana/grafana-app-sdk v0.39.2 h1:ymfr+1318t+JC9U2OYrzVpGmNG/aJONUmF
github.com/grafana/grafana-app-sdk v0.39.2/go.mod h1:t0m6q561lpoHQCixS9LUHFUhUzDClzNtm7BH60gHVSY=
github.com/grafana/grafana-app-sdk/logging v0.39.1 h1:lI5rbrheuwVPuyIM6LIuEYOCSpgmXahfKtqeMyhbGPU=
github.com/grafana/grafana-app-sdk/logging v0.39.1/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk=
github.com/grafana/grafana-aws-sdk v1.0.3 h1:FtGiTrdlPXuQmLqeZdyNjjkNKOOdvQ4sxWw8MtJc6ow=
github.com/grafana/grafana-aws-sdk v1.0.3/go.mod h1:hO7q7yWV+t6dmiyJjMa3IbuYnYkBua+G/IAlOPVIYKE=
github.com/grafana/grafana-aws-sdk v1.0.4 h1:D14UAehsOqpjliHmHzveRQ1p43KCsMzdmb7GovWj+SY=
github.com/grafana/grafana-aws-sdk v1.0.4/go.mod h1:hO7q7yWV+t6dmiyJjMa3IbuYnYkBua+G/IAlOPVIYKE=
github.com/grafana/grafana-azure-sdk-go/v2 v2.1.6 h1:OfCkitCuomzZKW1WYHrG8MxKwtMhALb7jqoj+487eTg=
github.com/grafana/grafana-azure-sdk-go/v2 v2.1.6/go.mod h1:V7y2BmsWxS3A9Ohebwn4OiSfJJqi//4JQydQ8fHTduo=
github.com/grafana/grafana-cloud-migration-snapshot v1.6.0 h1:S4kHwr//AqhtL9xHBtz1gqVgZQeCRGTxjgsRBAkpjKY=

View File

@@ -347,6 +347,7 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV
github.com/RaveNoX/go-jsoncommentstrip v1.0.0 h1:t527LHHE3HmiHrq74QMpNPZpGCIJzTx+apLkMKt4HC0=
github.com/RoaringBitmap/gocroaring v0.4.0 h1:5nufXUgWpBEUNEJXw7926YAA58ZAQRpWPrQV1xCoSjc=
github.com/RoaringBitmap/real-roaring-datasets v0.0.0-20190726190000-eb7c87156f76 h1:ZYlhPbqQFU+AHfgtCdHGDTtRW1a8geZyiE8c6Q+Sl1s=
github.com/RoaringBitmap/real-roaring-datasets v0.0.0-20190726190000-eb7c87156f76/go.mod h1:oM0MHmQ3nDsq609SS36p+oYbRi16+oVvU2Bw4Ipv0SE=
github.com/Sereal/Sereal/Go/sereal v0.0.0-20231009093132-b9187f1a92c6 h1:5kUcJJAKWWI82Xnp/CaU0eu5hLlHkmm9acjowSkwCd0=
github.com/Sereal/Sereal/Go/sereal v0.0.0-20231009093132-b9187f1a92c6/go.mod h1:JwrycNnC8+sZPDyzM3MQ86LvaGzSpfxg885KOOwFRW4=
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0=
@@ -570,6 +571,7 @@ github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQ
github.com/envoyproxy/go-control-plane/envoy v1.32.3/go.mod h1:F6hWupPfh75TBXGKA++MCT/CZHFq5r9/uwt/kQYkZfE=
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
github.com/expr-lang/expr v1.17.0/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
@@ -679,6 +681,8 @@ github.com/grafana/alerting v0.0.0-20250403153742-418bc7118d05 h1:hMzOzI/S0nkZt0
github.com/grafana/alerting v0.0.0-20250403153742-418bc7118d05/go.mod h1:K3YAJumchx5EEZItGv4D3pCv/Ux796hmoOibP/p/eYk=
github.com/grafana/alerting v0.0.0-20250429131604-de176b4a0309 h1:H2p3XKDHnTBGkMXLCgXiqb2dFnHbQ4zPDXOwKK4Ne3Y=
github.com/grafana/alerting v0.0.0-20250429131604-de176b4a0309/go.mod h1:pMfhRxL2LZ3Pm8iy7VcVsb9CLYuBtjFYbf1oxgx7yFA=
github.com/grafana/alerting v0.0.0-20250701210250-cea2d1683945 h1:3imTbxFpZSVI6IBIB9mn+Xc40lUweWjfMaBSgXR7rLs=
github.com/grafana/alerting v0.0.0-20250701210250-cea2d1683945/go.mod h1:gtR7agmxVfJOmNKV/n2ZULgOYTYNL+PDKYB5N48tQ7Q=
github.com/grafana/authlib v0.0.0-20250123104008-e99947858901/go.mod h1:/gYfphsNu9v1qYWXxpv1NSvMEMSwvdf8qb8YlgwIRl8=
github.com/grafana/authlib/types v0.0.0-20250120144156-d6737a7dc8f5/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
@@ -693,6 +697,8 @@ github.com/grafana/grafana-app-sdk/logging v0.39.0 h1:3GgN5+dUZYqq74Q+GT9/ET+yo+
github.com/grafana/grafana-app-sdk/logging v0.39.0/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk=
github.com/grafana/grafana-aws-sdk v0.38.2 h1:TzQD0OpWsNjtldi5G5TLDlBRk8OyDf+B5ujcoAu4Dp0=
github.com/grafana/grafana-aws-sdk v0.38.2/go.mod h1:j3vi+cXYHEFqjhBGrI6/lw1TNM+dl0Y3f0cSnDOPy+s=
github.com/grafana/grafana-aws-sdk v1.0.2 h1:98eBuHYFmgvH0xO9kKf4RBsEsgQRp8EOA/9yhDIpkss=
github.com/grafana/grafana-aws-sdk v1.0.2/go.mod h1:hO7q7yWV+t6dmiyJjMa3IbuYnYkBua+G/IAlOPVIYKE=
github.com/grafana/grafana-plugin-sdk-go v0.263.0/go.mod h1:U43Cnrj/9DNYyvFcNdeUWNjMXTKNB0jcTcQGpWKd2gw=
github.com/grafana/grafana-plugin-sdk-go v0.267.0/go.mod h1:OuwS4c/JYgn0rr/w5zhJBpLo4gKm/vw15RsfpYAvK9Q=
github.com/grafana/grafana-plugin-sdk-go v0.269.1/go.mod h1:yv2KbO4mlr9WuDK2f+2gHAMTwwLmLuqaEnrPXTRU+OI=
@@ -1270,6 +1276,7 @@ golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhp
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=
golang.org/x/mod v0.6.0-dev.0.20220818022119-ed83ed61efb9/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -1297,6 +1304,7 @@ golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc=
gonum.org/v1/plot v0.15.2 h1:Tlfh/jBk2tqjLZ4/P8ZIwGrLEWQSPDLRm/SNWKNXiGI=
gonum.org/v1/plot v0.15.2/go.mod h1:DX+x+DWso3LTha+AdkJEv5Txvi+Tql3KAGkehP0/Ubg=
@@ -1382,6 +1390,7 @@ k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 h1:2OX19X59HxDprNCVrWi6jb7LW1
k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kms v0.33.2/go.mod h1:C1I8mjFFBNzfUZXYt9FZVJ8MJl7ynFbGgZFbBzkBJ3E=
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
modernc.org/cc/v3 v3.36.3 h1:uISP3F66UlixxWEcKuIWERa4TwrZENHSL8tWxZz8bHg=
modernc.org/ccgo/v3 v3.16.9 h1:AXquSwg7GuMk11pIdw7fmO1Y/ybgazVkMhsZWCV0mHM=

View File

@@ -1,4 +1,4 @@
import { defaultDataQueryKind, Spec } from './v2alpha1/types.spec.gen';
import { Spec } from './v2alpha1/types.spec.gen';
export const handyTestingSchema: Spec = {
title: 'Default Dashboard',
@@ -37,16 +37,15 @@ export const handyTestingSchema: Spec = {
spec: {
builtIn: false,
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'prometheus',
datasource: {
name: 'uid',
},
kind: 'prometheus',
spec: {
expr: 'test-query',
},
},
datasource: {
type: 'prometheus',
uid: 'uid',
},
filter: { ids: [1] },
enable: true,
hide: false,
@@ -58,16 +57,15 @@ export const handyTestingSchema: Spec = {
kind: 'AnnotationQuery',
spec: {
builtIn: false,
datasource: {
type: 'grafana-testdata-datasource',
uid: 'uid',
},
enable: true,
iconColor: 'red',
name: 'Enabled',
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'grafana-testdata-datasource',
datasource: {
name: 'uid',
},
kind: 'grafana-testdata-datasource',
spec: {
lines: 4,
refId: 'Anno',
@@ -81,16 +79,15 @@ export const handyTestingSchema: Spec = {
kind: 'AnnotationQuery',
spec: {
builtIn: false,
datasource: {
type: 'grafana-testdata-datasource',
uid: 'uid',
},
enable: false,
iconColor: 'yellow',
name: 'Disabled',
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'grafana-testdata-datasource',
datasource: {
name: 'uid',
},
kind: 'grafana-testdata-datasource',
spec: { lines: 5, refId: 'Anno', scenarioId: 'annotations' },
},
hide: false,
@@ -100,17 +97,16 @@ export const handyTestingSchema: Spec = {
kind: 'AnnotationQuery',
spec: {
builtIn: false,
datasource: {
type: 'grafana-testdata-datasource',
uid: 'uid',
},
enable: true,
hide: true,
iconColor: 'dark-purple',
name: 'Hidden',
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'grafana-testdata-datasource',
datasource: {
name: 'uid',
},
kind: 'grafana-testdata-datasource',
spec: {
lines: 6,
refId: 'Anno',
@@ -132,13 +128,12 @@ export const handyTestingSchema: Spec = {
kind: 'PanelQuery',
spec: {
refId: 'A',
datasource: {
type: 'prometheus',
uid: 'datasource1',
},
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'prometheus',
datasource: {
name: 'datasource1',
},
kind: 'prometheus',
spec: {
expr: 'test-query',
},
@@ -270,6 +265,10 @@ export const handyTestingSchema: Spec = {
text: 'text1',
value: 'value1',
},
datasource: {
type: 'prometheus',
uid: 'datasource1',
},
definition: 'definition1',
description: 'A query variable',
hide: 'dontHide',
@@ -279,12 +278,7 @@ export const handyTestingSchema: Spec = {
name: 'queryVar',
options: [],
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'prometheus',
datasource: {
name: 'datasource1',
},
kind: 'prometheus',
spec: {
expr: 'test-query',
refId: 'A',

View File

@@ -11,19 +11,19 @@ export const defaultAnnotationQueryKind = (): AnnotationQueryKind => ({
});
export interface AnnotationQuerySpec {
query: DataQueryKind;
datasource?: DataSourceRef;
query?: DataQueryKind;
enable: boolean;
hide: boolean;
iconColor: string;
name: string;
builtIn?: boolean;
filter?: AnnotationPanelFilter;
// Catch-all field for datasource-specific properties. Should not be available in as code tooling.
// Catch-all field for datasource-specific properties
legacyOptions?: Record<string, any>;
}
export const defaultAnnotationQuerySpec = (): AnnotationQuerySpec => ({
query: defaultDataQueryKind(),
enable: false,
hide: false,
iconColor: "",
@@ -31,22 +31,24 @@ export const defaultAnnotationQuerySpec = (): AnnotationQuerySpec => ({
builtIn: false,
});
export interface DataSourceRef {
// The plugin type-id
type?: string;
// Specific datasource instance
uid?: string;
}
export const defaultDataSourceRef = (): DataSourceRef => ({
});
export interface DataQueryKind {
kind: "DataQuery";
group: string;
version: string;
// New type for datasource reference
// Not 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.
datasource?: {
name?: string;
};
// The kind of a DataQueryKind is the datasource type
kind: string;
spec: Record<string, any>;
}
export const defaultDataQueryKind = (): DataQueryKind => ({
kind: "DataQuery",
group: "",
version: "v0",
kind: "",
spec: {},
});
@@ -149,6 +151,7 @@ export const defaultPanelQueryKind = (): PanelQueryKind => ({
export interface PanelQuerySpec {
query: DataQueryKind;
datasource?: DataSourceRef;
refId: string;
hidden: boolean;
}
@@ -991,6 +994,7 @@ export interface QueryVariableSpec {
refresh: VariableRefresh;
skipUrlSync: boolean;
description?: string;
datasource?: DataSourceRef;
query: DataQueryKind;
regex: string;
sort: VariableSort;
@@ -1279,18 +1283,6 @@ export const defaultGroupByVariableSpec = (): GroupByVariableSpec => ({
skipUrlSync: false,
});
// Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec
// This type is widely used in the codebase and changing it will have a big impact
export interface DataSourceRef {
// The plugin type-id
type?: string;
// Specific datasource instance
uid?: string;
}
export const defaultDataSourceRef = (): DataSourceRef => ({
});
// Adhoc variable kind
export interface AdhocVariableKind {
kind: "AdhocVariable";

View File

@@ -7,6 +7,8 @@ import (
"fmt"
"net/http"
"net/url"
"path"
"regexp"
"strings"
"github.com/grafana/grafana/pkg/api/response"
@@ -39,6 +41,9 @@ var getViewIndex = func() string {
return viewIndex
}
// Only allow redirects that start with an alphanumerical character, a dash or an underscore.
var redirectRe = regexp.MustCompile(`^/[a-zA-Z0-9-_].*`)
var (
errAbsoluteRedirectTo = errors.New("absolute URLs are not allowed for redirect_to cookie value")
errInvalidRedirectTo = errors.New("invalid redirect_to cookie value")
@@ -68,6 +73,15 @@ func (hs *HTTPServer) ValidateRedirectTo(redirectTo string) error {
return errForbiddenRedirectTo
}
cleanPath := path.Clean(to.Path)
// "." is what path.Clean returns for empty paths
if cleanPath == "." {
return errForbiddenRedirectTo
}
if to.Path != "/" && !redirectRe.MatchString(cleanPath) {
return errForbiddenRedirectTo
}
// when using a subUrl, the redirect_to should start with the subUrl (which contains the leading slash), otherwise the redirect
// will send the user to the wrong location
if hs.Cfg.AppSubURL != "" && !strings.HasPrefix(to.Path, hs.Cfg.AppSubURL+"/") {

View File

@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net/http"
"net/url"
"testing"
"time"
@@ -20,6 +21,7 @@ import (
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/usertest"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web/webtest"
)
func TestUserTokenAPIEndpoint(t *testing.T) {
@@ -150,6 +152,95 @@ func TestUserTokenAPIEndpoint(t *testing.T) {
})
}
func TestHTTPServer_RotateUserAuthTokenRedirect(t *testing.T) {
redirectTestCases := []struct {
name string
redirectUrl string
expectedUrl string
}{
// Valid redirects should be preserved
{"valid root path", "/", "/"},
{"valid simple path", "/hello", "/hello"},
{"valid single char path", "/a", "/a"},
{"valid nested path", "/asd/hello", "/asd/hello"},
// Invalid redirects should be converted to root
{"backslash domain", `/\grafana.com`, "/"},
{"traversal backslash domain", `/a/../\grafana.com`, "/"},
{"double slash", "//grafana", "/"},
{"missing initial slash", "missingInitialSlash", "/"},
{"parent directory", "/../", "/"},
}
sessionTestCases := []struct {
name string
useSessionStorageRedirect bool
}{
{"when useSessionStorageRedirect is enabled", true},
{"when useSessionStorageRedirect is disabled", false},
}
for _, sessionCase := range sessionTestCases {
t.Run(sessionCase.name, func(t *testing.T) {
for _, redirectCase := range redirectTestCases {
t.Run(redirectCase.name, func(t *testing.T) {
server := SetupAPITestServer(t, func(hs *HTTPServer) {
cfg := setting.NewCfg()
cfg.LoginCookieName = "grafana_session"
cfg.LoginMaxLifetime = 10 * time.Hour
hs.Cfg = cfg
hs.log = log.New()
hs.AuthTokenService = &authtest.FakeUserAuthTokenService{
RotateTokenProvider: func(ctx context.Context, cmd auth.RotateCommand) (*auth.UserToken, error) {
return &auth.UserToken{UnhashedToken: "new"}, nil
},
}
})
redirectToQuery := url.QueryEscape(redirectCase.redirectUrl)
urlString := "/user/auth-tokens/rotate"
if sessionCase.useSessionStorageRedirect {
urlString = urlString + "?redirectTo=" + redirectToQuery
}
req := server.NewGetRequest(urlString)
req.AddCookie(&http.Cookie{Name: "grafana_session", Value: "123", Path: "/"})
if sessionCase.useSessionStorageRedirect {
req = webtest.RequestWithWebContext(req, &contextmodel.ReqContext{UseSessionStorageRedirect: true})
} else {
req.AddCookie(&http.Cookie{Name: "redirect_to", Value: redirectToQuery, Path: "/"})
}
var redirectStatusCode int
var redirectLocation string
server.HttpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
if len(via) > 1 {
// Stop after first redirect
return http.ErrUseLastResponse
}
if req.Response == nil {
return nil
}
redirectStatusCode = req.Response.StatusCode
redirectLocation = req.Response.Header.Get("Location")
return nil
}
res, err := server.Send(req)
require.NoError(t, err)
assert.Equal(t, 302, redirectStatusCode)
assert.Equal(t, redirectCase.expectedUrl, redirectLocation)
require.NoError(t, res.Body.Close())
})
}
})
}
}
func TestHTTPServer_RotateUserAuthToken(t *testing.T) {
type testCase struct {
desc string

View File

@@ -3,6 +3,8 @@ package middleware
import (
"fmt"
"net/http"
"path"
"regexp"
"strconv"
"github.com/grafana/grafana/pkg/services/contexthandler"
@@ -11,6 +13,9 @@ import (
"github.com/grafana/grafana/pkg/web"
)
// Only allow redirects that start with an alphanumerical character, a dash or an underscore.
var redirectRe = regexp.MustCompile(`^/?[a-zA-Z0-9-_].*`)
// OrgRedirect changes org and redirects users if the
// querystring `orgId` doesn't match the active org.
func OrgRedirect(cfg *setting.Cfg, userSvc user.Service) web.Handler {
@@ -31,6 +36,11 @@ func OrgRedirect(cfg *setting.Cfg, userSvc user.Service) web.Handler {
return
}
if !validRedirectPath(c.Req.URL.Path) {
// Do not switch orgs or perform the redirect because the new path is not valid
return
}
if err := userSvc.Update(ctx.Req.Context(), &user.UpdateUserCommand{UserID: ctx.UserID, OrgID: &orgId}); err != nil {
if ctx.IsApiRequest() {
ctx.JsonApiErr(404, "Not found", nil)
@@ -54,3 +64,8 @@ func OrgRedirect(cfg *setting.Cfg, userSvc user.Service) web.Handler {
c.Redirect(newURL, 302)
}
}
func validRedirectPath(p string) bool {
cleanPath := path.Clean(p)
return cleanPath == "." || cleanPath == "/" || redirectRe.MatchString(cleanPath)
}

View File

@@ -2,6 +2,7 @@ package middleware
import (
"fmt"
"net/url"
"testing"
"github.com/stretchr/testify/require"
@@ -23,6 +24,12 @@ func TestOrgRedirectMiddleware(t *testing.T) {
expStatus: 302,
expLocation: "/?orgId=3",
},
{
desc: "when setting a correct org for the user with an empty path",
input: "?orgId=3",
expStatus: 302,
expLocation: "/?orgId=3",
},
{
desc: "when setting a correct org for the user with '&kiosk'",
input: "/?orgId=3&kiosk",
@@ -64,6 +71,16 @@ func TestOrgRedirectMiddleware(t *testing.T) {
require.Equal(t, 404, sc.resp.Code)
})
middlewareScenario(t, "when redirecting to an invalid path", func(t *testing.T, sc *scenarioContext) {
sc.withIdentity(&authn.Identity{})
path := url.QueryEscape(`/\example.com`)
sc.m.Get(url.QueryEscape(path), sc.defaultHandler)
sc.fakeReq("GET", fmt.Sprintf("%s?orgId=3", path)).exec()
require.Equal(t, 404, sc.resp.Code)
})
middlewareScenario(t, "works correctly when grafana is served under a subpath", func(t *testing.T, sc *scenarioContext) {
sc.withIdentity(&authn.Identity{})

View File

@@ -1250,7 +1250,6 @@
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardAnnotationQuerySpec": {
"type": "object",
"required": [
"query",
"enable",
"hide",
"iconColor",
@@ -1260,6 +1259,9 @@
"builtIn": {
"type": "boolean"
},
"datasource": {
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardDataSourceRef"
},
"enable": {
"type": "boolean",
"default": false
@@ -1276,7 +1278,7 @@
"default": ""
},
"legacyOptions": {
"description": "Catch-all field for datasource-specific properties. Should not be available in as code tooling.",
"description": "Catch-all field for datasource-specific properties",
"type": "object",
"additionalProperties": {
"type": "object"
@@ -1287,12 +1289,7 @@
"default": ""
},
"query": {
"default": {},
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardDataQueryKind"
}
]
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardDataQueryKind"
}
}
},
@@ -1868,24 +1865,11 @@
"type": "object",
"required": [
"kind",
"group",
"version",
"spec"
],
"properties": {
"datasource": {
"description": "New type for datasource reference Not 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.",
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardV2alpha1DataQueryKindDatasource"
}
]
},
"group": {
"type": "string",
"default": ""
},
"kind": {
"description": "The kind of a DataQueryKind is the datasource type",
"type": "string",
"default": ""
},
@@ -1894,15 +1878,10 @@
"additionalProperties": {
"type": "object"
}
},
"version": {
"type": "string",
"default": ""
}
}
},
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardDataSourceRef": {
"description": "Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec This type is widely used in the codebase and changing it will have a big impact",
"type": "object",
"properties": {
"type": {
@@ -2764,6 +2743,9 @@
"hidden"
],
"properties": {
"datasource": {
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardDataSourceRef"
},
"hidden": {
"type": "boolean",
"default": false
@@ -3011,6 +2993,9 @@
}
]
},
"datasource": {
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardDataSourceRef"
},
"definition": {
"type": "string"
},
@@ -3740,14 +3725,6 @@
}
}
},
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardV2alpha1DataQueryKindDatasource": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardV2alpha1FieldConfigSourceOverrides": {
"type": "object",
"required": [

View File

@@ -2923,11 +2923,16 @@
"type": "object",
"required": [
"title",
"description",
"version",
"group",
"permissions"
],
"properties": {
"description": {
"type": "string",
"default": ""
},
"group": {
"type": "string",
"default": ""
@@ -3236,11 +3241,16 @@
"type": "object",
"required": [
"title",
"description",
"version",
"group",
"permissions"
],
"properties": {
"description": {
"type": "string",
"default": ""
},
"group": {
"type": "string",
"default": ""
@@ -3723,11 +3733,16 @@
"type": "object",
"required": [
"title",
"description",
"version",
"group",
"permissions"
],
"properties": {
"description": {
"type": "string",
"default": ""
},
"group": {
"type": "string",
"default": ""

View File

@@ -147,6 +147,7 @@ func requestContextMiddleware() web.Middleware {
c.RequestNonce = ctx.RequestNonce
c.PerfmonTimer = ctx.PerfmonTimer
c.LookupTokenErr = ctx.LookupTokenErr
c.UseSessionStorageRedirect = ctx.UseSessionStorageRedirect
}
next.ServeHTTP(w, r)

View File

@@ -2,7 +2,7 @@ import { uniqueId } from 'lodash';
import { HttpResponse, http } from 'msw';
import { Route, Routes } from 'react-router-dom-v5-compat';
import { Props } from 'react-virtualized-auto-sizer';
import { render, screen, waitFor, waitForElementToBeRemoved, within } from 'test/test-utils';
import { render, screen, waitFor, within } from 'test/test-utils';
import { byRole, byTestId } from 'testing-library-selector';
import { setPluginLinksHook } from '@grafana/runtime';
@@ -41,7 +41,6 @@ const ui = {
header: byRole('heading', { level: 1 }),
editLink: byRole('link', { name: 'Edit' }),
exportButton: byRole('button', { name: 'Export' }),
ruleLoader: byTestId('alert-rule-list-item-loader'),
ruleItem: byRole('treeitem'),
export: {
dialog: byRole('dialog', { name: /Drawer title Export .* rules/ }),
@@ -161,7 +160,7 @@ describe('GroupDetailsPage', () => {
'/alerting/grafana/namespaces/test-folder-uid/groups/test-group-cpu/edit?returnTo=%2Falerting%2Fgrafana%2Fnamespaces%2Ftest-folder-uid%2Fgroups%2Ftest-group-cpu%2Fview'
);
await waitForElementToBeRemoved(() => ui.ruleLoader.queryAll());
expect(await screen.findByRole('treeitem', { name: rule1.grafana_alert.title })).toBeInTheDocument();
const alertRuleItems = await ui.ruleItem.findAll();
expect(alertRuleItems).toHaveLength(2);
@@ -221,11 +220,9 @@ describe('GroupDetailsPage', () => {
// Act
renderGroupDetailsPage('grafana', 'test-folder-uid', group.name);
// wait for loaders to show and dissapear
await waitFor(() => expect(ui.ruleLoader.queryAll()).toHaveLength(3));
await waitForElementToBeRemoved(() => ui.ruleLoader.queryAll());
const alertRuleItems = await ui.ruleItem.findAll();
// Wait until rule items are rendered
expect(await screen.findByRole('treeitem', { name: rule1.grafana_alert.title })).toBeInTheDocument();
const alertRuleItems = ui.ruleItem.getAll();
// Assert
expect(alertRuleItems).toHaveLength(2);
@@ -238,9 +235,8 @@ describe('GroupDetailsPage', () => {
// Act
renderGroupDetailsPage('grafana', 'test-folder-uid', group.name);
// wait for loaders to show and dissapear
await waitFor(() => expect(ui.ruleLoader.queryAll()).toHaveLength(3));
await waitForElementToBeRemoved(() => ui.ruleLoader.queryAll());
// wait for rule items to render
expect(await screen.findByRole('treeitem', { name: rule1.grafana_alert.title })).toBeInTheDocument();
const alertRuleItems = await ui.ruleItem.findAll();
@@ -264,9 +260,8 @@ describe('GroupDetailsPage', () => {
// Act
renderGroupDetailsPage('grafana', 'test-folder-uid', provisionedGroup.name);
// wait for loaders to show and dissapear
await waitFor(() => expect(ui.ruleLoader.queryAll()).toHaveLength(3));
await waitForElementToBeRemoved(() => ui.ruleLoader.queryAll());
// wait for rule items to render
expect(await screen.findByRole('treeitem', { name: provisionedRule.grafana_alert.title })).toBeInTheDocument();
const alertRuleItems = await ui.ruleItem.findAll();

View File

@@ -17,6 +17,7 @@ export function AlertRuleListItemSkeleton() {
description={<Skeleton width={256} />}
actions={<RuleActionsSkeleton />}
data-testid="alert-rule-list-item-loader"
aria-disabled={true}
/>
);
}

View File

@@ -37,39 +37,6 @@ jest.mock('@grafana/runtime', () => {
...original.config.featureToggles,
dashboardNewLayouts: false, // Default value
},
bootData: {
...original.config.bootData,
settings: {
...original.config.bootData.settings,
datasources: {
'gdev-testdata': {
id: 7,
uid: 'abc',
type: 'grafana-testdata-datasource',
name: 'gdev-testdata',
meta: {
id: 'grafana-testdata-datasource',
type: 'datasource',
name: 'TestData',
aliasIDs: ['testdata'],
},
},
'-- Grafana --': {
id: -1,
uid: 'grafana',
type: 'datasource',
name: '-- Grafana --',
meta: {
id: 'grafana',
type: 'datasource',
name: '-- Grafana --',
},
},
},
defaultDatasource: 'gdev-testdata',
},
},
},
};
});
@@ -1621,11 +1588,9 @@ const v2ProvisionedDashboardResource = {
kind: 'AnnotationQuery',
spec: {
builtIn: true,
query: {
kind: 'DataQuery',
group: 'grafana',
spec: {},
version: 'v0',
datasource: {
type: 'grafana',
uid: '-- Grafana --',
},
enable: true,
hide: true,
@@ -1648,14 +1613,13 @@ const v2ProvisionedDashboardResource = {
{
kind: 'PanelQuery',
spec: {
datasource: {
type: 'grafana-testdata-datasource',
uid: 'PD8C576611E62080A',
},
hidden: false,
query: {
kind: 'DataQuery',
group: 'grafana-testdata-datasource',
version: 'v0',
datasource: {
name: 'PD8C576611E62080A',
},
kind: 'grafana-testdata-datasource',
spec: {
scenarioId: 'random_walk',
seriesCount: 2,

View File

@@ -549,12 +549,13 @@ describe('dashboard exporter v2', () => {
{
kind: 'PanelQuery',
spec: {
datasource: {
type: 'prometheus',
uid: '${datasourceVar}',
},
hidden: false,
query: {
datasource: {
name: '${datasourceVar}',
},
group: 'prometheus',
kind: 'prometheus',
spec: {
editorMode: 'builder',
expr: 'go_goroutines{job="prometheus"}',
@@ -582,7 +583,7 @@ describe('dashboard exporter v2', () => {
it('should replace datasource in a query variable', async () => {
const { dashboard } = await setup();
const variable = dashboard.variables[0] as QueryVariableKind;
expect(variable.spec.query.datasource?.name).toBeUndefined();
expect(variable.spec.datasource?.uid).toBeUndefined();
});
it('do not expose datasource name and id in datasource variable', async () => {
@@ -596,7 +597,7 @@ describe('dashboard exporter v2', () => {
const { dashboard } = await setup();
const annotationQuery = dashboard.annotations[0];
expect(annotationQuery.spec.query?.datasource?.name).toBeUndefined();
expect(annotationQuery.spec.datasource?.uid).toBeUndefined();
});
it('should remove library panels from layout', async () => {
@@ -615,8 +616,11 @@ describe('dashboard exporter v2', () => {
if (panel.kind !== 'Panel') {
throw new Error('Panel should be a Panel');
}
expect(panel.spec.data.spec.queries[0].spec.query.datasource?.name).toBe('${datasourceVar}');
expect(panel.spec.data.spec.queries[0].spec.query.group).toBe('prometheus');
expect(panel.spec.data.spec.queries[0].spec.datasource).toEqual({
type: 'prometheus',
uid: '${datasourceVar}',
});
});
});

View File

@@ -344,8 +344,7 @@ export async function makeExportableV2(dashboard: DashboardV2Spec) {
const removeDataSourceRefs = (
obj: AnnotationQueryKind['spec'] | QueryVariableKind['spec'] | PanelQueryKind['spec']
) => {
const datasourceUid = obj.query?.datasource?.name;
const datasourceUid = obj.datasource?.uid;
if (datasourceUid?.startsWith('${') && datasourceUid?.endsWith('}')) {
const varName = datasourceUid.slice(2, -1);
// if there's a match we don't want to remove the datasource ref
@@ -355,7 +354,7 @@ export async function makeExportableV2(dashboard: DashboardV2Spec) {
}
}
obj.query && (obj.query.datasource = undefined);
obj.datasource = undefined;
};
const processPanel = (panel: PanelKind) => {

View File

@@ -10,13 +10,10 @@ import { Dashboard, VariableModel } from '@grafana/schema';
import {
Spec as DashboardV2Spec,
defaultSpec as defaultDashboardV2Spec,
defaultDataQueryKind,
defaultPanelSpec,
defaultTimeSettingsSpec,
GridLayoutKind,
PanelKind,
PanelSpec,
QueryVariableKind,
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen';
import { DEFAULT_ANNOTATION_COLOR } from '@grafana/ui';
import { AnnoKeyDashboardSnapshotOriginalUrl } from 'app/features/apiserver/types';
@@ -50,13 +47,11 @@ jest.mock('@grafana/runtime', () => ({
name: 'Grafana',
meta: { id: 'grafana' },
type: 'datasource',
uid: 'grafana',
},
prometheus: {
name: 'prometheus',
meta: { id: 'prometheus' },
type: 'datasource',
uid: 'prometheus-uid',
},
},
},
@@ -728,14 +723,9 @@ describe('DashboardSceneSerializer', () => {
spec: {
builtIn: true,
name: 'Annotations & Alerts',
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'grafana',
datasource: {
name: '-- Grafana --',
},
spec: {},
datasource: {
uid: '-- Grafana --',
type: 'grafana',
},
enable: true,
hide: true,
@@ -894,226 +884,6 @@ describe('DashboardSceneSerializer', () => {
},
});
});
describe('data source references persistence', () => {
it('should not fill data source references for annotations when input did not contain it', () => {
const dashboard = setupV2({
annotations: [
{
kind: 'AnnotationQuery',
spec: {
builtIn: false,
enable: true,
hide: false,
iconColor: 'blue',
name: 'prom-annotations',
query: {
group: 'prometheus',
kind: 'DataQuery',
spec: {
refId: 'Anno',
},
version: 'v0',
},
},
},
],
});
const saveAsModel = serializer.getSaveAsModel(dashboard, baseOptions);
// referencing index 1 as transformation adds built in annotation query
expect(saveAsModel.annotations[1].spec.query.datasource).toBeUndefined();
});
it('should fill data source references for annotations when input did contain it', () => {
const dashboard = setupV2({
annotations: [
{
kind: 'AnnotationQuery',
spec: {
builtIn: false,
enable: true,
hide: false,
iconColor: 'blue',
name: 'prom-annotations',
query: {
group: 'prometheus',
kind: 'DataQuery',
datasource: {
name: 'prometheus-uid',
},
spec: {
refId: 'Anno',
},
version: 'v0',
},
},
},
],
});
const saveAsModel = serializer.getSaveAsModel(dashboard, baseOptions);
// referencing index 1 as transformation adds built in annotation query
expect(saveAsModel.annotations[1].spec.query.datasource).toEqual({
name: 'prometheus-uid',
});
});
it('should not fill data source references for panel queries when input did not contain it', () => {
const dashboard = setupV2({
elements: {
'panel-1': {
kind: 'Panel',
spec: {
...defaultPanelSpec(),
data: {
kind: 'QueryGroup',
spec: {
transformations: [],
queryOptions: {},
queries: [
{
kind: 'PanelQuery',
spec: {
refId: 'A',
hidden: false,
query: {
kind: 'DataQuery',
group: 'prometheus',
version: 'v0',
spec: {},
},
},
},
],
},
},
},
},
},
});
const saveAsModel = serializer.getSaveAsModel(dashboard, baseOptions);
expect(
(saveAsModel.elements['panel-1'] as PanelKind).spec.data.spec.queries[0].spec.query.datasource
).toBeUndefined();
});
it('should fill data source references for panel queries when input did contain it', () => {
const dashboard = setupV2({
elements: {
'panel-1': {
kind: 'Panel',
spec: {
...defaultPanelSpec(),
data: {
kind: 'QueryGroup',
spec: {
transformations: [],
queryOptions: {},
queries: [
{
kind: 'PanelQuery',
spec: {
refId: 'A',
hidden: false,
query: {
kind: 'DataQuery',
group: 'prometheus',
version: 'v0',
datasource: {
name: 'prometheus-uid',
},
spec: {},
},
},
},
],
},
},
},
},
},
});
const saveAsModel = serializer.getSaveAsModel(dashboard, baseOptions);
expect(
(saveAsModel.elements['panel-1'] as PanelKind).spec.data.spec.queries[0].spec.query.datasource
).toEqual({
name: 'prometheus-uid',
});
});
it('should not fill data source references for query variables when input did contain it', () => {
const queryVariable: QueryVariableKind = {
kind: 'QueryVariable',
spec: {
name: 'app',
current: {
text: 'app1',
value: 'app1',
},
hide: 'dontHide',
includeAll: false,
label: 'Query Variable',
skipUrlSync: false,
regex: '',
definition: '',
options: [],
refresh: 'never',
sort: 'alphabeticalAsc',
multi: false,
allowCustomValue: true,
query: {
kind: 'DataQuery',
group: 'prometheus',
version: 'v0',
spec: {},
},
},
};
const dashboard = setupV2({
variables: [queryVariable],
});
const saveAsModel = serializer.getSaveAsModel(dashboard, baseOptions);
expect((saveAsModel.variables[0] as QueryVariableKind).spec.query.datasource).toBeUndefined();
});
it('should fill data source references for query variables when input did contain it', () => {
const queryVariable: QueryVariableKind = {
kind: 'QueryVariable',
spec: {
name: 'app',
current: {
text: 'app1',
value: 'app1',
},
hide: 'dontHide',
includeAll: false,
label: 'Query Variable',
skipUrlSync: false,
regex: '',
definition: '',
options: [],
refresh: 'never',
sort: 'alphabeticalAsc',
multi: false,
allowCustomValue: true,
query: {
kind: 'DataQuery',
group: 'prometheus',
version: 'v0',
datasource: {
name: 'prometheus-uid',
},
spec: {},
},
},
};
const dashboard = setupV2({
variables: [queryVariable],
});
const saveAsModel = serializer.getSaveAsModel(dashboard, baseOptions);
expect((saveAsModel.variables[0] as QueryVariableKind).spec.query.datasource).toEqual({
name: 'prometheus-uid',
});
});
});
});
describe('panel mapping methods', () => {
@@ -1244,7 +1014,7 @@ describe('DashboardSceneSerializer', () => {
refId: 'A',
hidden: false,
// No datasource defined
query: { kind: 'DataQuery', version: defaultDataQueryKind().version, group: 'sql', spec: {} },
query: { kind: 'sql', spec: {} },
},
},
{
@@ -1252,15 +1022,8 @@ describe('DashboardSceneSerializer', () => {
spec: {
refId: 'B',
hidden: false,
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'prometheus',
datasource: {
name: 'datasource-1',
},
spec: {},
},
datasource: { uid: 'datasource-1', type: 'prometheus' },
query: { kind: 'prometheus', spec: {} },
},
},
],
@@ -1295,7 +1058,7 @@ describe('DashboardSceneSerializer', () => {
refId: 'C',
hidden: false,
// No datasource defined
query: { kind: 'DataQuery', version: defaultDataQueryKind().version, group: 'sql', spec: {} },
query: { kind: 'sql', spec: {} },
},
},
],
@@ -1343,7 +1106,7 @@ describe('DashboardSceneSerializer', () => {
kind: 'AnnotationQuery',
spec: {
name: 'Annotation 1',
query: { kind: 'DataQuery', version: defaultDataQueryKind().version, group: 'prometheus', spec: {} },
query: { kind: 'prometheus', spec: {} },
enable: true,
hide: false,
iconColor: 'red',

View File

@@ -288,7 +288,7 @@ export class V2DashboardSerializer
const panelQueries = elementPanel.spec.data.spec.queries;
for (const query of panelQueries) {
if (!query.spec.query.datasource?.name) {
if (!query.spec.datasource) {
const elementId = this.getElementIdForPanel(elementPanel.spec.id);
if (!this.defaultDsReferencesMap.panels.has(elementId)) {
this.defaultDsReferencesMap.panels.set(elementId, new Set());
@@ -306,7 +306,7 @@ export class V2DashboardSerializer
if (saveModel?.variables) {
for (const variable of saveModel.variables) {
// for query variables that dont have a ds defined add them to the list
if (variable.kind === 'QueryVariable' && !variable.spec.query.datasource?.name) {
if (variable.kind === 'QueryVariable' && !variable.spec.datasource) {
this.defaultDsReferencesMap.variables.add(variable.spec.name);
}
}
@@ -315,7 +315,7 @@ export class V2DashboardSerializer
// initialize annotations ds references map
if (saveModel?.annotations) {
for (const annotation of saveModel.annotations) {
if (!annotation.spec.query?.datasource?.name) {
if (!annotation.spec.datasource) {
this.defaultDsReferencesMap.annotations.add(annotation.spec.name);
}
}

View File

@@ -7,19 +7,28 @@ exports[`transformSceneToSaveModelSchemaV2 should transform scene to save model
"kind": "AnnotationQuery",
"spec": {
"builtIn": false,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --",
},
"enable": true,
"hide": false,
"iconColor": "red",
"name": "query1",
"query": {
"datasource": {
"name": "-- Grafana --",
},
"group": "grafana",
"kind": "DataQuery",
"spec": {},
"version": "v0",
},
},
{
"kind": "AnnotationQuery",
"spec": {
"builtIn": false,
"datasource": {
"type": "prometheus",
"uid": "abcdef",
},
"enable": true,
"hide": true,
"iconColor": "blue",
"name": "query2",
},
},
{
@@ -28,17 +37,8 @@ exports[`transformSceneToSaveModelSchemaV2 should transform scene to save model
"builtIn": false,
"enable": true,
"hide": true,
"iconColor": "blue",
"name": "query2",
"query": {
"datasource": {
"name": "abcdef",
},
"group": "prometheus",
"kind": "DataQuery",
"spec": {},
"version": "v0",
},
"iconColor": "green",
"name": "query3",
},
},
],
@@ -152,6 +152,10 @@ exports[`transformSceneToSaveModelSchemaV2 should transform scene to save model
"text": "text1",
"value": "value1",
},
"datasource": {
"type": "prometheus",
"uid": "datasource1",
},
"definition": "definition1",
"description": "A query variable",
"hide": "hideLabel",
@@ -161,16 +165,11 @@ exports[`transformSceneToSaveModelSchemaV2 should transform scene to save model
"name": "queryVar",
"options": [],
"query": {
"datasource": {
"name": "datasource1",
},
"group": "prometheus",
"kind": "DataQuery",
"kind": "prometheus",
"spec": {
"expr": "label_values(node_boot_time_seconds)",
"refId": "A",
},
"version": "v0",
},
"refresh": "onDashboardLoad",
"regex": "regex1",

View File

@@ -1,226 +0,0 @@
import { AnnotationQuery } from '@grafana/data';
import { AnnotationQueryKind } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen';
import { transformV1ToV2AnnotationQuery, transformV2ToV1AnnotationQuery } from './annotations';
describe('V1<->V2 annotation convertions', () => {
test('given grafana-built in annotations', () => {
// test case
const annotationDefinition: AnnotationQuery = {
builtIn: 1,
datasource: {
type: 'grafana',
uid: 'grafana',
},
enable: true,
hide: false,
iconColor: 'yellow',
name: 'Annotations \u0026 Alerts',
target: {
// @ts-expect-error
limit: 100,
matchAny: false,
tags: [],
type: 'dashboard',
},
type: 'dashboard',
};
const expectedV2: AnnotationQueryKind = {
kind: 'AnnotationQuery',
spec: {
builtIn: true,
enable: true,
hide: false,
iconColor: 'yellow',
name: 'Annotations \u0026 Alerts',
query: {
kind: 'DataQuery',
group: 'grafana',
version: 'v0',
datasource: {
name: 'grafana',
},
spec: {
limit: 100,
matchAny: false,
tags: [],
type: 'dashboard',
},
},
},
};
const resultV2: AnnotationQueryKind = transformV1ToV2AnnotationQuery(annotationDefinition, 'grafana', 'grafana');
expect(resultV2).toEqual(expectedV2);
const resultV1: AnnotationQuery = transformV2ToV1AnnotationQuery(expectedV2);
expect(resultV1).toEqual(annotationDefinition);
});
test('given annotations with datasource', () => {
const annotationDefinition = {
datasource: {
type: 'grafana-testdata-datasource',
uid: 'uid',
},
enable: true,
hide: false,
iconColor: 'blue',
name: 'testdata-annos',
target: {
lines: 10,
refId: 'Anno',
scenarioId: 'annotations',
},
};
const expectedV2: AnnotationQueryKind = {
kind: 'AnnotationQuery',
spec: {
enable: true,
hide: false,
iconColor: 'blue',
name: 'testdata-annos',
builtIn: false,
query: {
kind: 'DataQuery',
group: 'grafana-testdata-datasource',
version: 'v0',
datasource: {
name: 'uid',
},
spec: {
lines: 10,
refId: 'Anno',
scenarioId: 'annotations',
},
},
},
};
const resultV2: AnnotationQueryKind = transformV1ToV2AnnotationQuery(
annotationDefinition,
'grafana-testdata-datasource',
'uid'
);
expect(resultV2).toEqual(expectedV2);
const resultV1: AnnotationQuery = transformV2ToV1AnnotationQuery(expectedV2);
expect(resultV1).toEqual(annotationDefinition);
});
test('given annotations with target', () => {
const annotationDefinition = {
datasource: {
type: 'prometheus',
uid: 'uid',
},
enable: true,
hide: false,
iconColor: 'yellow',
name: 'prom-annos',
target: {
expr: '{action="add_client"}',
interval: '',
lines: 10,
refId: 'Anno',
scenarioId: 'annotations',
},
};
const expectedV2: AnnotationQueryKind = {
kind: 'AnnotationQuery',
spec: {
enable: true,
hide: false,
iconColor: 'yellow',
name: 'prom-annos',
builtIn: false,
query: {
kind: 'DataQuery',
group: 'prometheus',
version: 'v0',
datasource: {
name: 'uid',
},
spec: {
expr: '{action="add_client"}',
interval: '',
lines: 10,
refId: 'Anno',
scenarioId: 'annotations',
},
},
},
};
const resultV2: AnnotationQueryKind = transformV1ToV2AnnotationQuery(annotationDefinition, 'prometheus', 'uid');
expect(resultV2).toEqual(expectedV2);
const resultV1: AnnotationQuery = transformV2ToV1AnnotationQuery(expectedV2);
expect(resultV1).toEqual(annotationDefinition);
});
test('given annotations with non-schematised options / legacyOptions', () => {
const annotationDefinition = {
datasource: {
type: 'elasticsearch',
uid: 'uid',
},
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',
};
const expectedV2: AnnotationQueryKind = {
kind: 'AnnotationQuery',
spec: {
enable: true,
hide: false,
iconColor: 'red',
name: 'elastic - annos',
builtIn: false,
query: {
kind: 'DataQuery',
group: 'elasticsearch',
version: 'v0',
datasource: {
name: 'uid',
},
spec: {
lines: 10,
query: 'test query',
refId: 'Anno',
scenarioId: 'annotations',
},
},
legacyOptions: {
tagsField: 'asd',
textField: 'asd',
timeEndField: 'asdas',
timeField: 'asd',
},
},
};
const resultV2: AnnotationQueryKind = transformV1ToV2AnnotationQuery(annotationDefinition, 'elasticsearch', 'uid');
expect(resultV2).toEqual(expectedV2);
const resultV1: AnnotationQuery = transformV2ToV1AnnotationQuery(expectedV2);
expect(resultV1).toEqual(annotationDefinition);
});
});

View File

@@ -1,118 +0,0 @@
import { AnnotationQuery } from '@grafana/data';
import {
AnnotationQueryKind,
defaultDataQueryKind,
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen';
import { getRuntimePanelDataSource } from './layoutSerializers/utils';
export function transformV1ToV2AnnotationQuery(
annotation: AnnotationQuery,
dsType: string,
dsUID?: string,
// Overrides are used to provide properties based on scene's annotations data layer object state
override?: Partial<AnnotationQuery>
): AnnotationQueryKind {
const group = annotation.builtIn ? 'grafana' : dsType;
const {
// known properties documented in v1 schema
enable,
hide,
iconColor,
name,
builtIn,
filter,
mappings,
datasource,
target,
snapshotData,
type,
// unknown properties that are still available for configuration through API
...legacyOptions
} = annotation;
const result: AnnotationQueryKind = {
kind: 'AnnotationQuery',
spec: {
builtIn: Boolean(annotation.builtIn),
name: annotation.name,
enable: Boolean(override?.enable) || Boolean(annotation.enable),
hide: Boolean(override?.hide) || Boolean(annotation.hide),
iconColor: annotation.iconColor,
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group, // Annotation layer has a datasource type provided in runtime.
spec: target || {},
},
},
};
if (dsUID) {
result.spec.query.datasource = {
name: dsUID,
};
}
// if legacy options is not an empty object, add it to the result
if (Object.keys(legacyOptions).length > 0) {
result.spec.legacyOptions = legacyOptions;
}
if (annotation.filter?.ids?.length) {
result.spec.filter = annotation.filter;
}
// TODO: add mappings
return result;
}
export function transformV2ToV1AnnotationQuery(annotation: AnnotationQueryKind): AnnotationQuery {
let { query: dataQuery, ...annotationQuery } = annotation.spec;
// Mapping from AnnotationQueryKind to AnnotationQuery used by scenes.
let annoQuerySpec: AnnotationQuery = {
enable: annotation.spec.enable,
hide: annotation.spec.hide,
iconColor: annotation.spec.iconColor,
name: annotation.spec.name,
// TOOO: mappings
};
if (Object.keys(dataQuery.spec).length > 0) {
// @ts-expect-error DataQueryKind spec should be typed as DataQuery interface
annoQuerySpec.target = {
...dataQuery?.spec,
};
}
if (annotation.spec.builtIn) {
annoQuerySpec.type = 'dashboard';
annoQuerySpec.builtIn = 1;
}
if (annotation.spec.filter) {
annoQuerySpec.filter = annotation.spec.filter;
}
// some annotations will contain in the legacyOptions properties that need to be
// added to the root level AnnotationQuery
if (annotationQuery.legacyOptions) {
annoQuerySpec = {
...annoQuerySpec,
...annotationQuery.legacyOptions,
};
}
// get data source from annotation query
const datasource = getRuntimePanelDataSource(dataQuery);
annoQuerySpec.datasource = datasource;
return annoQuerySpec;
}

View File

@@ -1,7 +1,4 @@
import {
defaultDataQueryKind,
PanelQueryKind,
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen';
import { PanelQueryKind } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen';
import { getRuntimePanelDataSource } from './utils';
@@ -32,12 +29,6 @@ jest.mock('@grafana/runtime', () => ({
meta: { id: 'loki' },
type: 'datasource',
},
'-- Grafana --': {
uid: 'grafana',
name: 'Grafana',
meta: { id: 'grafana' },
type: 'datasource',
},
},
},
},
@@ -51,23 +42,22 @@ describe('getRuntimePanelDataSource', () => {
spec: {
refId: 'A',
hidden: false,
datasource: {
uid: 'test-ds-uid',
type: 'test-ds-type',
},
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'prometheus',
datasource: {
name: 'prometheus-uid',
},
kind: 'prometheus',
spec: {},
},
},
};
const result = getRuntimePanelDataSource(query.spec.query);
const result = getRuntimePanelDataSource(query);
expect(result).toEqual({
uid: 'prometheus-uid',
type: 'prometheus',
uid: 'test-ds-uid',
type: 'test-ds-type',
});
});
@@ -77,16 +67,15 @@ describe('getRuntimePanelDataSource', () => {
spec: {
refId: 'A',
hidden: false,
datasource: undefined,
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'prometheus',
kind: 'prometheus',
spec: {},
},
},
};
const result = getRuntimePanelDataSource(query.spec.query);
const result = getRuntimePanelDataSource(query);
expect(result).toEqual({
uid: 'default-prometheus-uid',
@@ -100,16 +89,15 @@ describe('getRuntimePanelDataSource', () => {
spec: {
refId: 'A',
hidden: false,
datasource: undefined,
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'loki',
kind: 'loki',
spec: {},
},
},
};
const result = getRuntimePanelDataSource(query.spec.query);
const result = getRuntimePanelDataSource(query);
expect(result).toEqual({
uid: 'loki-uid',
@@ -124,16 +112,15 @@ describe('getRuntimePanelDataSource', () => {
spec: {
refId: 'A',
hidden: false,
datasource: undefined,
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'unknown-type',
kind: 'unknown-type',
spec: {},
},
},
};
const result = getRuntimePanelDataSource(query.spec.query);
const result = getRuntimePanelDataSource(query);
expect(result).toEqual({
uid: 'default-prometheus-uid',
@@ -151,19 +138,18 @@ describe('getRuntimePanelDataSource', () => {
spec: {
refId: 'A',
hidden: false,
datasource: {
uid: '',
type: 'test-ds-type',
},
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'prometheus',
datasource: {
name: '',
},
kind: 'prometheus',
spec: {},
},
},
};
const result = getRuntimePanelDataSource(query.spec.query);
const result = getRuntimePanelDataSource(query);
expect(result).toEqual({
uid: 'default-prometheus-uid',

View File

@@ -19,7 +19,6 @@ import {
PanelQueryKind,
QueryVariableKind,
TabsLayoutTabKind,
DataQueryKind,
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen';
import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
@@ -186,15 +185,12 @@ function getPanelDataSource(panel: PanelKind): DataSourceRef | undefined {
panel.spec.data.spec.queries.forEach((query) => {
if (!datasource) {
if (!query.spec.query.datasource?.name) {
datasource = getRuntimePanelDataSource(query.spec.query);
if (!query.spec.datasource?.uid) {
datasource = getRuntimePanelDataSource(query);
} else {
datasource = {
uid: query.spec.query.datasource?.name,
type: query.spec.query.group,
};
datasource = query.spec.datasource;
}
} else if (datasource.uid !== query.spec.query.datasource?.name || datasource.type !== query.spec.query.group) {
} else if (datasource.uid !== query.spec.datasource?.uid || datasource.type !== query.spec.datasource?.type) {
isMixedDatasource = true;
}
});
@@ -203,19 +199,11 @@ function getPanelDataSource(panel: PanelKind): DataSourceRef | undefined {
}
export function getRuntimeVariableDataSource(variable: QueryVariableKind): DataSourceRef | undefined {
const ds: DataSourceRef = {
uid: variable.spec.query.datasource?.name,
type: variable.spec.query.group,
};
return getDataSourceForQuery(ds, variable.spec.query.group);
return getDataSourceForQuery(variable.spec.datasource, variable.spec.query.kind);
}
export function getRuntimePanelDataSource(query: DataQueryKind): DataSourceRef {
const ds: DataSourceRef = {
uid: query.datasource?.name,
type: query.group,
};
return getDataSourceForQuery(ds, query.group);
export function getRuntimePanelDataSource(query: PanelQueryKind): DataSourceRef | undefined {
return getDataSourceForQuery(query.spec.datasource, query.spec.query.kind);
}
/**
@@ -223,7 +211,10 @@ export function getRuntimePanelDataSource(query: DataQueryKind): DataSourceRef {
* @param queryKind - The kind of query being performed
* @returns The resolved DataSourceRef
*/
function getDataSourceForQuery(querySpecDS: DataSourceRef | undefined | null, queryKind: string): DataSourceRef {
function getDataSourceForQuery(
querySpecDS: DataSourceRef | undefined | null,
queryKind: string
): DataSourceRef | undefined {
// If datasource is specified and has a uid, use it
if (querySpecDS?.uid) {
return querySpecDS;
@@ -262,22 +253,14 @@ function getDataSourceForQuery(querySpecDS: DataSourceRef | undefined | null, qu
};
}
if (dsList && !dsList[defaultDatasource]) {
throw new Error(`Default datasource ${defaultDatasource} not found in datasource list`);
}
// In the datasource list from bootData "id" is the type and the uid could be uid or the name
// in cases like grafana, dashboard or mixed datasource
return {
uid: dsList[defaultDatasource].uid || dsList[defaultDatasource].name,
type: dsList[defaultDatasource].meta.id,
};
// If we don't find a default datasource, return undefined
return undefined;
}
function panelQueryKindToSceneQuery(query: PanelQueryKind): SceneDataQuery {
return {
refId: query.spec.refId,
datasource: getRuntimePanelDataSource(query.spec.query),
datasource: getRuntimePanelDataSource(query),
hide: query.spec.hidden,
...query.spec.query.spec,
};

View File

@@ -45,8 +45,8 @@ const getDataSourceMock = jest.fn();
const fakeDsMock: DataSourceApi = {
name: 'fake-std',
type: 'fake-type',
getRef: () => ({ type: 'fake-type', uid: 'fake-uid' }),
type: 'fake-std',
getRef: () => ({ type: 'fake-std', uid: 'fake-std' }),
query: () =>
Promise.resolve({
data: [],
@@ -74,7 +74,7 @@ const fakeDsMock: DataSourceApi = {
toDataQuery: (q) => ({ ...q, refId: 'FakeDataSource-refId' }),
},
id: 1,
uid: 'fake-uid',
uid: 'fake-std',
};
jest.mock('@grafana/runtime', () => ({
@@ -95,7 +95,7 @@ describe('sceneVariablesSetToVariables', () => {
description: 'test-desc',
value: ['selected-value'],
text: ['selected-value-text'],
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
query: 'query',
includeAll: true,
allowCustomValue: true,
@@ -123,8 +123,8 @@ describe('sceneVariablesSetToVariables', () => {
],
},
"datasource": {
"type": "fake-type",
"uid": "fake-uid",
"type": "fake-std",
"uid": "fake-std",
},
"definition": undefined,
"description": "test-desc",
@@ -148,7 +148,7 @@ describe('sceneVariablesSetToVariables', () => {
description: 'test-desc',
value: ['selected-value'],
text: ['selected-value-text'],
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
query: 'query',
definition: 'query',
includeAll: true,
@@ -176,8 +176,8 @@ describe('sceneVariablesSetToVariables', () => {
],
},
"datasource": {
"type": "fake-type",
"uid": "fake-uid",
"type": "fake-std",
"uid": "fake-std",
},
"definition": "query",
"description": "test-desc",
@@ -201,7 +201,7 @@ describe('sceneVariablesSetToVariables', () => {
description: 'test-desc',
value: ['selected-value'],
text: ['selected-value-text'],
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
query: 'query',
options: [
{ label: 'test', value: 'test' },
@@ -228,7 +228,7 @@ describe('sceneVariablesSetToVariables', () => {
description: 'test-desc',
value: ['test'],
text: ['test'],
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
query: 'query',
options: [
{ label: 'test', value: 'test' },
@@ -499,7 +499,7 @@ describe('sceneVariablesSetToVariables', () => {
allowCustomValue: true,
label: 'test-label',
description: 'test-desc',
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
filters: [
{
key: 'filterTest',
@@ -533,8 +533,8 @@ describe('sceneVariablesSetToVariables', () => {
},
],
"datasource": {
"type": "fake-type",
"uid": "fake-uid",
"type": "fake-std",
"uid": "fake-std",
},
"defaultKeys": undefined,
"description": "test-desc",
@@ -662,7 +662,7 @@ describe('sceneVariablesSetToVariables', () => {
allowCustomValue: true,
label: 'test-label',
description: 'test-desc',
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
defaultKeys: [
{
text: 'some',
@@ -710,8 +710,8 @@ describe('sceneVariablesSetToVariables', () => {
},
],
"datasource": {
"type": "fake-type",
"uid": "fake-uid",
"type": "fake-std",
"uid": "fake-std",
},
"defaultKeys": [
{
@@ -757,7 +757,7 @@ describe('sceneVariablesSetToVariables', () => {
label: 'test-label',
description: 'test-desc',
allowCustomValue: true,
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
defaultOptions: [
{
text: 'Foo',
@@ -784,8 +784,8 @@ describe('sceneVariablesSetToVariables', () => {
"value": [],
},
"datasource": {
"type": "fake-type",
"uid": "fake-uid",
"type": "fake-std",
"uid": "fake-std",
},
"defaultValue": undefined,
"description": "test-desc",
@@ -813,7 +813,7 @@ describe('sceneVariablesSetToVariables', () => {
name: 'test',
label: 'test-label',
description: 'test-desc',
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
defaultOptions: [
{
text: 'Foo',
@@ -841,7 +841,7 @@ describe('sceneVariablesSetToVariables', () => {
description: 'test-desc',
value: ['selected-value'],
text: ['selected-value-text'],
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
query: 'query',
includeAll: true,
allValue: 'test-all',
@@ -856,45 +856,44 @@ describe('sceneVariablesSetToVariables', () => {
expect(result).toHaveLength(1);
expect(result[0]).toMatchInlineSnapshot(`
{
"kind": "QueryVariable",
{
"kind": "QueryVariable",
"spec": {
"allValue": "test-all",
"allowCustomValue": true,
"current": {
"text": [
"selected-value-text",
],
"value": [
"selected-value",
],
},
"datasource": {
"type": "fake-std",
"uid": "fake-std",
},
"definition": undefined,
"description": "test-desc",
"hide": "dontHide",
"includeAll": true,
"label": "test-label",
"multi": true,
"name": "test",
"options": [],
"query": {
"kind": "fake-std",
"spec": {
"allValue": "test-all",
"allowCustomValue": true,
"current": {
"text": [
"selected-value-text",
],
"value": [
"selected-value",
],
},
"definition": undefined,
"description": "test-desc",
"hide": "dontHide",
"includeAll": true,
"label": "test-label",
"multi": true,
"name": "test",
"options": [],
"query": {
"datasource": {
"name": "fake-uid",
},
"group": "fake-type",
"kind": "DataQuery",
"spec": {
"__legacyStringValue": "query",
},
"version": "v0",
},
"refresh": "onDashboardLoad",
"regex": "",
"skipUrlSync": false,
"sort": "disabled",
"__legacyStringValue": "query",
},
}
`);
},
"refresh": "onDashboardLoad",
"regex": "",
"skipUrlSync": false,
"sort": "disabled",
},
}
`);
});
it('should handle CustomVariable', () => {
@@ -1153,7 +1152,7 @@ describe('sceneVariablesSetToVariables', () => {
name: 'test',
label: 'test-label',
description: 'test-desc',
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
filters: [
{
key: 'filterTest',
@@ -1189,8 +1188,8 @@ describe('sceneVariablesSetToVariables', () => {
},
],
"datasource": {
"type": "fake-type",
"uid": "fake-uid",
"type": "fake-std",
"uid": "fake-std",
},
"defaultKeys": [],
"description": "test-desc",
@@ -1215,7 +1214,7 @@ describe('sceneVariablesSetToVariables', () => {
name: 'test',
label: 'test-label',
description: 'test-desc',
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
defaultKeys: [
{
text: 'some',
@@ -1265,8 +1264,8 @@ describe('sceneVariablesSetToVariables', () => {
},
],
"datasource": {
"type": "fake-type",
"uid": "fake-uid",
"type": "fake-std",
"uid": "fake-std",
},
"defaultKeys": [
{
@@ -1313,7 +1312,7 @@ describe('sceneVariablesSetToVariables', () => {
name: 'test',
label: 'test-label',
description: 'test-desc',
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
defaultOptions: [
{
text: 'Foo',
@@ -1341,8 +1340,8 @@ describe('sceneVariablesSetToVariables', () => {
"value": [],
},
"datasource": {
"type": "fake-type",
"uid": "fake-uid",
"type": "fake-std",
"uid": "fake-std",
},
"defaultValue": undefined,
"description": "test-desc",
@@ -1373,7 +1372,7 @@ describe('sceneVariablesSetToVariables', () => {
name: 'test',
label: 'test-label',
description: 'test-desc',
datasource: { uid: 'fake-uid', type: 'fake-type' },
datasource: { uid: 'fake-std', type: 'fake-std' },
defaultOptions: [
{
text: 'Foo',

View File

@@ -24,7 +24,6 @@ import {
GroupByVariableKind,
defaultVariableHide,
VariableOption,
defaultDataQueryKind,
AdHocFilterWithLabels,
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen';
@@ -295,30 +294,14 @@ export function sceneVariablesSetToSchemaV2Variables(
}
const query = variable.state.query;
let dataQuery: DataQueryKind | string;
const datasource = getElementDatasource(set, variable, 'variable', undefined, dsReferencesMapping);
if (typeof query !== 'string') {
dataQuery = {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: datasource?.type ?? getDataQueryKind(query),
...(datasource?.uid && {
datasource: {
name: datasource.uid,
},
}),
kind: variable.state.datasource?.type ?? getDataQueryKind(query),
spec: getDataQuerySpec(query),
};
} else {
dataQuery = {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: datasource?.type ?? getDataQueryKind(query),
...(datasource?.uid && {
datasource: {
name: datasource.uid,
},
}),
kind: variable.state.datasource?.type ?? getDataQueryKind(query),
spec: {
[LEGACY_STRING_VALUE_KEY]: query,
},
@@ -332,6 +315,7 @@ export function sceneVariablesSetToSchemaV2Variables(
options,
query: dataQuery,
definition: variable.state.definition,
datasource: getElementDatasource(set, variable, 'variable', undefined, dsReferencesMapping),
sort: transformSortVariableToEnum(variable.state.sort),
refresh: transformVariableRefreshToEnum(variable.state.refresh),
regex: variable.state.regex,

View File

@@ -22,7 +22,6 @@ import {
CustomVariableKind,
Spec as DashboardV2Spec,
DatasourceVariableKind,
defaultDataQueryKind,
GridLayoutItemSpec,
GridLayoutSpec,
GroupByVariableKind,
@@ -139,7 +138,6 @@ describe('transformSaveModelSchemaV2ToScene', () => {
// Variables
const variables = scene.state?.$variables;
expect(variables?.state.variables).toHaveLength(dash.variables.length);
validateVariable({
sceneVariable: variables?.state.variables[0],
variableKind: dash.variables[0] as QueryVariableKind,
@@ -208,26 +206,36 @@ describe('transformSaveModelSchemaV2ToScene', () => {
// Annotations
expect(scene.state.$data).toBeInstanceOf(DashboardDataLayerSet);
const dataLayers = scene.state.$data as DashboardDataLayerSet;
// we should get two annotations, Grafana built-in and the custom ones
expect(dataLayers.state.annotationLayers).toHaveLength(dash.annotations.length);
expect(dataLayers.state.annotationLayers[0].state.name).toBe(dash.annotations[0].spec.name);
expect(dataLayers.state.annotationLayers[0].state.isEnabled).toBe(dash.annotations[0].spec.enable);
expect(dataLayers.state.annotationLayers[0].state.isHidden).toBe(dash.annotations[0].spec.hide);
expect(dataLayers.state.annotationLayers).toHaveLength(5);
// Built-in
const builtInAnnotation = dataLayers.state.annotationLayers[0] as unknown as DashboardAnnotationsDataLayer;
expect(builtInAnnotation.state.name).toBe('Annotations & Alerts');
expect(builtInAnnotation.state.isEnabled).toBe(true);
expect(builtInAnnotation.state.isHidden).toBe(true);
expect(builtInAnnotation.state?.query.builtIn).toBe(1);
// Enabled
expect(dataLayers.state.annotationLayers[1].state.name).toBe(dash.annotations[1].spec.name);
expect(dataLayers.state.annotationLayers[1].state.isEnabled).toBe(dash.annotations[1].spec.enable);
expect(dataLayers.state.annotationLayers[1].state.isHidden).toBe(dash.annotations[1].spec.hide);
// Disabled
expect(dataLayers.state.annotationLayers[2].state.name).toBe(dash.annotations[2].spec.name);
expect(dataLayers.state.annotationLayers[2].state.isEnabled).toBe(dash.annotations[2].spec.enable);
expect(dataLayers.state.annotationLayers[2].state.isHidden).toBe(dash.annotations[2].spec.hide);
// Hidden
// Disabled
expect(dataLayers.state.annotationLayers[3].state.name).toBe(dash.annotations[3].spec.name);
expect(dataLayers.state.annotationLayers[3].state.isEnabled).toBe(dash.annotations[3].spec.enable);
expect(dataLayers.state.annotationLayers[3].state.isHidden).toBe(dash.annotations[3].spec.hide);
// Hidden
expect(dataLayers.state.annotationLayers[4].state.name).toBe(dash.annotations[4].spec.name);
expect(dataLayers.state.annotationLayers[4].state.isEnabled).toBe(dash.annotations[4].spec.enable);
expect(dataLayers.state.annotationLayers[4].state.isHidden).toBe(dash.annotations[4].spec.hide);
// VizPanel
const vizPanels = (scene.state.body as DashboardLayoutManager).getVizPanels();
expect(vizPanels).toHaveLength(2);
@@ -271,14 +279,13 @@ describe('transformSaveModelSchemaV2ToScene', () => {
kind: 'PanelQuery',
spec: {
refId: 'A',
datasource: {
type: 'graphite',
uid: 'datasource1',
},
hidden: false,
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'graphite',
datasource: {
name: 'datasource1',
},
kind: 'prometheus',
spec: {
expr: 'test-query',
},
@@ -300,14 +307,13 @@ describe('transformSaveModelSchemaV2ToScene', () => {
kind: 'PanelQuery',
spec: {
refId: 'A',
datasource: {
type: 'prometheus',
uid: 'datasource1',
},
hidden: false,
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'prometheus',
datasource: {
name: 'datasource1',
},
kind: 'prometheus',
spec: {
expr: 'test-query',
},
@@ -334,12 +340,7 @@ describe('transformSaveModelSchemaV2ToScene', () => {
refId: 'A',
hidden: false,
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'prometheus',
datasource: {
name: 'abc123',
},
kind: 'prometheus',
spec: {
expr: 'test-query',
},
@@ -721,6 +722,10 @@ describe('transformSaveModelSchemaV2ToScene', () => {
enable: true,
hide: false,
iconColor: 'purple',
datasource: {
type: 'prometheus',
uid: 'abc123',
},
legacyOptions: {
expr: 'rate(http_requests_total[5m])',
queryType: 'range',
@@ -728,15 +733,6 @@ describe('transformSaveModelSchemaV2ToScene', () => {
useValueAsTime: true,
step: '1m',
},
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'prometheus',
datasource: {
name: 'abc123',
},
spec: {},
},
},
},
],
@@ -768,35 +764,23 @@ describe('transformSaveModelSchemaV2ToScene', () => {
// Get the annotation layers
const dataLayerSet = scene.state.$data as DashboardDataLayerSet;
expect(dataLayerSet).toBeDefined();
// it should have two annotation layers, built-in and custom
expect(dataLayerSet.state.annotationLayers.length).toBe(2);
const defaultAnnotationLayer = dataLayerSet.state.annotationLayers[0] as DashboardAnnotationsDataLayer;
// Verify that the default annotation layer has been correctly initialized
expect(defaultAnnotationLayer.state.query).toEqual({
datasource: {
uid: '-- Grafana --',
type: 'grafana',
},
builtIn: 1,
enable: true,
iconColor: 'rgba(0, 211, 255, 1)',
name: 'Annotations & Alerts',
hide: true,
type: 'dashboard',
});
const annotationLayer = dataLayerSet.state.annotationLayers[1] as DashboardAnnotationsDataLayer;
// Verify that the legacyOptions have been merged into the query object
expect(annotationLayer.state.query).toMatchObject({
datasource: {
uid: 'abc123',
type: 'prometheus',
},
name: 'Annotation with legacy options',
enable: true,
hide: false,
iconColor: 'purple',
expr: 'rate(http_requests_total[5m])',
queryType: 'range',
legendFormat: '{{method}} {{endpoint}}',
useValueAsTime: true,
step: '1m',
});
// Verify the original legacyOptions object is also preserved
expect(annotationLayer.state.query.legacyOptions).toMatchObject({
expr: 'rate(http_requests_total[5m])',
queryType: 'range',
legendFormat: '{{method}} {{endpoint}}',

View File

@@ -28,7 +28,6 @@ import {
defaultAdhocVariableKind,
defaultConstantVariableKind,
defaultCustomVariableKind,
defaultDataQueryKind,
defaultDatasourceVariableKind,
defaultGroupByVariableKind,
defaultIntervalVariableKind,
@@ -63,7 +62,6 @@ import { DashboardScene } from '../scene/DashboardScene';
import { DashboardLayoutManager } from '../scene/types/DashboardLayoutManager';
import { getIntervalsFromQueryString } from '../utils/utils';
import { transformV2ToV1AnnotationQuery } from './annotations';
import { SnapshotVariable } from './custom-variables/SnapshotVariable';
import { layoutDeserializerRegistry } from './layoutSerializers/layoutSerializerRegistry';
import { getRuntimeVariableDataSource } from './layoutSerializers/utils';
@@ -92,23 +90,32 @@ export function transformSaveModelSchemaV2ToScene(dto: DashboardWithAccessInfo<D
const { spec: dashboard, metadata, apiVersion } = dto;
// annotations might not come with the builtIn Grafana annotation, we need to add it
const grafanaBuiltAnnotation = getGrafanaBuiltInAnnotationDataLayer(dashboard);
if (grafanaBuiltAnnotation) {
dashboard.annotations.unshift(grafanaBuiltAnnotation);
}
const annotationLayers = dashboard.annotations.map((annotation) => {
const annotationQuerySpec = transformV2ToV1AnnotationQuery(annotation);
const layerState = {
let annoQuerySpec = annotation.spec;
// some annotations will contain in the legacyOptions properties that need to be
// added to the root level annotation spec
if (annoQuerySpec?.legacyOptions) {
annoQuerySpec = {
...annoQuerySpec,
...annoQuerySpec.legacyOptions,
};
}
return new DashboardAnnotationsDataLayer({
key: uniqueId('annotations-'),
query: annotationQuerySpec,
query: {
...annoQuerySpec,
builtIn: annotation.spec.builtIn ? 1 : 0,
},
name: annotation.spec.name,
isEnabled: Boolean(annotation.spec.enable),
isHidden: Boolean(annotation.spec.hide),
};
return new DashboardAnnotationsDataLayer(layerState);
});
});
const isDashboardEditable = Boolean(dashboard.editable);
@@ -507,15 +514,7 @@ function getGrafanaBuiltInAnnotationDataLayer(dashboard: DashboardV2Spec) {
const grafanaBuiltAnnotation: AnnotationQueryKind = {
kind: 'AnnotationQuery',
spec: {
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'grafana',
datasource: {
name: '-- Grafana --',
},
spec: {},
},
datasource: { uid: '-- Grafana --', type: 'grafana' },
name: 'Annotations & Alerts',
iconColor: DEFAULT_ANNOTATION_COLOR,
enable: true,

View File

@@ -57,7 +57,6 @@ import {
validateDashboardSchemaV2,
getDataQueryKind,
getAutoAssignedDSRef,
getVizPanelQueries,
} from './transformSceneToSaveModelSchemaV2';
// Mock dependencies
@@ -411,7 +410,9 @@ describe('transformSceneToSaveModelSchemaV2', () => {
expect(result).toMatchSnapshot();
// Check that the annotation layers are correctly transformed
expect(result.annotations).toHaveLength(2);
expect(result.annotations).toHaveLength(3);
// Check annotation layer 3 without initial data source isn't updated with runtime default
expect(result.annotations?.[2].spec.datasource?.type).toBe(undefined);
});
it('should transform the minimum scene to save model schema v2', () => {
@@ -561,8 +562,16 @@ describe('transformSceneToSaveModelSchemaV2', () => {
name: 'annotation-with-options',
enable: true,
iconColor: 'red',
customProp1: true,
customProp2: 'test',
legacyOptions: {
expr: 'rate(http_requests_total[5m])',
queryType: 'range',
legendFormat: '{{method}} {{endpoint}}',
useValueAsTime: true,
},
// Some other properties that aren't in the annotation spec
// and should be moved to options
customProp1: 'value1',
customProp2: 'value2',
},
name: 'layerWithOptions',
isEnabled: true,
@@ -584,11 +593,19 @@ describe('transformSceneToSaveModelSchemaV2', () => {
expect(result.annotations.length).toBe(1);
expect(result.annotations[0].spec.legacyOptions).toBeDefined();
expect(result.annotations[0].spec.legacyOptions).toEqual({
customProp1: true,
customProp2: 'test',
expr: 'rate(http_requests_total[5m])',
queryType: 'range',
legendFormat: '{{method}} {{endpoint}}',
useValueAsTime: true,
customProp1: 'value1',
customProp2: 'value2',
});
// Ensure these properties are not at the root level
expect(result).not.toHaveProperty('annotations[0].spec.expr');
expect(result).not.toHaveProperty('annotations[0].spec.queryType');
expect(result).not.toHaveProperty('annotations[0].spec.legendFormat');
expect(result).not.toHaveProperty('annotations[0].spec.useValueAsTime');
expect(result).not.toHaveProperty('annotations[0].spec.customProp1');
expect(result).not.toHaveProperty('annotations[0].spec.customProp2');
});
@@ -817,50 +834,6 @@ describe('getElementDatasource', () => {
});
});
describe('getVizPanelQueries', () => {
it('should handle panel query datasources correctly', () => {
const queryWithDS: SceneDataQuery = {
refId: 'B',
datasource: { uid: 'prometheus-uid', type: 'prometheus' },
};
const queryWithoutDS: SceneDataQuery = {
refId: 'A',
};
// Mock query runner
const queryRunner = new SceneQueryRunner({
queries: [queryWithoutDS, queryWithDS],
datasource: { uid: 'default-ds', type: 'default' },
});
// Create test elements
const vizPanel = new VizPanel({
key: 'panel-1',
pluginId: 'timeseries',
$data: queryRunner,
});
// Mock dsReferencesMapping
const dsReferencesMapping = {
panels: new Map(new Set([['panel-1', new Set<string>(['A'])]])),
variables: new Set<string>(),
annotations: new Set<string>(),
};
const result = getVizPanelQueries(vizPanel, dsReferencesMapping);
expect(result.length).toBe(2);
expect(result[0].spec.query.kind).toBe('DataQuery');
expect(result[0].spec.query.datasource).toBeUndefined(); // ignore datasource if it wasn't provided
expect(result[0].spec.query.group).toBe('default');
expect(result[0].spec.query.version).toBe('v0');
expect(result[1].spec.query.kind).toBe('DataQuery');
expect(result[1].spec.query.datasource?.name).toBe('prometheus-uid');
expect(result[1].spec.query.group).toBe('prometheus');
expect(result[1].spec.query.version).toBe('v0');
});
});
function getMinimalSceneState(body: DashboardLayoutManager): Partial<DashboardSceneState> {
return {
id: 1,
@@ -1092,6 +1065,18 @@ function createAnnotationLayers() {
isEnabled: true,
isHidden: true,
}),
// this could happen if a dahboard was created from code and the datasource was not defined
new DashboardAnnotationsDataLayer({
key: 'layer3',
query: {
name: 'query3',
enable: true,
iconColor: 'green',
},
name: 'layer3',
isEnabled: true,
isHidden: true,
}),
];
}

View File

@@ -43,7 +43,6 @@ import {
DashboardCursorSync,
FieldConfig,
FieldColor,
defaultDataQueryKind,
} from '../../../../../packages/grafana-schema/src/schema/dashboard/v2alpha1/types.spec.gen';
import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet';
import { DashboardScene, DashboardSceneState } from '../scene/DashboardScene';
@@ -52,7 +51,6 @@ import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
import { getLibraryPanelBehavior, getPanelIdForVizPanel, getQueryRunnerFor, isLibraryPanel } from '../utils/utils';
import { DSReferencesMapping } from './DashboardSceneSerializer';
import { transformV1ToV2AnnotationQuery } from './annotations';
import { sceneVariablesSetToSchemaV2Variables } from './sceneVariablesSetToVariables';
import { colorIdEnumToColorIdV2, transformCursorSynctoEnum } from './transformToV2TypesUtils';
@@ -252,7 +250,7 @@ function getPanelLinks(panel: VizPanel): DataLink[] {
return [];
}
export function getVizPanelQueries(vizPanel: VizPanel, dsReferencesMapping?: DSReferencesMapping): PanelQueryKind[] {
function getVizPanelQueries(vizPanel: VizPanel, dsReferencesMapping?: DSReferencesMapping): PanelQueryKind[] {
const queries: PanelQueryKind[] = [];
const queryRunner = getQueryRunnerFor(vizPanel);
const vizPanelQueries = queryRunner?.state.queries;
@@ -260,22 +258,12 @@ export function getVizPanelQueries(vizPanel: VizPanel, dsReferencesMapping?: DSR
if (vizPanelQueries) {
vizPanelQueries.forEach((query) => {
const queryDatasource = getElementDatasource(vizPanel, query, 'panel', queryRunner, dsReferencesMapping);
const dataQuery: DataQueryKind = {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: getDataQueryKind(query, queryRunner),
datasource: {
name: queryDatasource?.uid,
},
kind: getDataQueryKind(query, queryRunner),
spec: omit(query, 'datasource', 'refId', 'hide'),
};
if (!dataQuery.datasource?.name) {
delete dataQuery.datasource;
}
const querySpec: PanelQuerySpec = {
datasource: queryDatasource,
query: dataQuery,
refId: query.refId,
hidden: Boolean(query.hide),
@@ -419,46 +407,78 @@ function getAnnotations(state: DashboardSceneState, dsReferencesMapping?: DSRefe
if (!(layer instanceof dataLayers.AnnotationsDataLayer)) {
continue;
}
const result: AnnotationQueryKind = {
kind: 'AnnotationQuery',
spec: {
builtIn: Boolean(layer.state.query.builtIn),
name: layer.state.query.name,
datasource: getElementDatasource(layer, layer.state.query, 'annotation', undefined, dsReferencesMapping),
enable: Boolean(layer.state.isEnabled),
hide: Boolean(layer.state.isHidden),
iconColor: layer.state.query.iconColor,
},
};
const datasource = getElementDatasource(layer, layer.state.query, 'annotation', undefined, dsReferencesMapping);
let layerDs = layer.state.query.datasource;
if (!layerDs) {
// This can happen only if we are transforming a scene that was created
// from a v1 spec. In v1 annotation layer can contain no datasource ref, which is guaranteed
// for layers created for v2 schema. See transform transformSaveModelSchemaV2ToScene.ts.
// In this case we will resolve default data source
layerDs = getDefaultDataSourceRef();
console.error(
'Misconfigured AnnotationsDataLayer: Data source is required for annotations. Resolving default data source',
layer,
layerDs
);
// Transform v1 dashboard (using target) to v2 structure
// adds extra condition to prioritize query over target
// if query is defined, use it
if (layer.state.query.target && !layer.state.query.query) {
// Handle built-in annotations
if (layer.state.query.builtIn) {
result.spec.query = {
kind: 'grafana', // built-in annotations are always of type grafana
spec: {
...layer.state.query.target,
},
};
} else {
result.spec.query = {
kind: getAnnotationQueryKind(layer.state.query),
spec: {
...layer.state.query.target,
},
};
}
}
// For annotations without query.query defined (e.g., grafana annotations without tags)
else if (layer.state.query.query?.kind) {
result.spec.query = {
kind: layer.state.query.query.kind,
spec: {
...layer.state.query.query.spec,
},
};
}
// Collect datasource-specific properties not in standard annotation spec
let otherProps = omit(
layer.state.query,
'type',
'target',
'builtIn',
'name',
'datasource',
'iconColor',
'enable',
'hide',
'filter',
'query'
);
const result = transformV1ToV2AnnotationQuery(layer.state.query, layerDs.type!, layerDs.uid!, {
enable: layer.state.isEnabled,
hide: layer.state.isHidden,
});
const annotationQuery = layer.state.query;
// Store extra properties in the legacyOptions field instead of directly in the spec
if (Object.keys(otherProps).length > 0) {
// Extract options property and get the rest of the properties
const { legacyOptions, ...restProps } = otherProps;
// Merge options with the rest of the properties
result.spec.legacyOptions = { ...legacyOptions, ...restProps };
}
// If filter is an empty array, don't save it
if (annotationQuery.filter?.ids?.length) {
result.spec.filter = annotationQuery.filter;
}
// Finally, if the datasource references mapping did not containt data source ref,
// this means that the original model that was fetched did not contain it. In such scenario we don't want to save
// the explicit data source reference, so lets remove it from the save model.
if (!datasource) {
delete result.spec.query.datasource;
if (layer.state.query.filter?.ids?.length) {
result.spec.filter = layer.state.query.filter;
}
annotations.push(result);
}
return annotations;
}

View File

@@ -5,7 +5,6 @@ import { locationService, reportInteraction } from '@grafana/runtime';
import {
AnnotationQueryKind,
Spec as DashboardV2Spec,
defaultDataQueryKind,
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen';
import { Form } from 'app/core/components/Form/Form';
import { getDashboardAPI } from 'app/features/dashboard/api/dashboard_api';
@@ -17,8 +16,6 @@ import { ImportDashboardFormV2 } from './ImportDashboardFormV2';
const IMPORT_FINISHED_EVENT_NAME = 'dashboard_import_imported';
type FormData = SaveDashboardCommand<DashboardV2Spec> & { [key: `datasource-${string}`]: string };
export function ImportDashboardOverviewV2() {
const [uidReset, setUidReset] = useState(false);
const dispatch = useDispatch();
@@ -37,29 +34,24 @@ export function ImportDashboardOverviewV2() {
dispatch(clearLoadedDashboard());
}
async function onSubmit(form: FormData) {
async function onSubmit(form: SaveDashboardCommand<DashboardV2Spec>) {
reportInteraction(IMPORT_FINISHED_EVENT_NAME);
const dashboardWithDataSources: DashboardV2Spec = {
...dashboard,
title: form.dashboard.title,
annotations: dashboard.annotations?.map((annotation: AnnotationQueryKind) => {
const dsType = annotation.spec.query?.spec.group;
if (dsType) {
if (annotation.spec.query?.kind) {
const dsType = annotation.spec.query.kind;
if (form[`datasource-${dsType}` as keyof typeof form]) {
const ds = form[`datasource-${dsType}` as keyof typeof form] as { uid: string; type: string };
return {
...annotation,
spec: {
...annotation.spec,
query: {
kind: 'DataQuery',
group: dsType,
version: defaultDataQueryKind().version,
datasource: { name: ds.uid },
spec: {
...annotation.spec.query?.spec,
},
datasource: {
uid: ds.uid,
type: ds.type,
},
},
};
@@ -69,23 +61,18 @@ export function ImportDashboardOverviewV2() {
}),
variables: dashboard.variables?.map((variable) => {
if (variable.kind === 'QueryVariable') {
const dsType = variable.spec.query?.spec.group;
if (dsType) {
if (variable.spec.query?.kind) {
const dsType = variable.spec.query.kind;
if (form[`datasource-${dsType}` as keyof typeof form]) {
const ds = form[`datasource-${dsType}` as keyof typeof form] as { uid: string; type: string };
return {
...variable,
spec: {
...variable.spec,
query: {
...variable.spec.query,
spec: {
...variable.spec.query.spec,
group: ds.type,
datasource: {
name: ds.uid,
},
},
datasource: {
...variable.spec.datasource,
uid: ds.uid,
type: ds.type,
},
options: [],
current: {
@@ -170,7 +157,7 @@ export function ImportDashboardOverviewV2() {
return (
<>
<Form<FormData>
<Form<SaveDashboardCommand<DashboardV2Spec> & { [key: `datasource-${string}`]: string }>
onSubmit={onSubmit}
defaultValues={{ dashboard, k8s: { annotations: { 'grafana.app/folder': folder.uid } } }}
validateOnMount

View File

@@ -52,8 +52,7 @@ export function validateVariable<
expect(sceneVariable?.state.pluginId).toBe(variableKind.spec.pluginId);
}
if (sceneVariable instanceof QueryVariable && variableKind.kind === 'QueryVariable') {
expect(sceneVariable?.state.datasource?.type).toBe(variableKind.spec.query?.group);
expect(sceneVariable?.state.datasource?.uid).toBe(variableKind.spec.query?.datasource?.name);
expect(sceneVariable?.state.datasource).toBe(variableKind.spec.datasource);
expect(sceneVariable?.state.query).toEqual(variableKind.spec.query.spec);
}
if (sceneVariable instanceof CustomVariable && variableKind.kind === 'CustomVariable') {

View File

@@ -2,7 +2,6 @@ import { AnnotationQuery, DataQuery, VariableModel, VariableRefresh, Panel } fro
import { handyTestingSchema } from '@grafana/schema/dist/esm/schema/dashboard/v2_examples';
import {
Spec as DashboardV2Spec,
defaultDataQueryKind,
GridLayoutItemKind,
GridLayoutKind,
PanelKind,
@@ -467,14 +466,10 @@ describe('ResponseTransformers', () => {
{
kind: 'PanelQuery',
spec: {
datasource: 'datasource1',
hidden: false,
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'prometheus',
datasource: {
name: 'datasource1',
},
kind: 'prometheus',
spec: {
expr: 'test-query',
},
@@ -978,9 +973,11 @@ describe('ResponseTransformers', () => {
result.forEach((query) => {
expect(query.kind).toBe('PanelQuery');
expect(query.spec.query.group).toEqual('theoretical-ds');
expect(query.spec.query.datasource?.name).toEqual('theoretical-uid');
expect(query.spec.query.kind).toBe('DataQuery');
expect(query.spec.datasource).toEqual({
type: 'theoretical-ds',
uid: 'theoretical-uid',
});
expect(query.spec.query.kind).toBe('theoretical-ds');
});
});
@@ -1006,9 +1003,11 @@ describe('ResponseTransformers', () => {
result.forEach((query) => {
expect(query.kind).toBe('PanelQuery');
expect(query.spec.query.group).toEqual('theoretical-ds');
expect(query.spec.query.datasource?.name).toEqual('theoretical-uid');
expect(query.spec.query.kind).toBe('DataQuery');
expect(query.spec.datasource).toEqual({
type: 'theoretical-ds',
uid: 'theoretical-uid',
});
expect(query.spec.query.kind).toBe('theoretical-ds');
});
});
});
@@ -1016,14 +1015,14 @@ describe('ResponseTransformers', () => {
function validateAnnotation(v1: AnnotationQuery, v2: DashboardV2Spec['annotations'][0]) {
const { spec: v2Spec } = v2;
expect(v1.name).toBe(v2Spec.name);
expect(v1.datasource?.type).toBe(v2Spec.query.group);
expect(v1.datasource?.uid).toBe(v2Spec.query.datasource?.name);
expect(v1.datasource).toBe(v2Spec.datasource);
expect(v1.enable).toBe(v2Spec.enable);
expect(v1.hide).toBe(v2Spec.hide);
expect(v1.iconColor).toBe(v2Spec.iconColor);
expect(v1.builtIn).toBe(v2Spec.builtIn ? 1 : undefined);
expect(v1.target).toEqual(v2Spec.query.spec);
expect(v1.builtIn).toBe(v2Spec.builtIn ? 1 : 0);
expect(v1.target).toBe(v2Spec.query?.spec);
expect(v1.filter).toEqual(v2Spec.filter);
}
@@ -1044,10 +1043,7 @@ describe('ResponseTransformers', () => {
return {
refId: q.spec.refId,
hide: q.spec.hidden,
datasource: {
type: q.spec.query.spec.group,
uid: q.spec.query.spec.datasource?.uid,
},
datasource: q.spec.datasource,
...q.spec.query.spec,
};
})
@@ -1097,24 +1093,18 @@ describe('ResponseTransformers', () => {
};
expect(v2Common).toEqual(v1Common);
if (v2.kind === 'QueryVariable') {
expect(v2.spec.query).toMatchObject({
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: (v1.datasource?.type || getDefaultDataSourceRef()?.type) ?? 'grafana',
...(v1.datasource?.uid && {
datasource: {
name: v1.datasource?.uid,
},
}),
});
expect(v2.spec.datasource).toEqual(v1.datasource);
if (typeof v1.query === 'string') {
expect(v2.spec.query.spec).toEqual({
[LEGACY_STRING_VALUE_KEY]: v1.query,
});
expect(v2.spec.query.spec[LEGACY_STRING_VALUE_KEY]).toEqual(v1.query);
} else {
expect(v2.spec.query.spec).toEqual({
...(typeof v1.query === 'object' ? v1.query : {}),
expect(v2.spec.query).toEqual({
kind: v1.datasource?.type,
spec: {
...(typeof v1.query === 'object' ? v1.query : {}),
},
});
}
}

View File

@@ -38,7 +38,6 @@ import {
LibraryPanelKind,
PanelKind,
GridLayoutItemKind,
defaultDataQueryKind,
RowsLayoutRowKind,
GridLayoutKind,
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen';
@@ -56,7 +55,6 @@ import {
DeprecatedInternalId,
ObjectMeta,
} from 'app/features/apiserver/types';
import { transformV2ToV1AnnotationQuery } from 'app/features/dashboard-scene/serialization/annotations';
import { GRID_ROW_HEIGHT } from 'app/features/dashboard-scene/serialization/const';
import { validateFiltersOrigin } from 'app/features/dashboard-scene/serialization/sceneVariablesSetToVariables';
import { TypedVariableModelV2 } from 'app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene';
@@ -504,13 +502,9 @@ export function getPanelQueries(targets: DataQuery[], panelDatasource: DataSourc
spec: {
refId: t.refId,
hidden: t.hide ?? false,
datasource: t.datasource ? t.datasource : panelDatasource,
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: t.datasource?.type || panelDatasource.type!,
datasource: {
name: t.datasource?.uid || panelDatasource.uid!,
},
kind: t.datasource?.type || panelDatasource.type!,
spec: {
...query,
},
@@ -574,12 +568,7 @@ function getVariables(vars: TypedVariableModel[]): DashboardV2Spec['variables']
regex: v.regex || '',
sort: transformSortVariableToEnum(v.sort),
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: v.datasource?.type ?? getDefaultDatasourceType(),
datasource: {
name: v.datasource?.uid,
},
kind: v.datasource?.type || getDefaultDatasourceType(),
spec: query,
},
allowCustomValue: v.allowCustomValue ?? true,
@@ -733,12 +722,7 @@ function getAnnotations(annotations: AnnotationQuery[]): DashboardV2Spec['annota
iconColor: a.iconColor,
builtIn: Boolean(a.builtIn),
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: a.datasource?.type || getDefaultDatasourceType(),
datasource: {
name: a.datasource?.uid,
},
kind: a.datasource?.type || getDefaultDatasourceType(),
spec: {
...a.target,
},
@@ -773,10 +757,7 @@ function getVariablesV1(vars: DashboardV2Spec['variables']): VariableModel[] {
LEGACY_STRING_VALUE_KEY in v.spec.query.spec
? v.spec.query.spec[LEGACY_STRING_VALUE_KEY]
: v.spec.query.spec,
datasource: {
type: v.spec.query?.spec.group,
uid: v.spec.query?.spec.datasource?.name,
},
datasource: v.spec.datasource,
sort: transformSortVariableToEnumV1(v.spec.sort),
refresh: transformVariableRefreshToEnumV1(v.spec.refresh),
regex: v.spec.regex,
@@ -893,6 +874,22 @@ function getVariablesV1(vars: DashboardV2Spec['variables']): VariableModel[] {
return variables;
}
function getAnnotationsV1(annotations: DashboardV2Spec['annotations']): AnnotationQuery[] {
// @ts-expect-error - target v2 query is not compatible with v1 target
return annotations.map((a) => {
return {
name: a.spec.name,
datasource: a.spec.datasource,
enable: a.spec.enable,
hide: a.spec.hide,
iconColor: a.spec.iconColor,
builtIn: a.spec.builtIn ? 1 : 0,
target: a.spec.query?.spec,
filter: a.spec.filter,
};
});
}
interface LibraryPanelDTO extends Pick<Panel, 'libraryPanel' | 'id' | 'title' | 'gridPos' | 'type'> {}
function getPanelsV1(
@@ -953,10 +950,7 @@ function transformV2PanelToV1Panel(
return {
refId: q.spec.refId,
hide: q.spec.hidden,
datasource: {
uid: q.spec.query.spec.datasource?.uid,
type: q.spec.query.spec.group,
},
datasource: q.spec.datasource,
...q.spec.query.spec,
};
}),
@@ -1140,8 +1134,7 @@ function transformToV1VariableTypes(variable: TypedVariableModelV2): VariableTyp
}
export function transformDashboardV2SpecToV1(spec: DashboardV2Spec, metadata: ObjectMeta): DashboardDataDTO {
const annotations = spec.annotations.map(transformV2ToV1AnnotationQuery);
const annotations = getAnnotationsV1(spec.annotations);
const variables = getVariablesV1(spec.variables);
const panels = getPanelsV1(spec.elements, spec.layout);
return {

View File

@@ -7,7 +7,6 @@ import {
defaultSpec as defaultDashboardV2Spec,
defaultPanelSpec,
defaultQueryVariableSpec,
defaultDataQueryKind,
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen';
import { browseDashboardsAPI } from 'app/features/browse-dashboards/api/browseDashboardsAPI';
import { getLibraryPanel } from 'app/features/library-panels/state/api';
@@ -837,9 +836,7 @@ describe('processV2Datasources', () => {
refId: 'A',
hidden: false,
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'prometheus',
kind: 'prometheus',
spec: {
expr: 'access_evaluation_duration_count',
range: true,
@@ -865,9 +862,7 @@ describe('processV2Datasources', () => {
...defaultQueryVariableSpec(),
name: 'var1',
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'loki',
kind: 'loki',
spec: {
expr: 'access_evaluation_duration_count',
range: true,
@@ -885,9 +880,7 @@ describe('processV2Datasources', () => {
hide: false,
iconColor: 'red',
query: {
kind: 'DataQuery',
version: defaultDataQueryKind().version,
group: 'loki',
kind: 'loki',
spec: {
expr: 'access_evaluation_duration_count',
range: true,
@@ -989,17 +982,13 @@ describe('processV2DatasourceInput', () => {
...defaultQueryVariableSpec(),
name: 'var2WithGrafanaDs',
query: {
kind: 'DataQuery' as const,
version: defaultDataQueryKind().version,
group: 'grafana',
kind: 'grafana',
spec: {
expr: 'access_evaluation_duration_count',
range: true,
panelId: 2,
},
},
},
};
const result = await processV2DatasourceInput(queryVariable.spec, {});
expect(result).toEqual({});
});
@@ -1012,9 +1001,7 @@ describe('processV2DatasourceInput', () => {
refId: 'A',
hidden: false,
query: {
kind: 'DataQuery' as const,
version: defaultDataQueryKind().version,
group: 'datasource',
kind: 'datasource',
spec: {
panelId: 2,
},

View File

@@ -168,7 +168,6 @@ export function processV2Datasources(dashboard: DashboardV2Spec): ThunkResult<vo
if (element.kind !== 'Panel') {
throw new Error('Only panels are currenlty supported in v2 dashboards');
}
if (element.spec.data.spec.queries.length > 0) {
for (const query of element.spec.data.spec.queries) {
inputs = await processV2DatasourceInput(query.spec, inputs);
@@ -333,43 +332,43 @@ export function getFolderByUid(uid: string): Promise<{ uid: string; title: strin
}
export async function processV2DatasourceInput(
spec: PanelQueryKind['spec'] | QueryVariableKind['spec'] | AnnotationQueryKind['spec'],
obj: PanelQueryKind['spec'] | QueryVariableKind['spec'] | AnnotationQueryKind['spec'],
inputs: Record<string, DataSourceInput> = {}
) {
const datasourceRef = spec.query.datasource;
let dataSourceInput: DataSourceInput | undefined;
const dsType = spec.query.group;
if (!datasourceRef) {
const datasourceRef = obj?.datasource;
if (!datasourceRef && obj?.query) {
const dsType = obj.query.kind;
// if dsType is grafana, it means we are using a built-in annotation or default grafana datasource, in those
// cases we don't need to map it
// "datasource" type is what we call "--Dashboard--" datasource <.-.>
if (dsType === 'grafana' || dsType === 'datasource') {
return inputs;
}
}
const datasource = await getDatasourceSrv().get({ type: dsType });
let dataSourceInput: DataSourceInput | undefined;
if (datasource) {
dataSourceInput = {
name: datasource.name,
label: datasource.name,
info: `Select a ${datasource.name} data source`,
value: datasource.uid,
type: InputType.DataSource,
pluginId: datasource.meta?.id,
};
const datasource = await getDatasourceSrv().get({ type: dsType });
if (datasource) {
dataSourceInput = {
name: datasource.name,
label: datasource.name,
info: `Select a ${datasource.name} data source`,
value: datasource.uid,
type: InputType.DataSource,
pluginId: datasource.meta?.id,
};
inputs[datasource.meta?.id] = dataSourceInput;
} else {
dataSourceInput = {
name: dsType,
label: dsType,
info: `No data sources of type ${dsType} found`,
value: '',
type: InputType.DataSource,
pluginId: dsType,
};
inputs[dsType] = dataSourceInput;
inputs[datasource.meta?.id] = dataSourceInput;
} else {
dataSourceInput = {
name: dsType,
label: dsType,
info: `No data sources of type ${dsType} found`,
value: '',
type: InputType.DataSource,
pluginId: dsType,
};
inputs[dsType] = dataSourceInput;
}
}
return inputs;
}

View File

@@ -5,5 +5,5 @@ Utilities / functions for working with dagger pipelines
def with_dagger_install(commands = [], dagger_version = ""):
return [
"wget -qO- https://github.com/dagger/dagger/releases/download/{}/dagger_{}_linux_amd64.tar.gz | tar zx -C /bin".format(dagger_version, dagger_version),
"apk add docker",
"apk add docker bash",
] + commands

View File

@@ -210,11 +210,25 @@ def rgm_main():
)
def rgm_tag():
# Runs a package / build process (with all distros) when a tag is made
"""Tag release pipeline that builds and packages all distributions.
Returns:
Drone pipeline.
"""
generate_token_step = github_app_generate_token_step()
build_steps = rgm_run("rgm-build", "drone_build_tag_grafana.sh")
# Add dependency on token generation step
for step in build_steps:
step["depends_on"] = [generate_token_step["name"]]
steps = [generate_token_step] + build_steps
return pipeline(
name = "rgm-tag-prerelease",
trigger = tag_trigger,
steps = rgm_run("rgm-build", "drone_build_tag_grafana.sh"),
steps = steps,
volumes = github_app_step_volumes() + github_app_pipeline_volumes(),
)
def rgm_version_branch():