Compare commits
46
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4e61faae9 | ||
|
|
e6f0107923 | ||
|
|
bbd0fbe9d0 | ||
|
|
633c9a9cb0 | ||
|
|
66259bdede | ||
|
|
a6952b554f | ||
|
|
083c7f31f7 | ||
|
|
ec74a721ea | ||
|
|
e821578ab0 | ||
|
|
ad9f9fc408 | ||
|
|
a5638b5c8b | ||
|
|
e00eb854f5 | ||
|
|
82b283959b | ||
|
|
374cb1b163 | ||
|
|
9321ca2019 | ||
|
|
db0b35f6df | ||
|
|
a1a73dde66 | ||
|
|
c7727eb25c | ||
|
|
4c75ea918a | ||
|
|
a553256b46 | ||
|
|
faabe2e46d | ||
|
|
d6e81c6334 | ||
|
|
7e6b5505f0 | ||
|
|
dd3f085648 | ||
|
|
b6784c4354 | ||
|
|
441556d1a3 | ||
|
|
32da63a20f | ||
|
|
da5af29218 | ||
|
|
9d928a3ac6 | ||
|
|
b79ace082c | ||
|
|
b6d34acc44 | ||
|
|
ddb4690633 | ||
|
|
749cc735bb | ||
|
|
7888f19443 | ||
|
|
c7e8291bd1 | ||
|
|
e9883f6c61 | ||
|
|
fcceff99e2 | ||
|
|
cad9e1c5f3 | ||
|
|
2dfcaf9be8 | ||
|
|
c4f2f3f6f4 | ||
|
|
100fb26d27 | ||
|
|
f6df949bc3 | ||
|
|
a5103784fe | ||
|
|
890fc1ea79 | ||
|
|
e6b12f865f | ||
|
|
703e93d103 |
@@ -1101,6 +1101,7 @@ eslint-suppressions.json @grafanabot
|
||||
# Grafana Sharing Squad
|
||||
/public/app/features/dashboard-scene/sharing/ @grafana/sharing-squad
|
||||
/public/app/features/dashboard/components/ShareModal/ @grafana/sharing-squad
|
||||
/public/app/features/dashboard/dashgrid/DashboardLibrary/ @grafana/sharing-squad
|
||||
/public/app/features/manage-dashboards/components/SnapshotListTable.tsx @grafana/sharing-squad
|
||||
/pkg/services/dashboardsnapshots/ @grafana/sharing-squad
|
||||
/public/app/features/explore/QueryLibrary/ @grafana/sharing-squad
|
||||
|
||||
@@ -8,7 +8,9 @@ name: "CodeQL checks"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: ['**'] # run on all branches
|
||||
branches:
|
||||
- main
|
||||
- release-*.*.*
|
||||
paths-ignore:
|
||||
- '**/*.cue'
|
||||
- '**/*.json'
|
||||
@@ -74,6 +76,7 @@ jobs:
|
||||
name: Set go version
|
||||
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00
|
||||
with:
|
||||
cache: false
|
||||
go-version-file: go.mod
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
|
||||
@@ -178,6 +178,10 @@ jobs:
|
||||
run: |
|
||||
extract_error_message='ERROR! API client generation failed!'
|
||||
yarn generate-apis || (echo "${extract_error_message}" && false)
|
||||
- name: Generate Enterprise API clients
|
||||
run: |
|
||||
extract_error_message='ERROR! API client generation failed!'
|
||||
yarn generate-enterprise-apis || (echo "${extract_error_message}" && false)
|
||||
- name: Verify generated clients
|
||||
run: |
|
||||
uncommited_error_message="ERROR! API client generation has not been committed. Please run 'yarn generate-apis', commit the changes and push again."
|
||||
@@ -187,3 +191,13 @@ jobs:
|
||||
echo "${uncommited_error_message}"
|
||||
exit 1
|
||||
fi
|
||||
- name: Verify generated enterprise clients
|
||||
run: |
|
||||
uncommited_error_message="ERROR! Enterprise API client generation has not been committed. Please run 'yarn generate-enterprise-apis', commit the changes and push again."
|
||||
cd ../grafana-enterprise
|
||||
file_diff="$(git diff)"
|
||||
if [ -n "$file_diff" ]; then
|
||||
echo "$file_diff"
|
||||
echo "${uncommited_error_message}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -212,6 +212,7 @@ jobs:
|
||||
run-id: ${{ github.run_id }}
|
||||
bucket-path: ${{ needs.setup.outputs.version }}_${{ github.run_id }}
|
||||
environment: prod
|
||||
runs-on: ubuntu-x64-small
|
||||
|
||||
publish-dockerhub:
|
||||
if: github.ref_name == 'main'
|
||||
|
||||
+4
-4
@@ -10,7 +10,7 @@ require (
|
||||
github.com/grafana/grafana v0.0.0-00010101000000-000000000000
|
||||
github.com/grafana/grafana-app-sdk v0.48.2
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.1
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
k8s.io/apimachinery v0.34.2
|
||||
@@ -160,7 +160,7 @@ require (
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect
|
||||
github.com/grafana/sqlds/v4 v4.2.7 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
@@ -232,7 +232,7 @@ require (
|
||||
github.com/prometheus/alertmanager v0.28.0 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/common/sigv4 v0.1.0 // indirect
|
||||
github.com/prometheus/exporter-toolkit v0.14.0 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
@@ -279,7 +279,7 @@ require (
|
||||
golang.org/x/exp v0.0.0-20251002181428-27f1f14c8bb9 // indirect
|
||||
golang.org/x/mod v0.30.0 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 // indirect
|
||||
|
||||
+8
-8
@@ -667,8 +667,8 @@ github.com/grafana/grafana-aws-sdk v1.3.0 h1:/bfJzP93rCel1GbWoRSq0oUo424MZXt8jAp
|
||||
github.com/grafana/grafana-aws-sdk v1.3.0/go.mod h1:VGycF0JkCGKND2O5je1ucOqPJ0ZNhZYzV3c2bNBAaGk=
|
||||
github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1 h1:FFcEA01tW+SmuJIuDbHOdgUBL+d7DPrZ2N4zwzPhfGk=
|
||||
github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1/go.mod h1:Oi4anANlCuTCc66jCyqIzfVbgLXFll8Wja+Y4vfANlc=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0 h1:V8dGyatzcOLQeivFhBV2JWMwTSZH/clDnpfKG9p3dTA=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0/go.mod h1:3I0g+v6jAwVmrt6BEjDUP4V6pkhGP5QKY5NkXY4Ayr4=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0 h1:9JT9E6T0h8HsK9emTZ5s01uCKaf0Ok4PjYbb7M/iOjM=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0/go.mod h1:20qhoYxIgbZRmwCEO1KMP8q2yq/Kge5+xE/99/hLEk0=
|
||||
github.com/grafana/grafana/pkg/promlib v0.0.8 h1:VUWsqttdf0wMI4j9OX9oNrykguQpZcruudDAFpJJVw0=
|
||||
github.com/grafana/grafana/pkg/promlib v0.0.8/go.mod h1:U1ezG/MGaEPoThqsr3lymMPN5yIPdVTJnDZ+wcXT+ao=
|
||||
github.com/grafana/grafana/pkg/semconv v0.0.0-20250804150913-990f1c69ecc2 h1:A65jWgLk4Re28gIuZcpC0aTh71JZ0ey89hKGE9h543s=
|
||||
@@ -687,8 +687,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDa
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
|
||||
@@ -1046,8 +1046,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4=
|
||||
github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI=
|
||||
github.com/prometheus/exporter-toolkit v0.14.0 h1:NMlswfibpcZZ+H0sZBiTjrA3/aBFHkNZqE+iCj5EmRg=
|
||||
@@ -1420,8 +1420,8 @@ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -38,6 +38,7 @@ require (
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
@@ -59,7 +60,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
@@ -85,7 +86,7 @@ require (
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
|
||||
@@ -77,8 +77,8 @@ github.com/grafana/grafana-app-sdk/logging v0.48.1 h1:veM0X5LAPyN3KsDLglWjIofndb
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.1/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
|
||||
@@ -140,8 +140,8 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
@@ -239,8 +239,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -5,7 +5,7 @@ go 1.25.3
|
||||
require (
|
||||
github.com/grafana/grafana-app-sdk v0.48.2
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.1
|
||||
github.com/prometheus/common v0.67.1
|
||||
github.com/prometheus/common v0.67.2
|
||||
k8s.io/apimachinery v0.34.2
|
||||
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912
|
||||
)
|
||||
@@ -68,7 +68,7 @@ require (
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
|
||||
@@ -104,8 +104,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
|
||||
@@ -165,8 +165,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -49,7 +49,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
@@ -68,7 +68,7 @@ require (
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
|
||||
@@ -104,8 +104,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
|
||||
@@ -165,8 +165,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -49,7 +49,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
@@ -68,7 +68,7 @@ require (
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
|
||||
@@ -104,8 +104,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
|
||||
@@ -165,8 +165,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -7,7 +7,7 @@ require (
|
||||
github.com/grafana/authlib/types v0.0.0-20250926065801-df98203cff37
|
||||
github.com/grafana/grafana-app-sdk v0.48.2
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.1
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/stretchr/testify v1.11.1
|
||||
@@ -51,7 +51,7 @@ require (
|
||||
github.com/grafana/otel-profiling-go v0.5.1 // indirect
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
@@ -84,7 +84,7 @@ require (
|
||||
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
@@ -110,7 +110,7 @@ require (
|
||||
golang.org/x/exp v0.0.0-20251002181428-27f1f14c8bb9 // indirect
|
||||
golang.org/x/mod v0.30.0 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 // indirect
|
||||
|
||||
@@ -89,8 +89,8 @@ github.com/grafana/grafana-app-sdk v0.48.2 h1:CQQDhwo1fWaXQVKvxxOcK6azbuY3E2TgJH
|
||||
github.com/grafana/grafana-app-sdk v0.48.2/go.mod h1:LDOvQ7OOyHLcXdSa0InATCa5OMoYAd6E1+rGLrMgHuk=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.1 h1:veM0X5LAPyN3KsDLglWjIofndbGuf7MqnrDuDN+F/Ng=
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.1/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0 h1:V8dGyatzcOLQeivFhBV2JWMwTSZH/clDnpfKG9p3dTA=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0/go.mod h1:3I0g+v6jAwVmrt6BEjDUP4V6pkhGP5QKY5NkXY4Ayr4=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0 h1:9JT9E6T0h8HsK9emTZ5s01uCKaf0Ok4PjYbb7M/iOjM=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0/go.mod h1:20qhoYxIgbZRmwCEO1KMP8q2yq/Kge5+xE/99/hLEk0=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e/go.mod h1:IA4SOwun8QyST9c5UNs/fN37XL6boXXDvRYFcFwbipg=
|
||||
github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8=
|
||||
@@ -99,8 +99,8 @@ github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasn
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@@ -202,8 +202,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/protocolbuffers/txtpbfmt v0.0.0-20241112170944-20d2c9ebc01d h1:HWfigq7lB31IeJL8iy7jkUmU/PG1Sr8jVGhS749dbUA=
|
||||
@@ -294,8 +294,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
|
||||
)
|
||||
|
||||
func RegisterConversions(s *runtime.Scheme, dsIndexProvider schemaversion.DataSourceIndexProvider) error {
|
||||
func RegisterConversions(s *runtime.Scheme, dsIndexProvider schemaversion.DataSourceIndexProvider, _ schemaversion.LibraryElementIndexProvider) error {
|
||||
// Wrap the provider once with 10s caching for all conversions.
|
||||
// This prevents repeated DB queries across multiple conversion calls while allowing
|
||||
// the cache to refresh periodically, making it suitable for long-lived singleton usage.
|
||||
|
||||
@@ -828,11 +828,12 @@ func TestWithConversionValidation_DataLoss(t *testing.T) {
|
||||
func TestDataLossDetectionOnAllInputFiles(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := testutil.NewDataSourceProvider(testutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := testutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
err := RegisterConversions(scheme, dsProvider)
|
||||
err := RegisterConversions(scheme, dsProvider, leProvider)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Read all files from input directory
|
||||
|
||||
@@ -33,7 +33,8 @@ import (
|
||||
func TestConversionMatrixExist(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
versions := []metav1.Object{
|
||||
&dashv0.Dashboard{Spec: common.Unstructured{Object: map[string]any{"title": "dashboardV0"}}},
|
||||
@@ -43,7 +44,7 @@ func TestConversionMatrixExist(t *testing.T) {
|
||||
}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := RegisterConversions(scheme, dsProvider)
|
||||
err := RegisterConversions(scheme, dsProvider, leProvider)
|
||||
require.NoError(t, err)
|
||||
|
||||
for idx, in := range versions {
|
||||
@@ -85,11 +86,12 @@ func TestDeepCopyValid(t *testing.T) {
|
||||
func TestDashboardConversionToAllVersions(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
err := RegisterConversions(scheme, dsProvider)
|
||||
err := RegisterConversions(scheme, dsProvider, leProvider)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Read all files from input directory
|
||||
@@ -244,11 +246,12 @@ func TestDashboardConversionToAllVersions(t *testing.T) {
|
||||
func TestMigratedDashboardsConversion(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
err := RegisterConversions(scheme, dsProvider)
|
||||
err := RegisterConversions(scheme, dsProvider, leProvider)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Read all files from migration package's latest_version directory
|
||||
@@ -378,7 +381,8 @@ func testConversion(t *testing.T, convertedDash metav1.Object, filename, outputD
|
||||
func TestConversionMetrics(t *testing.T) {
|
||||
// Initialize migration with test providers
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -386,7 +390,7 @@ func TestConversionMetrics(t *testing.T) {
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
err := RegisterConversions(scheme, dsProvider)
|
||||
err := RegisterConversions(scheme, dsProvider, leProvider)
|
||||
require.NoError(t, err)
|
||||
|
||||
tests := []struct {
|
||||
@@ -505,7 +509,8 @@ func TestConversionMetrics(t *testing.T) {
|
||||
// TestConversionMetricsWrapper tests the withConversionMetrics wrapper function
|
||||
func TestConversionMetricsWrapper(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -673,7 +678,8 @@ func TestSchemaVersionExtraction(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Test the schema version extraction logic by creating a wrapper and checking the metrics labels
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -717,7 +723,8 @@ func TestSchemaVersionExtraction(t *testing.T) {
|
||||
// TestConversionLogging tests that conversion-level logging works correctly
|
||||
func TestConversionLogging(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -725,7 +732,7 @@ func TestConversionLogging(t *testing.T) {
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
err := RegisterConversions(scheme, dsProvider)
|
||||
err := RegisterConversions(scheme, dsProvider, leProvider)
|
||||
require.NoError(t, err)
|
||||
|
||||
tests := []struct {
|
||||
@@ -808,7 +815,8 @@ func TestConversionLogging(t *testing.T) {
|
||||
// TestConversionLogLevels tests that appropriate log levels are used
|
||||
func TestConversionLogLevels(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
t.Run("log levels and structured fields verification", func(t *testing.T) {
|
||||
// Create test wrapper to verify logging behavior
|
||||
@@ -879,7 +887,8 @@ func TestConversionLogLevels(t *testing.T) {
|
||||
// TestConversionLoggingFields tests that all expected fields are included in log messages
|
||||
func TestConversionLoggingFields(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
t.Run("verify all log fields are present", func(t *testing.T) {
|
||||
// Test that the conversion wrapper includes all expected structured fields
|
||||
|
||||
@@ -19,7 +19,8 @@ import (
|
||||
func TestV0ConversionErrorHandling(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -130,7 +131,8 @@ func TestV0ConversionErrorHandling(t *testing.T) {
|
||||
func TestV0ConversionErrorPropagation(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
t.Run("ConvertDashboard_V0_to_V1beta1 returns error on migration failure", func(t *testing.T) {
|
||||
source := &dashv0.Dashboard{
|
||||
@@ -203,7 +205,8 @@ func TestV0ConversionErrorPropagation(t *testing.T) {
|
||||
func TestV0ConversionSuccessPaths(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
t.Run("Convert_V0_to_V1beta1 success path returns nil", func(t *testing.T) {
|
||||
source := &dashv0.Dashboard{
|
||||
@@ -271,7 +274,8 @@ func TestV0ConversionSuccessPaths(t *testing.T) {
|
||||
func TestV0ConversionSecondStepErrors(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
t.Run("Convert_V0_to_V2alpha1 sets status on first step error", func(t *testing.T) {
|
||||
// Create a dashboard that will fail v0->v1beta1 conversion
|
||||
|
||||
@@ -18,7 +18,8 @@ import (
|
||||
func TestV1ConversionErrorHandling(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
migration.Initialize(dsProvider)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
|
||||
t.Run("Convert_V1beta1_to_V2alpha1 sets status on conversion error", func(t *testing.T) {
|
||||
// Create a dashboard that will cause conversion to fail
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
)
|
||||
|
||||
// Initialize provides the migrator singleton with required dependencies and builds the map of migrations.
|
||||
func Initialize(dsIndexProvider schemaversion.DataSourceIndexProvider) {
|
||||
migratorInstance.init(dsIndexProvider)
|
||||
func Initialize(dsIndexProvider schemaversion.DataSourceIndexProvider, leIndexProvider schemaversion.LibraryElementIndexProvider) {
|
||||
migratorInstance.init(dsIndexProvider, leIndexProvider)
|
||||
}
|
||||
|
||||
// GetDataSourceIndexProvider returns the datasource index provider instance that was initialized.
|
||||
@@ -20,12 +20,20 @@ func GetDataSourceIndexProvider() schemaversion.DataSourceIndexProvider {
|
||||
return migratorInstance.dsIndexProvider
|
||||
}
|
||||
|
||||
// GetLibraryElementIndexProvider returns the library element index provider instance that was initialized.
|
||||
func GetLibraryElementIndexProvider() schemaversion.LibraryElementIndexProvider {
|
||||
// Wait for initialization to complete
|
||||
<-migratorInstance.ready
|
||||
return migratorInstance.leIndexProvider
|
||||
}
|
||||
|
||||
// ResetForTesting resets the migrator singleton for testing purposes.
|
||||
func ResetForTesting() {
|
||||
migratorInstance = &migrator{
|
||||
migrations: map[int]schemaversion.SchemaVersionMigrationFunc{},
|
||||
ready: make(chan struct{}),
|
||||
dsIndexProvider: nil,
|
||||
leIndexProvider: nil,
|
||||
}
|
||||
initOnce = sync.Once{}
|
||||
}
|
||||
@@ -48,12 +56,14 @@ type migrator struct {
|
||||
ready chan struct{}
|
||||
migrations map[int]schemaversion.SchemaVersionMigrationFunc
|
||||
dsIndexProvider schemaversion.DataSourceIndexProvider
|
||||
leIndexProvider schemaversion.LibraryElementIndexProvider
|
||||
}
|
||||
|
||||
func (m *migrator) init(dsIndexProvider schemaversion.DataSourceIndexProvider) {
|
||||
func (m *migrator) init(dsIndexProvider schemaversion.DataSourceIndexProvider, leIndexProvider schemaversion.LibraryElementIndexProvider) {
|
||||
initOnce.Do(func() {
|
||||
m.dsIndexProvider = dsIndexProvider
|
||||
m.migrations = schemaversion.GetMigrations(dsIndexProvider)
|
||||
m.leIndexProvider = leIndexProvider
|
||||
m.migrations = schemaversion.GetMigrations(dsIndexProvider, leIndexProvider)
|
||||
close(m.ready)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ const DEV_DASHBOARDS_OUTPUT_DIR = "testdata/dev-dashboards-output"
|
||||
func TestMigrate(t *testing.T) {
|
||||
// Reset the migration singleton and use the same datasource provider as the frontend test to ensure consistency
|
||||
ResetForTesting()
|
||||
Initialize(migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig))
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
Initialize(dsProvider, leProvider)
|
||||
|
||||
t.Run("minimum version check", func(t *testing.T) {
|
||||
err := Migrate(context.Background(), map[string]interface{}{
|
||||
@@ -45,7 +47,9 @@ func TestMigrate(t *testing.T) {
|
||||
|
||||
func TestMigrateSingleVersion(t *testing.T) {
|
||||
// Use the same datasource provider as the frontend test to ensure consistency
|
||||
Initialize(migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig))
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
Initialize(dsProvider, leProvider)
|
||||
|
||||
runSingleVersionMigrationTests(t, SINGLE_VERSION_OUTPUT_DIR)
|
||||
}
|
||||
@@ -212,7 +216,9 @@ func loadDashboard(t *testing.T, path string) map[string]interface{} {
|
||||
// TestSchemaMigrationMetrics tests that schema migration metrics are recorded correctly
|
||||
func TestSchemaMigrationMetrics(t *testing.T) {
|
||||
// Initialize migration with test providers
|
||||
Initialize(migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig))
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
Initialize(dsProvider, leProvider)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -296,7 +302,9 @@ func TestSchemaMigrationMetrics(t *testing.T) {
|
||||
|
||||
// TestSchemaMigrationLogging tests that schema migration logging works correctly
|
||||
func TestSchemaMigrationLogging(t *testing.T) {
|
||||
Initialize(migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig))
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
Initialize(dsProvider, leProvider)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -413,7 +421,9 @@ func TestMigrateDevDashboards(t *testing.T) {
|
||||
// Reset the migration singleton and use the dev dashboard datasource provider
|
||||
// to match the frontend devDashboardDataSources configuration
|
||||
ResetForTesting()
|
||||
Initialize(migrationtestutil.NewDataSourceProvider(migrationtestutil.DevDashboardConfig))
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.DevDashboardConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
Initialize(dsProvider, leProvider)
|
||||
|
||||
runDevDashboardMigrationTests(t, schemaversion.LATEST_VERSION, DEV_DASHBOARDS_OUTPUT_DIR)
|
||||
}
|
||||
|
||||
@@ -27,12 +27,27 @@ type DataSourceIndexProvider interface {
|
||||
Index(ctx context.Context) *DatasourceIndex
|
||||
}
|
||||
|
||||
type LibraryElementInfo struct {
|
||||
UID string
|
||||
Name string
|
||||
Kind int64
|
||||
Type string
|
||||
Description string
|
||||
FolderUID string
|
||||
}
|
||||
|
||||
type LibraryElementIndexProvider interface {
|
||||
|
||||
// GetLibraryElementInfo returns library element information for use in migrations.
|
||||
GetLibraryElementInfo(ctx context.Context) []LibraryElementInfo
|
||||
}
|
||||
|
||||
type PanelPluginInfo struct {
|
||||
ID string
|
||||
Version string
|
||||
}
|
||||
|
||||
func GetMigrations(dsIndexProvider DataSourceIndexProvider) map[int]SchemaVersionMigrationFunc {
|
||||
func GetMigrations(dsIndexProvider DataSourceIndexProvider, _ LibraryElementIndexProvider) map[int]SchemaVersionMigrationFunc {
|
||||
return map[int]SchemaVersionMigrationFunc{
|
||||
2: V2,
|
||||
3: V3,
|
||||
|
||||
@@ -6,6 +6,19 @@ import (
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
|
||||
)
|
||||
|
||||
// EmptyLibraryElementProvider provides an empty library element list for tests
|
||||
type EmptyLibraryElementProvider struct{}
|
||||
|
||||
// NewLibraryElementProvider creates a new empty library element provider for tests
|
||||
func NewLibraryElementProvider() *EmptyLibraryElementProvider {
|
||||
return &EmptyLibraryElementProvider{}
|
||||
}
|
||||
|
||||
// GetLibraryElementInfo returns an empty list for tests
|
||||
func (p *EmptyLibraryElementProvider) GetLibraryElementInfo(_ context.Context) []schemaversion.LibraryElementInfo {
|
||||
return []schemaversion.LibraryElementInfo{}
|
||||
}
|
||||
|
||||
// DataSourceConfig defines different test configurations
|
||||
type DataSourceConfig string
|
||||
|
||||
|
||||
+2
-2
@@ -56,7 +56,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
@@ -75,7 +75,7 @@ require (
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.44.0 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
|
||||
+4
-4
@@ -116,8 +116,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
|
||||
@@ -179,8 +179,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
+2
-2
@@ -40,7 +40,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
@@ -51,7 +51,7 @@ require (
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
|
||||
+4
-4
@@ -85,8 +85,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
@@ -128,8 +128,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -50,7 +50,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
@@ -69,7 +69,7 @@ require (
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
|
||||
@@ -104,8 +104,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
|
||||
@@ -165,8 +165,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -51,7 +51,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
@@ -70,7 +70,7 @@ require (
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
|
||||
@@ -104,8 +104,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
|
||||
@@ -165,8 +165,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -51,7 +51,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
@@ -70,7 +70,7 @@ require (
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
|
||||
@@ -104,8 +104,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
|
||||
@@ -165,8 +165,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
+2
-2
@@ -58,7 +58,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
@@ -77,7 +77,7 @@ require (
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.44.0 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
|
||||
+4
-4
@@ -116,8 +116,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
|
||||
@@ -179,8 +179,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -41,7 +41,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/woodsbury/decimal128 v1.3.0 // indirect
|
||||
@@ -51,7 +51,7 @@ require (
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
|
||||
@@ -85,8 +85,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
@@ -128,8 +128,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -13,7 +13,7 @@ require (
|
||||
github.com/grafana/nanogit v0.0.0-20251106115617-c622d3e0fc4b
|
||||
github.com/migueleliasweb/go-github-mock v1.1.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
golang.org/x/oauth2 v0.32.0
|
||||
golang.org/x/oauth2 v0.33.0
|
||||
k8s.io/apimachinery v0.34.2
|
||||
k8s.io/apiserver v0.34.2
|
||||
k8s.io/client-go v0.34.2
|
||||
@@ -57,7 +57,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
|
||||
@@ -113,8 +113,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
@@ -172,8 +172,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -209,6 +209,8 @@ type FindScopeNavigationsResults struct {
|
||||
type ScopeNavigationSpec struct {
|
||||
URL string `json:"url"`
|
||||
Scope string `json:"scope"`
|
||||
// Used to navigate to a sub-scope of the main scope. URL will not be used if this is set.
|
||||
SubScope string `json:"subScope,omitempty"`
|
||||
}
|
||||
|
||||
// Type of the item.
|
||||
|
||||
@@ -635,6 +635,13 @@ func schema_pkg_apis_scope_v0alpha1_ScopeNavigationSpec(ref common.ReferenceCall
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"subScope": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Used to navigate to a sub-scope of the main scope. URL will not be used if this is set.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"url", "scope"},
|
||||
},
|
||||
|
||||
+2
-2
@@ -45,7 +45,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/woodsbury/decimal128 v1.3.0 // indirect
|
||||
@@ -56,7 +56,7 @@ require (
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
|
||||
+4
-4
@@ -89,8 +89,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
@@ -140,8 +140,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -56,7 +56,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
@@ -75,7 +75,7 @@ require (
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.44.0 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
|
||||
@@ -116,8 +116,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
|
||||
@@ -179,8 +179,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -218,6 +218,12 @@ delete_auto_gen_ids = false
|
||||
# Improves startup performance for instances with large numbers of annotations who do not plan to downgrade Grafana.
|
||||
skip_dashboard_uid_migration_on_startup = false
|
||||
|
||||
# Set to true to skip all database migrations on startup. Should be used in conjunction with "ensure_default_org_and_user".
|
||||
skip_migrations = false
|
||||
|
||||
# Set to false to skip ensuring the default organization and user on startup.
|
||||
ensure_default_org_and_user = true
|
||||
|
||||
#################################### Cache server #############################
|
||||
[remote_cache]
|
||||
# Either "redis", "memcached" or "database" default is "database"
|
||||
|
||||
@@ -65,6 +65,8 @@ services:
|
||||
- 'alloy.logs=true'
|
||||
environment:
|
||||
OTEL_BSP_SCHEDULE_DELAY: 500
|
||||
GF_DATABASE_SKIP_MIGRATIONS: true
|
||||
GF_DATABASE_ENSURE_DEFAULT_ORG_AND_USER: false
|
||||
GF_DEFAULT_APP_MODE: development
|
||||
GF_DEFAULT_TARGET: frontend-server
|
||||
GF_SECURITY_CONTENT_SECURITY_POLICY: false
|
||||
|
||||
@@ -1,29 +1,58 @@
|
||||
scopes:
|
||||
app1:
|
||||
title: Application 1
|
||||
shoe-org:
|
||||
title: Shoe organization
|
||||
filters:
|
||||
- key: organization
|
||||
operator: equals
|
||||
value: shoe
|
||||
|
||||
shoes:
|
||||
title: Shoes
|
||||
filters:
|
||||
- key: product
|
||||
operator: equals
|
||||
value: shoes
|
||||
|
||||
apparel:
|
||||
title: Apparel
|
||||
filters:
|
||||
- key: product
|
||||
operator: equals
|
||||
value: apparel
|
||||
|
||||
frontend:
|
||||
title: Frontend
|
||||
filters:
|
||||
- key: team
|
||||
operator: equals
|
||||
value: frontend
|
||||
|
||||
database:
|
||||
title: Database
|
||||
filters:
|
||||
- key: team
|
||||
operator: equals
|
||||
value: database
|
||||
|
||||
main-app:
|
||||
title: Main App
|
||||
filters:
|
||||
- key: app
|
||||
operator: equals
|
||||
value: app1
|
||||
value: main
|
||||
|
||||
app2:
|
||||
title: Application 2
|
||||
kids-app:
|
||||
title: Kids App
|
||||
filters:
|
||||
- key: app
|
||||
operator: equals
|
||||
value: app2
|
||||
|
||||
cluster1:
|
||||
title: Cluster 1
|
||||
filters:
|
||||
- key: cluster
|
||||
operator: equals
|
||||
value: cluster1
|
||||
value: kids
|
||||
|
||||
tree:
|
||||
gdev-scopes:
|
||||
title: gdev-scopes
|
||||
nodeType: container
|
||||
disableMultiSelect: true
|
||||
children:
|
||||
production:
|
||||
title: Production
|
||||
@@ -54,7 +83,6 @@ tree:
|
||||
nodeType: leaf
|
||||
linkId: test-case-2
|
||||
linkType: scope
|
||||
|
||||
clusters:
|
||||
title: Clusters
|
||||
nodeType: container
|
||||
@@ -66,19 +94,139 @@ tree:
|
||||
nodeType: leaf
|
||||
linkId: cluster1
|
||||
linkType: scope
|
||||
shoe-org-root:
|
||||
title: Shoe organization
|
||||
subTitle: Nested scopes navigation
|
||||
nodeType: leaf
|
||||
linkId: shoe-org
|
||||
linkType: scope
|
||||
|
||||
navigations:
|
||||
# Example: Link to a dashboard
|
||||
app1-nav:
|
||||
url: /d/86Js1xRmk
|
||||
scope: app1
|
||||
navigationTree:
|
||||
- name: global-overview
|
||||
title: Global overview
|
||||
url: /d/TkZXxlNG3
|
||||
scope: shoe-org
|
||||
|
||||
# Example: Link to a dashboard with full URL (already has /d/)
|
||||
app2-nav:
|
||||
url: /d/GlAqcPgmz
|
||||
scope: app2
|
||||
- name: reliability-placeholder
|
||||
title: Reliability
|
||||
url: /d/dcb9f5e9-8066-4397-889e-864b99555dbb
|
||||
scope: shoe-org
|
||||
groups:
|
||||
- Reliability
|
||||
|
||||
# Example: Custom URL path
|
||||
custom-nav:
|
||||
url: /explore
|
||||
scope: app1
|
||||
- name: shoes
|
||||
title: Shoes
|
||||
url: /d/_5rDmaQiz
|
||||
scope: shoe-org
|
||||
subScope: shoes
|
||||
children:
|
||||
- name: shoes-overview
|
||||
title: Overview
|
||||
url: /d/5SdHCadmz
|
||||
scope: shoes
|
||||
|
||||
- name: shoes-team-overview
|
||||
title: Team Overview
|
||||
url: /d/EJ8_d9jZk
|
||||
scope: shoes
|
||||
|
||||
- name: shoes-frontend
|
||||
title: Frontend
|
||||
url: /d/edediimbjhdz4b
|
||||
scope: shoes
|
||||
subScope: frontend
|
||||
children:
|
||||
- name: frontend-api
|
||||
title: API Metrics
|
||||
url: /d/5Y0jv6pVz
|
||||
scope: frontend
|
||||
|
||||
- name: frontend-ui
|
||||
title: UI Performance
|
||||
url: /d/2xuwrgV7z
|
||||
scope: frontend
|
||||
- name: frontend-shoes
|
||||
title: Nested shoes
|
||||
url: /d/5SdHCadmz
|
||||
scope: frontend
|
||||
subScope: shoes # This should be filtered out since 'shoes' is already in the path
|
||||
|
||||
- name: shoes-database
|
||||
title: Database
|
||||
url: /d/lVE-2YFMz
|
||||
scope: shoes
|
||||
subScope: database
|
||||
children:
|
||||
- name: database-connections
|
||||
title: Database Connections
|
||||
url: /d/mIJjFy8Kz
|
||||
scope: database
|
||||
|
||||
- name: database-replication
|
||||
title: Database Replication
|
||||
url: /d/fdn48fmz8f94wc
|
||||
scope: database
|
||||
|
||||
- name: shoes-main-app
|
||||
title: Main App
|
||||
url: /d/WZ7AhQiVz
|
||||
scope: shoes
|
||||
subScope: main-app
|
||||
children:
|
||||
- name: main-app-users
|
||||
title: User Analytics
|
||||
url: /d/a6801696-cc53-4196-b1f9-2403e3909185
|
||||
scope: main-app
|
||||
|
||||
- name: main-app-revenue
|
||||
title: Revenue Metrics
|
||||
url: /d/imQX6j-Gz
|
||||
scope: main-app
|
||||
|
||||
- name: shoes-kids-app
|
||||
title: Kids App
|
||||
url: /d/bds35fot3cv7kb
|
||||
scope: shoes
|
||||
subScope: kids-app
|
||||
children:
|
||||
- name: kids-app-features
|
||||
title: Feature Usage
|
||||
url: /d/16f11TZWk
|
||||
scope: kids-app
|
||||
|
||||
- name: kids-app-engagement
|
||||
title: User Engagement
|
||||
url: /d/c01bf42b-b783-4447-a304-8554cee1843b
|
||||
scope: kids-app
|
||||
|
||||
- name: apparel
|
||||
title: Apparel
|
||||
url: /d/UTv--wqMk
|
||||
scope: shoe-org
|
||||
subScope: apparel
|
||||
children:
|
||||
- name: apparel-product-overview
|
||||
title: Product Overview
|
||||
url: /d/Kp9Z0hTik
|
||||
scope: apparel
|
||||
|
||||
- name: all-teams-placeholder
|
||||
title: All Teams
|
||||
url: /d/b36b5576-2e3d-4b0c-8dce-e79514d99345
|
||||
scope: shoe-org
|
||||
groups:
|
||||
- Discovered dashboards
|
||||
children:
|
||||
- name: others-placeholder
|
||||
title: Others
|
||||
url: /d/xtY_uCAiz
|
||||
scope: shoe-org
|
||||
groups:
|
||||
- All Teams
|
||||
children:
|
||||
- name: latency-and-errors
|
||||
title: Latency and Errors
|
||||
url: /d/ZqZnVvFZz
|
||||
scope: shoe-org
|
||||
groups:
|
||||
- Others
|
||||
|
||||
+196
-13
@@ -43,9 +43,10 @@ func getEnv(key, defaultValue string) string {
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Scopes map[string]ScopeConfig `yaml:"scopes"`
|
||||
Tree map[string]TreeNode `yaml:"tree"`
|
||||
Navigations map[string]NavigationConfig `yaml:"navigations"`
|
||||
Scopes map[string]ScopeConfig `yaml:"scopes"`
|
||||
Tree map[string]TreeNode `yaml:"tree"`
|
||||
Navigations map[string]NavigationConfig `yaml:"navigations"`
|
||||
NavigationTree []NavigationTreeNode `yaml:"navigationTree"`
|
||||
}
|
||||
|
||||
// ScopeConfig is used for YAML parsing - converts to v0alpha1.ScopeSpec
|
||||
@@ -64,16 +65,32 @@ type ScopeFilterConfig struct {
|
||||
|
||||
// TreeNode is used for YAML parsing - converts to v0alpha1.ScopeNodeSpec
|
||||
type TreeNode struct {
|
||||
Title string `yaml:"title"`
|
||||
NodeType string `yaml:"nodeType"`
|
||||
LinkID string `yaml:"linkId,omitempty"`
|
||||
LinkType string `yaml:"linkType,omitempty"`
|
||||
Children map[string]TreeNode `yaml:"children,omitempty"`
|
||||
Title string `yaml:"title"`
|
||||
SubTitle string `yaml:"subTitle,omitempty"`
|
||||
NodeType string `yaml:"nodeType"`
|
||||
LinkID string `yaml:"linkId,omitempty"`
|
||||
LinkType string `yaml:"linkType,omitempty"`
|
||||
DisableMultiSelect bool `yaml:"disableMultiSelect,omitempty"`
|
||||
Children map[string]TreeNode `yaml:"children,omitempty"`
|
||||
}
|
||||
|
||||
type NavigationConfig struct {
|
||||
URL string `yaml:"url"` // URL path (e.g., /d/abc123 or /explore)
|
||||
Scope string `yaml:"scope"`
|
||||
URL string `yaml:"url"` // URL path (e.g., /d/abc123 or /explore)
|
||||
Scope string `yaml:"scope"` // Required scope
|
||||
SubScope string `yaml:"subScope"` // Optional subScope for hierarchical navigation
|
||||
Title string `yaml:"title"` // Display title
|
||||
Groups []string `yaml:"groups"` // Optional groups for categorization
|
||||
}
|
||||
|
||||
// NavigationTreeNode represents a node in the navigation tree structure
|
||||
type NavigationTreeNode struct {
|
||||
Name string `yaml:"name"`
|
||||
Title string `yaml:"title"`
|
||||
URL string `yaml:"url"`
|
||||
Scope string `yaml:"scope"`
|
||||
SubScope string `yaml:"subScope,omitempty"`
|
||||
Groups []string `yaml:"groups,omitempty"`
|
||||
Children []NavigationTreeNode `yaml:"children,omitempty"`
|
||||
}
|
||||
|
||||
// Helper function to convert ScopeFilterConfig to v0alpha1.ScopeFilter
|
||||
@@ -156,6 +173,41 @@ func (c *Client) makeRequest(method, endpoint string, body []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) getScopeNavigation(name string) (*v0alpha1.ScopeNavigation, error) {
|
||||
url := fmt.Sprintf("%s/apis/%s/namespaces/%s/scopenavigations/%s", c.baseURL, apiVersion, c.namespace, name)
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.SetBasicAuth(strings.Split(c.auth, ":")[0], strings.Split(c.auth, ":")[1])
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
||||
return nil, fmt.Errorf("API request failed: HTTP %d - %s", resp.StatusCode, string(bodyBytes))
|
||||
}
|
||||
|
||||
bodyBytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
|
||||
var navigation v0alpha1.ScopeNavigation
|
||||
if err := json.Unmarshal(bodyBytes, &navigation); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
||||
}
|
||||
|
||||
return &navigation, nil
|
||||
}
|
||||
|
||||
func (c *Client) createScope(name string, cfg ScopeConfig) error {
|
||||
prefixedName := prefix + "-" + name
|
||||
|
||||
@@ -206,8 +258,9 @@ func (c *Client) createScopeNode(name string, node TreeNode, parentName string)
|
||||
|
||||
spec := v0alpha1.ScopeNodeSpec{
|
||||
Title: node.Title,
|
||||
SubTitle: node.SubTitle,
|
||||
NodeType: nodeType,
|
||||
DisableMultiSelect: false,
|
||||
DisableMultiSelect: node.DisableMultiSelect,
|
||||
}
|
||||
|
||||
if prefixedParent != "" {
|
||||
@@ -241,17 +294,34 @@ func (c *Client) createScopeNode(name string, node TreeNode, parentName string)
|
||||
|
||||
func (c *Client) createScopeNavigation(name string, nav NavigationConfig) error {
|
||||
prefixedName := prefix + "-" + name
|
||||
prefixedScope := prefix + "-" + nav.Scope
|
||||
|
||||
if nav.URL == "" {
|
||||
return fmt.Errorf("navigation %s must have 'url' specified", name)
|
||||
}
|
||||
|
||||
if nav.Scope == "" {
|
||||
return fmt.Errorf("navigation %s must have 'scope' specified", name)
|
||||
}
|
||||
|
||||
prefixedScope := prefix + "-" + nav.Scope
|
||||
|
||||
spec := v0alpha1.ScopeNavigationSpec{
|
||||
URL: nav.URL,
|
||||
Scope: prefixedScope,
|
||||
}
|
||||
|
||||
if nav.SubScope != "" {
|
||||
prefixedSubScope := prefix + "-" + nav.SubScope
|
||||
spec.SubScope = prefixedSubScope
|
||||
}
|
||||
|
||||
status := v0alpha1.ScopeNavigationStatus{
|
||||
Title: nav.Title,
|
||||
}
|
||||
if len(nav.Groups) > 0 {
|
||||
status.Groups = nav.Groups
|
||||
}
|
||||
|
||||
resource := v0alpha1.ScopeNavigation{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: apiVersion,
|
||||
@@ -269,7 +339,99 @@ func (c *Client) createScopeNavigation(name string, nav NavigationConfig) error
|
||||
}
|
||||
|
||||
fmt.Printf("✓ Creating scope navigation: %s\n", prefixedName)
|
||||
return c.makeRequest("POST", "/scopenavigations", body)
|
||||
if err := c.makeRequest("POST", "/scopenavigations", body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update status in a second request (status is a subresource)
|
||||
if nav.Title != "" || len(nav.Groups) > 0 {
|
||||
// Get the created resource to retrieve its resourceVersion and existing spec
|
||||
createdNav, err := c.getScopeNavigation(prefixedName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get created navigation: %w", err)
|
||||
}
|
||||
|
||||
statusResource := v0alpha1.ScopeNavigation{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: apiVersion,
|
||||
Kind: "ScopeNavigation",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: prefixedName,
|
||||
ResourceVersion: createdNav.ObjectMeta.ResourceVersion,
|
||||
},
|
||||
Spec: createdNav.Spec, // Include existing spec to prevent it from being cleared
|
||||
Status: status,
|
||||
}
|
||||
|
||||
statusBody, err := json.Marshal(statusResource)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal scope navigation status: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf(" Updating status for: %s\n", prefixedName)
|
||||
return c.makeRequest("PUT", fmt.Sprintf("/scopenavigations/%s/status", prefixedName), statusBody)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NavigationWithName pairs a navigation config with its name and title
|
||||
type NavigationWithName struct {
|
||||
Name string
|
||||
Title string
|
||||
Nav NavigationConfig
|
||||
}
|
||||
|
||||
// Convert navigation tree to flat navigations (similar to mock's treeToNavigations)
|
||||
func treeToNavigations(node NavigationTreeNode, parentPath []string, dashboardCounter *int) []NavigationWithName {
|
||||
navigations := []NavigationWithName{}
|
||||
currentPath := append(parentPath, node.Name)
|
||||
|
||||
// Generate URL if not provided (cycle through dash-1, dash-2, etc.)
|
||||
url := node.URL
|
||||
if url == "" {
|
||||
*dashboardCounter++
|
||||
url = fmt.Sprintf("/d/dash-%d", *dashboardCounter)
|
||||
}
|
||||
|
||||
// Create navigation for this node
|
||||
nav := NavigationConfig{
|
||||
URL: url,
|
||||
Scope: node.Scope,
|
||||
Title: node.Title,
|
||||
}
|
||||
if node.SubScope != "" {
|
||||
nav.SubScope = node.SubScope
|
||||
}
|
||||
if len(node.Groups) > 0 {
|
||||
nav.Groups = node.Groups
|
||||
}
|
||||
navigations = append(navigations, NavigationWithName{
|
||||
Name: node.Name,
|
||||
Title: node.Title,
|
||||
Nav: nav,
|
||||
})
|
||||
|
||||
// Process children - they inherit the parent's subScope as their scope, or use parent's scope if no subScope
|
||||
if len(node.Children) > 0 {
|
||||
for _, child := range node.Children {
|
||||
// Children inherit the parent's subScope as their scope, or use parent's scope if no subScope
|
||||
childScope := node.SubScope
|
||||
if childScope == "" {
|
||||
childScope = node.Scope
|
||||
}
|
||||
// Override with child's scope if explicitly set
|
||||
if child.Scope != "" {
|
||||
childScope = child.Scope
|
||||
} else {
|
||||
child.Scope = childScope
|
||||
}
|
||||
navigations = append(navigations, treeToNavigations(child, currentPath, dashboardCounter)...)
|
||||
}
|
||||
}
|
||||
|
||||
return navigations
|
||||
}
|
||||
|
||||
func (c *Client) createTreeNodes(children map[string]TreeNode, parentName string) error {
|
||||
@@ -418,6 +580,27 @@ func main() {
|
||||
}
|
||||
|
||||
// Create scope navigations
|
||||
// First, process navigation tree if provided
|
||||
if len(config.NavigationTree) > 0 {
|
||||
fmt.Println("Creating scope navigations from tree...")
|
||||
dashboardCounter := 0
|
||||
for _, rootNode := range config.NavigationTree {
|
||||
flatNavigations := treeToNavigations(rootNode, []string{}, &dashboardCounter)
|
||||
for _, navWithName := range flatNavigations {
|
||||
// Use the title from navWithName if Nav.Title is empty
|
||||
if navWithName.Nav.Title == "" && navWithName.Title != "" {
|
||||
navWithName.Nav.Title = navWithName.Title
|
||||
}
|
||||
if err := client.createScopeNavigation(navWithName.Name, navWithName.Nav); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error creating scope navigation %s: %v\n", navWithName.Name, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// Also support flat navigations format for backward compatibility
|
||||
if len(config.Navigations) > 0 {
|
||||
fmt.Println("Creating scope navigations...")
|
||||
for name, nav := range config.Navigations {
|
||||
|
||||
@@ -254,6 +254,7 @@ Common settings in the [built-in core data sources](../../datasources/#built-in-
|
||||
| `incrementalQuerying` | string | Prometheus | Experimental: Turn on incremental querying to enhance dashboard reload performance with slow data sources |
|
||||
| `incrementalQueryOverlapWindow` | string | Prometheus | Experimental: Configure incremental query overlap window. Requires a valid duration string, for example, `180s` or `15m` Default value is `10m` (10 minutes). |
|
||||
| `disableRecordingRules` | boolean | Prometheus | Experimental: Turn off Prometheus recording rules |
|
||||
| `seriesEndpoint` | boolean | Prometheus | Using Prometheus `/api/v1/series` endpoint |
|
||||
| `implementation` | string | Alertmanager | The implementation of the Alertmanager data source, such as `prometheus`, `cortex` or `mimir` |
|
||||
| `handleGrafanaManagedAlerts` | boolean | Alertmanager | When enabled, Grafana-managed alerts are sent to this Alertmanager |
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
canonical: https://grafana.com/docs/grafana/latest/alerting/monitor-status/alerts-page/
|
||||
title: Alerts overview page
|
||||
description: Use the Alert page to assess, prioritize, and take action on alerts quickly in Grafana Cloud.
|
||||
weight: 405
|
||||
keywords:
|
||||
- Grafana Cloud
|
||||
- alerting
|
||||
- triage
|
||||
- incidents
|
||||
- monitoring
|
||||
- Grafana-managed alerts
|
||||
labels:
|
||||
products:
|
||||
- cloud
|
||||
- enterprise
|
||||
- oss
|
||||
---
|
||||
|
||||
{{< docs/public-preview product="Alerts page" >}}
|
||||
|
||||
# Alert view
|
||||
|
||||
Grafana Alerting provides a consolidated snapshot of your firing and pending Grafana-managed alerts in a simplified view. For users with complex deployments, it can be difficult to monitor and prioritize critical incidents among a large volume of firing or pending alerts. With the Alert page, you have a view where you can quickly explore and sort your recent alert history and see what alerts require review or action.
|
||||
|
||||
To see your firing and pending alerts in the alert page, go to **Alerts & IRM > Alerting > Alerts**.
|
||||
|
||||
{{< figure src="/media/docs/alerting/alerts-page.png" max-width="750px" alt="Filter your firing and pending alerts in the Alert view." >}}
|
||||
|
||||
## How it works
|
||||
|
||||
The Alerts page only shows alerts from Grafana-managed alert rules. Grafana uses a metric called `GRAFANA_ALERTS`, which is recorded in the default Mimir data source that is provisioned for cloud users.
|
||||
|
||||
{{< admonition type="note" >}}
|
||||
OSS users need to manually configure this. To configure alert state history for OSS, refer to the <a href="https://grafana.com/docs/grafana/latest/alerting/set-up/configure-alert-state-history/#configure-loki-and-prometheus-for-alert-state">configure Loki and Prometheus for alert state</a> documentation.
|
||||
{{< /admonition >}}
|
||||
|
||||
## Filter alerts in the Alerts page
|
||||
|
||||
The page displays the count of alert rules and instances that are both firing and pending. Use the filters to group your alerts and find specific alerts by label.
|
||||
|
||||
To group alerts by label, click the **Group by** field and select the labels from the dropdown menu. You can select multiple labels for alert grouping.
|
||||
|
||||
To filter by specific label values, click the **Filters** field and select a label to filter by, followed by an expression of what label value you want to use. You can enter multiple label values in your search.
|
||||
|
||||
You can also select a time range from the time picker to further adjust your results. Click the **time range** field and enter an absolute time range or select a period from the quick ranges list to apply a new time window to the display results.
|
||||
@@ -110,39 +110,6 @@ The Grafana Operator is particularly fitting for:
|
||||
|
||||
While the Grafana Operator simplifies many aspects of operating Grafana and its resources on Kubernetes, its current support is mainly focused on managing dashboards, folders, and data sources. Advanced features like alerting and plugins (only works for OSS) are not supported yet.
|
||||
|
||||
## Grizzly
|
||||
|
||||
[Grizzly](https://grafana.github.io/grizzly/) is a command line tool that allows you to manage your observability resources with code. Grizzly supports Kubernetes-inspired YAML representation for the Grafana resource, which makes it easier to learn. With Grizzly, you can move dashboards within Grafana instances and also retrieve information about already provisioned Grafana resources. Grizzly currently supports:
|
||||
|
||||
- Grafana dashboards and dashboard folders
|
||||
- Grafana data sources
|
||||
- Prometheus recording rules and alerts in Grafana Cloud
|
||||
- Grafana Cloud Synthetic Monitoring checks
|
||||
|
||||
Grizzly can also deploy dashboards built in Jsonnet using Grafonnet. (Learn more in the [Grafonnet documentation](https://grafana.github.io/grafonnet-lib/api-docs/).)
|
||||
|
||||
The following example shows a Kubernetes-style Grizzly configuration for creating a dashboard:
|
||||
|
||||
```yaml
|
||||
apiVersion: grizzly.grafana.com/v1alpha1
|
||||
kind: Dashboard
|
||||
metadata:
|
||||
name: as-code-dashboard
|
||||
spec:
|
||||
title: as-code dashboard
|
||||
uid: ascode
|
||||
```
|
||||
|
||||
To get started, see the [Grizzly guides](grizzly/dashboards-folders-datasources/) or refer to the [Grizzly’s documentation](https://grafana.github.io/grizzly/).
|
||||
|
||||
### Who is this recommended for?
|
||||
|
||||
Grizzly is best suited for users who are either using Jsonnet to manage Grafana resources or those who prefer a Kubernetes-style YAML definition of their Grafana resources.
|
||||
|
||||
### Known limitations
|
||||
|
||||
Grizzly currently doesn’t support Grafana OnCall and Grafana Alerting resources.
|
||||
|
||||
## Grafana Crossplane provider
|
||||
|
||||
[Grafana Crossplane provider](https://github.com/grafana/crossplane-provider-grafana) is built using Terrajet and provides support for all resources supported by the Grafana Terraform provider. It enables users to define Grafana resources as Kubernetes manifests and it also help users who build their GitOps pipelines around Kubernetes manifests using tools like ArgoCD.
|
||||
|
||||
@@ -12,22 +12,22 @@ canonical: https://grafana.com/docs/grafana/latest/as-code/infrastructure-as-cod
|
||||
|
||||
# Grafana Operator
|
||||
|
||||
[Grafana Operator](https://grafana.github.io/grafana-operator/) is a Kubernetes operator built to help you manage your Grafana instances and its resources from within Kubernetes. The Operator can install and manage local Grafana instances, Dashboards and Datasources through Kubernetes/OpenShift Custom resources. The Grafana Operator Automatically syncs the Kubernetes Custom resources and the actual resources in the Grafana Instance.
|
||||
The [Grafana Operator](https://grafana.github.io/grafana-operator/) is a Kubernetes operator built to help you manage your Grafana instances and its resources in a Kubernetes environment. The Grafana Operator automatically syncs Kubernetes custom resources and actual resources in your Grafana instance, and allows you to install and manage local Grafana instances, dashboards and data sources in Kubernetes or OpenShift.
|
||||
|
||||
## Installing the Grafana Operator
|
||||
## Install the Grafana Operator
|
||||
|
||||
To install the Grafana Operator in your Kubernetes cluster, Run the following command in your terminal:
|
||||
To install the Grafana Operator in your Kubernetes cluster, run the following command in your terminal:
|
||||
|
||||
```
|
||||
helm repo add grafana https://grafana.github.io/helm-charts
|
||||
helm upgrade -i grafana-operator grafana/grafana-operator
|
||||
```
|
||||
|
||||
For other installation methods, Refer [Grafana Operator Installation Documentation](https://grafana.github.io/grafana-operator/docs/installation/).
|
||||
For other installation methods, refer to the [Grafana Operator Installation](https://grafana.github.io/grafana-operator/docs/installation/) documentation.
|
||||
|
||||
## Getting Started
|
||||
## Use the Grafana Operator
|
||||
|
||||
Use the following guide to get started with using Grafana Operator to manage your Grafana instance:
|
||||
Use the following guides to use the Grafana Operator to manage your Grafana instance:
|
||||
|
||||
- [Manage data sources, and dashboards with folders using the Grafana Operator](operator-dashboards-folders-datasources/) describes how to add a folders, data sources, and dashboards, using the [Grafana Operator](https://grafana.github.io/grafana-operator/).
|
||||
- [Manage Dashboards with GitOps Using ArgoCD](manage-dashboards-argocd/) describes how to create and manage dashboards using ArgoCD and [Grafana Operator](https://grafana.github.io/grafana-operator/).
|
||||
|
||||
@@ -5,10 +5,12 @@ keywords:
|
||||
- Grafana Cloud
|
||||
- Grizzly
|
||||
- CLI
|
||||
menuTitle: Grizzly
|
||||
menuTitle: Grizzly (deprecated)
|
||||
title: Grizzly
|
||||
weight: 130
|
||||
weight: 200
|
||||
canonical: https://grafana.com/docs/grafana/latest/as-code/infrastructure-as-code/grizzly/
|
||||
aliases:
|
||||
- ../infrastructure-as-code/grizzly/dashboards-folders-datasources
|
||||
---
|
||||
|
||||
# Grizzly (deprecated)
|
||||
@@ -18,5 +20,3 @@ Grizzly has been removed. It is no longer deployed, enhanced, or supported.
|
||||
|
||||
Use the [Grafana CLI](/docs/grafana/<GRAFANA_VERSION>/observability-as-code/grafana-cli/) instead.
|
||||
{{< /admonition >}}
|
||||
|
||||
[Grizzly](https://grafana.github.io/grizzly/) is a command line tool that allows you to manage your observability resources with code. You can use it to manage dashboards, data sources, Prometheus rules, and Synthetic monitoring.
|
||||
|
||||
-149
@@ -1,149 +0,0 @@
|
||||
---
|
||||
keywords:
|
||||
- Infrastructure as Code
|
||||
- Quickstart
|
||||
- Grafana Cloud
|
||||
- Grizzly
|
||||
title: Creating and managing folders, data sources, and dashboards using Grizzly
|
||||
weight: 100
|
||||
canonical: https://grafana.com/docs/grafana/latest/as-code/infrastructure-as-code/grizzly/dashboards-folders-datasources/
|
||||
---
|
||||
|
||||
# Creating and managing folders, data sources, and dashboards using Grizzly
|
||||
|
||||
Learn how to add a data sources, folders and dashboard, using Grizzly.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, you should have the following available:
|
||||
|
||||
- A Grafana Cloud account
|
||||
- An existing Grafana Cloud stack with a Grafana API Key
|
||||
- [Grizzly](https://grafana.github.io/grizzly/installation/) installed on your machine
|
||||
|
||||
## Authentication Setup
|
||||
|
||||
To authenticate with the Grizzly API, you must create environment variables. Run the following commands to create environment variables named `GRAFANA_URL` and `GRAFANA_TOKEN`:
|
||||
|
||||
```shell
|
||||
export GRAFANA_URL=<Grafana-instance-url>
|
||||
export GRAFANA_TOKEN=<Grafana-API-Key>
|
||||
```
|
||||
|
||||
Replace the following field values:
|
||||
|
||||
- `<Grafana-instance-url>` with the URL of your Grafana instance.
|
||||
- `<Grafana-API-Key>` with API key from the Grafana instance.
|
||||
|
||||
## Add a data source
|
||||
|
||||
The following steps use the InfluxDB data source. The required arguments vary depending on the data source you select.
|
||||
|
||||
1. Create a file named `data-source.yml` and add the following:
|
||||
|
||||
```yaml
|
||||
apiVersion: grizzly.grafana.com/v1alpha1
|
||||
kind: Datasource
|
||||
metadata:
|
||||
name: <data-source-name>
|
||||
spec:
|
||||
name: <data-source-name>
|
||||
type: influxdb
|
||||
url: <data-source-url>
|
||||
database: <db-name>
|
||||
user: <username>
|
||||
secureJsonData:
|
||||
password: '<password>'
|
||||
uid: <uid>
|
||||
id: <id>
|
||||
access: proxy
|
||||
```
|
||||
|
||||
1. Replace the following field values:
|
||||
- `<data-source-name>` with the name of the data source to be added in Grafana.
|
||||
- `<data-source-url>` with URL of your data source.
|
||||
- `<username>` with the username for authenticating with your data source.
|
||||
- `<password>` with the password for authenticating with your data source.
|
||||
- `<db-name>` with name of your database.
|
||||
- `<id>` with the ID for your data source in Grafana.
|
||||
- `<uid>` wth the UID for your data source in Grafana.
|
||||
|
||||
## Add a folder
|
||||
|
||||
The following YAML definition creates a folder in your Grafana instance.
|
||||
|
||||
1. Create a file named `folder.yml` and add the following:
|
||||
|
||||
```yaml
|
||||
apiVersion: grizzly.grafana.com/v1alpha1
|
||||
kind: DashboardFolder
|
||||
metadata:
|
||||
name: <folder-name>
|
||||
spec:
|
||||
title: <folder-name>
|
||||
uid: <uid>
|
||||
```
|
||||
|
||||
1. Replace the following field values:
|
||||
- `<folder-name>` with the name of the folder to be added in Grafana.
|
||||
- `<uid>` with the UID for your folder in Grafana.
|
||||
|
||||
## Add a dashboard to the folder
|
||||
|
||||
Use the following YAML definition to create a simple dashboard in the Grafana instance folder from the previous step. To add more than a title and UID to the dashboard, you can convert your dashboard JSON config to YAML and paste it under `spec`.
|
||||
|
||||
1. Create a file named `dashboard.yml` and add the following:
|
||||
|
||||
```yaml
|
||||
apiVersion: grizzly.grafana.com/v1alpha1
|
||||
kind: Dashboard
|
||||
metadata:
|
||||
folder: <folder-name>
|
||||
name: influxdb-cloud-demos
|
||||
spec:
|
||||
title: InfluxDB Cloud Demos
|
||||
uid: influxdb-cloud-demos
|
||||
```
|
||||
|
||||
1. Replace the following field values:
|
||||
- `<folder-name>` with the name of the folder created in the previous step.
|
||||
|
||||
## Using Grizzly CLI
|
||||
|
||||
In a terminal, run the following commands from the directory where all of the YAML definitions are located.
|
||||
|
||||
1. Add the data source.
|
||||
|
||||
```shell
|
||||
grr apply data-source.yml
|
||||
```
|
||||
|
||||
1. Add a folder.
|
||||
|
||||
```shell
|
||||
grr apply folder.yml
|
||||
```
|
||||
|
||||
1. Add a dashboard to the folder.
|
||||
|
||||
```shell
|
||||
grr apply dashboard.yml
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
Once you apply the configurations using the Grizzly CLI, you should be able to verify the following:
|
||||
|
||||
- A new data source (InfluxDB in this example) is visible in Grafana.
|
||||
|
||||

|
||||
|
||||
- A new dashboard and folder in Grafana. In the following image a dashboard named `InfluxDB Cloud Demos` was created inside the `Demos` folder.
|
||||
|
||||

|
||||
|
||||
## Conclusion
|
||||
|
||||
In this guide, you created a data source, folder, and dashboard using Grizzly.
|
||||
|
||||
To learn more about managing Grafana using Grizzly, see the [Grizzly documentation](https://grafana.github.io/grizzly/).
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
description: Overview of Observability as Code including description, key features, and explanation of benefits.
|
||||
description: Overview of Observability as code including description, key features, and explanation of benefits.
|
||||
keywords:
|
||||
- observability
|
||||
- configuration
|
||||
@@ -13,30 +13,26 @@ labels:
|
||||
- enterprise
|
||||
- oss
|
||||
- cloud
|
||||
title: Observability as Code
|
||||
title: Observability as code
|
||||
weight: 100
|
||||
cards:
|
||||
items:
|
||||
- title: Get started
|
||||
height: 24
|
||||
href: ./get-started/
|
||||
description: Learn about how you can use Observability as Code.
|
||||
- title: Grafana CLI
|
||||
height: 24
|
||||
href: ./grafana-cli/
|
||||
description: Grafana CLI (`grafanactl`) is a command-line tool designed to simplify interaction with Grafana instances. You can authenticate, manage multiple environments, and perform administrative tasks through Grafana’s REST API, all from the terminal.
|
||||
description: Grafana CLI (`grafanactl`) is a command-line tool designed to simplify interaction with Grafana instances using the new REST APIs. You can authenticate, manage multiple environments, and perform administrative tasks from the terminal. It's suitable for CI/CD pipelines, local development, or free-form tasks.
|
||||
- title: Foundation SDK
|
||||
height: 24
|
||||
href: ./foundation-sdk/
|
||||
description: The Grafana Foundation SDK is a set of tools, types, and libraries that let you define Grafana dashboards and resources using familiar programming languages like Go, TypeScript, Python, Java, and PHP. Use it in conjunction with `grafanactl` to push your programmatically generated resources.
|
||||
- title: JSON schema v2
|
||||
height: 24
|
||||
href: ./schema-v2/
|
||||
description: Grafana dashboards are represented as JSON objects that store metadata, panels, variables, and settings. Observability as Code works with all versions of the JSON model, and it's fully compatible with version 2.
|
||||
- title: Foundation SDK
|
||||
height: 24
|
||||
href: ./foundation-sdk/
|
||||
description: The Grafana Foundation SDK is a set of tools, types, and libraries that let you define Grafana dashboards and resources using strongly typed code.
|
||||
- title: Git Sync (private preview)
|
||||
height: 24
|
||||
href: ./provision-resources/intro-git-sync/
|
||||
description: Git Sync is an experimental feature that lets you store your dashboard files in a GitHub repository and synchronize those changes with your Grafana instance.
|
||||
description: Git Sync lets you store your dashboard files in a GitHub repository and synchronize those changes with your Grafana instance, enabling version control, branching, and pull requests directly from Grafana.
|
||||
- title: File provisioning (private preview)
|
||||
height: 24
|
||||
href: ./provision-resources/
|
||||
@@ -51,6 +47,13 @@ hero:
|
||||
canonical: https://grafana.com/docs/grafana/latest/as-code/observability-as-code/
|
||||
aliases:
|
||||
- ../observability-as-code/ # /docs/grafana/next/observability-as-code/
|
||||
- ../observability-as-code/get-started/
|
||||
refs:
|
||||
infra-as-code:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/as-code/infrastructure-as-code/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/as-code/infrastructure-as-code/
|
||||
---
|
||||
|
||||
{{< docs/hero-simple key="hero" >}}
|
||||
@@ -59,58 +62,31 @@ aliases:
|
||||
|
||||
## Overview
|
||||
|
||||
Observability as Code lets you apply code management best practices to your observability resources.
|
||||
By representing Grafana resources as code, you can integrate them into existing infrastructure-as-code workflows and apply standard development practices.
|
||||
Grafana provides a suite of tools for **Observability as code** to help you manage your Grafana resources programmatically and at scale. This approach lets you define dashboards, data sources, and other configurations in code, enabling version control, automated testing, and reliable deployments through CI/CD pipelines. You can apply code management best practices to your observability resources, and integrate them into existing infrastructure-as-code workflows.
|
||||
|
||||
Observability as Code provides more control over configuration. Instead of manually configuring dashboards or settings through the Grafana UI, you can:
|
||||
Historically, managing Grafana as code involved various community and Grafana Labs tools, but lacked a single, cohesive story. Grafana 12 introduces foundational improvements, including new versioned APIs and official tooling, to provide a clearer path forward:
|
||||
|
||||
- Write configurations in code: Define dashboards in JSON or other supported formats.
|
||||
- Sync your Grafana setup to GitHub: Track changes, collaborate, and roll back updates using Git and GitHub, or other remote sources.
|
||||
- Automate with CI/CD: Integrate Grafana directly into your development and deployment pipelines.
|
||||
- Standardize workflows: Ensure consistency across your teams by using repeatable, codified processes for managing Grafana resources.
|
||||
- This approach requires handling HTTP requests and responses but provides complete control over resource management.
|
||||
- `grafanactl`, Git Sync, and the Foundation SDK are all built on top of these APIs.
|
||||
- To understand Dashboard Schemas accepted by the APIs, refer to the [JSON models documentation](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/observability-as-code/schema-v2/).
|
||||
|
||||
## Explore
|
||||
|
||||
{{< card-grid key="cards" type="simple" >}}
|
||||
|
||||
<!-- Hiding this part of the doc because the rest of the docs aren't released yet
|
||||
## Additional Observability as code tools
|
||||
|
||||
## Key features
|
||||
If you're already using established [Infrastructure as code](ref:infra-as-code) or other configuration management tools, Grafana offers integrations to manage resources within your existing workflows.
|
||||
|
||||
At this time, Observability as Code lets you configure dashboards in static files rather than using the UI.
|
||||
The number of resources covered by this approach will expand over time.
|
||||
|
||||
### App Platform: A unified foundation
|
||||
|
||||
The [App Platform](https://github.com/grafana/grafana-app-sdk) is the backbone of Observability as Code. It provides consistent APIs for managing Grafana resources like dashboards, data sources, and service-level objectives (SLOs). With the App Platform, you gain:
|
||||
|
||||
- A stable and predictable API for integrating Grafana into your systems.
|
||||
- Support for cloud-native workflows, making it easier to build and scale observability solutions.
|
||||
- The ability to manage Grafana resources programmatically.
|
||||
- Backwards compatibility with earlier versions of Grafana APIs, so older applications still work.
|
||||
|
||||
### Git integration
|
||||
|
||||
Version control is at the heart of Observability as Code. By integrating Grafana with Git, you can:
|
||||
|
||||
- Store your dashboards in a Git repository.
|
||||
- Automatically deploy changes through CI/CD pipelines.
|
||||
- Track who made changes, when they were made, and why.
|
||||
|
||||
### Enhanced dashboard management
|
||||
|
||||
Dashboards are central to Grafana’s value, and Observability as Code introduces improvements to make them easier to work with:
|
||||
|
||||
- **Ready for Schema v2:** An experimental dashboard schema that simplifies dashboards definition, separating properties for better clarity and making configurations more intuitive.
|
||||
- **New layout options:** Flexible layouts, including a new responsive grid layout that allow for more dynamic and responsive panel layouts.
|
||||
- **Improved metadata management:** Add descriptions, tags, and other metadata to better organize and understand your dashboards.
|
||||
|
||||
### Tooling and integrations
|
||||
|
||||
Observability as Code comes with tools to make your workflows seamless:
|
||||
|
||||
- Examples and best practices for integrating Grafana with tools like Terraform, Kubernetes, and GitHub Actions.
|
||||
- The Foundation SDK provides a set of libraries for getting started quickly configuring and manipulating Grafana resources.
|
||||
- A command line tool for configuring your dashboards programmatically.
|
||||
- Documentation, videos, and SDKs to help you get started quickly.
|
||||
-->
|
||||
- [Terraform](https://grafana.com/docs/grafana-cloud/as-code/infrastructure-as-code/terraform/)
|
||||
- Use the Grafana Terraform provider to manage dashboards, alerts, and more.
|
||||
- Understand how to define and deploy resources using HCL/JSON configurations.
|
||||
- [Ansible](https://grafana.com/docs/grafana-cloud/as-code/infrastructure-as-code/ansible/)
|
||||
- Learn to use the Grafana Ansible collection to manage Grafana Cloud resources, including folders and cloud stacks.
|
||||
- Write playbooks to automate resource provisioning through the Grafana API.
|
||||
- [Grafana Operator](https://grafana.com/docs/grafana-cloud/as-code/infrastructure-as-code/grafana-operator/)
|
||||
- Utilize Kubernetes-native management with the Grafana Operator.
|
||||
- Manage dashboards, folders, and data sources via Kubernetes Custom Resources.
|
||||
- Integrate with GitOps workflows for seamless version control and deployment.
|
||||
- [Crossplane](https://github.com/grafana/crossplane-provider-grafana) lets you manage Grafana resources using Kubernetes manifests with the Grafana Crossplane provider.
|
||||
- [Grafonnet](https://github.com/grafana/grafonnet) is a Jsonnet library for generating Grafana dashboard JSON definitions programmatically.
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
---
|
||||
description: Get started with Observability as Code by exploring the documentation, libraries, and tools available for as-code practices.
|
||||
keywords:
|
||||
- configuration
|
||||
- as code
|
||||
- as-code
|
||||
- dashboards
|
||||
- Git Sync
|
||||
- Git
|
||||
labels:
|
||||
products:
|
||||
- enterprise
|
||||
- oss
|
||||
title: Get started with Observability as Code
|
||||
weight: 100
|
||||
canonical: https://grafana.com/docs/grafana/latest/as-code/observability-as-code/get-started/
|
||||
aliases:
|
||||
- ../../observability-as-code/get-started/ # /docs/grafana/next/observability-as-code/get-started/
|
||||
---
|
||||
|
||||
# Get started with Observability as Code
|
||||
|
||||
Grafana provides a suite of tools for **Observability as Code** to help you manage your Grafana resources programmatically and at scale. This approach lets you define dashboards, data sources, and other configurations in code, enabling version control, automated testing, and reliable deployments through CI/CD pipelines.
|
||||
|
||||
Historically, managing Grafana as code involved various community and Grafana Labs tools, but lacked a single, cohesive story. Grafana 12 introduces foundational improvements, including new versioned APIs and official tooling, to provide a clearer path forward.
|
||||
|
||||
## Grafana CLI (`grafanactl`)
|
||||
|
||||
Use the official command-line tool, `grafanactl`, to interact with your Grafana instances and manage resources via the new APIs.
|
||||
|
||||
- It's the recommended tool for automation and direct API interaction, suitable for CI/CD pipelines and local development or free-form tasks. It supports pulling/pushing configurations from remote instances, validating configurations, and more.
|
||||
- `grafanactl` works across all environments for Grafana OSS, Enterprise, and Cloud.
|
||||
|
||||
Refer to the [Grafana CLI (`grafanactl`)](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/observability-as-code/grafana-cli) documentation for more information.
|
||||
|
||||
## Git Sync
|
||||
|
||||
For an integrated, UI-driven Git workflow focused on dashboards, explore Git Sync.
|
||||
|
||||
- Connect folders or entire Grafana instances directly to a GitHub repository to synchronize dashboard definitions, enabling version control, branching, and pull requests directly from Grafana.
|
||||
- Git Sync offers a simple, out-of-the-box approach for managing dashboards as code.
|
||||
{{< admonition type="note" >}}
|
||||
Git Sync is available in **private preview** for Grafana Cloud, and it's an **experimental feature** in Grafana 12, available in Grafana OSS and Enterprise [nightly releases](https://grafana.com/grafana/download/nightly).
|
||||
{{< /admonition >}}
|
||||
|
||||
Refer to the [Git Sync documentation](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/observability-as-code/provision-resources/intro-git-sync/) to learn more.
|
||||
|
||||
## Direct API usage
|
||||
|
||||
For maximum flexibility, advanced use cases, or building custom tooling, you can interact directly with the underlying versioned APIs.
|
||||
|
||||
- This approach requires handling HTTP requests and responses but provides complete control over resource management.
|
||||
- `grafanactl`, Git Sync, and the Foundation SDK are all built on top of these APIs.
|
||||
- To understand Dashboard Schemas accepted by the APIs, refer to the [JSON models documentation](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/observability-as-code/schema-v2/).
|
||||
|
||||
Refer to the [Grafana APIs](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/developers/http_api/apis/) documentation for more information.
|
||||
|
||||
## Foundation SDK
|
||||
|
||||
To programmatically define your Grafana resources (like dashboards or alerts) using familiar programming languages, use Foundation SDK.
|
||||
|
||||
- Define resources using strongly typed builders in languages like Go, TypeScript, Python, Java, and PHP.
|
||||
- Avoid crafting complex JSON manually and integrate resource generation into your existing development workflows.
|
||||
- Catch errors at compile time and easily integrate resource generation into your CI/CD pipelines.
|
||||
- Use in conjunction with `grafanactl` to push your programmatically generated resources.
|
||||
|
||||
Refer to the [Foundation SDK](../foundation-sdk) documentation for more information.
|
||||
|
||||
## Additional Observability as Code tools
|
||||
|
||||
If you're already using established Infrastructure as Code or other configuration management tools, Grafana offers integrations to manage resources within your existing workflows.
|
||||
|
||||
- [Terraform](https://grafana.com/docs/grafana-cloud/as-code/infrastructure-as-code/terraform/)
|
||||
- Use the Grafana Terraform provider to manage dashboards, alerts, and more.
|
||||
- Understand how to define and deploy resources using HCL/JSON configurations.
|
||||
|
||||
- [Ansible](https://grafana.com/docs/grafana-cloud/as-code/infrastructure-as-code/ansible/)
|
||||
- Learn to use the Grafana Ansible collection to manage Grafana Cloud resources, including folders and cloud stacks.
|
||||
- Write playbooks to automate resource provisioning through the Grafana API.
|
||||
|
||||
- [Grafana Operator](https://grafana.com/docs/grafana-cloud/as-code/infrastructure-as-code/grafana-operator/)
|
||||
- Utilize Kubernetes-native management with the Grafana Operator.
|
||||
- Manage dashboards, folders, and data sources via Kubernetes Custom Resources.
|
||||
- Integrate with GitOps workflows for seamless version control and deployment.
|
||||
|
||||
- [Crossplane](https://github.com/grafana/crossplane-provider-grafana) lets you manage Grafana resources using Kubernetes manifests with the Grafana Crossplane provider.
|
||||
- [Grafonnet](https://github.com/grafana/grafonnet) is a Jsonnet library for generating Grafana dashboard JSON definitions programmatically.
|
||||
- [Grizzly](https://grafana.com/docs/grafana-cloud/as-code/infrastructure-as-code/grizzly/dashboards-folders-datasources/) is a deprecated command-line tool that simplifies managing Grafana resources using Kubernetes-inspired YAML syntax.
|
||||
@@ -30,7 +30,7 @@ cards:
|
||||
title: Manage resources with Grafana CLI
|
||||
title_class: pt-0 lh-1
|
||||
hero:
|
||||
description: Grafana CLI (`grafanactl`) is a command-line tool designed to simplify interaction with Grafana instances. It enables users to authenticate, manage multiple environments, and perform administrative tasks through Grafana’s REST API, all from the terminal. Whether you're automating workflows in CI/CD pipelines or switching between staging and production environments, Grafana CLI provides a flexible and scriptable way to manage your Grafana setup efficiently.
|
||||
description: Grafana CLI (`grafanactl`) is a command-line tool designed to simplify interaction with Grafana instances. It enables users to authenticate, manage multiple environments, and perform administrative tasks through Grafana’s REST API, all from the terminal. Whether you're automating workflows in CI/CD pipelines or switching between staging and production environments, Grafana CLI provides a flexible and scriptable way to manage your Grafana setup efficiently. `grafanactl` works across all environments for Grafana OSS, Enterprise, and Cloud.
|
||||
height: 110
|
||||
level: 1
|
||||
title: Grafana CLI
|
||||
|
||||
@@ -25,7 +25,7 @@ aliases:
|
||||
|
||||
Git Sync is available in [private preview](https://grafana.com/docs/release-life-cycle/) for Grafana Cloud. Support and documentation is available but might be limited to enablement, configuration, and some troubleshooting. No SLAs are provided. You can sign up to the private preview using the [Git Sync early access form](https://forms.gle/WKkR3EVMcbqsNnkD9).
|
||||
|
||||
Git Sync and local file provisioning are [experimental features](https://grafana.com/docs/release-life-cycle/) introduced in Grafana v12 for open source and Enterprise editions. Engineering and on-call support is not available. Documentation is either limited or not provided outside of code comments. No SLA is provided.
|
||||
Git Sync and local file provisioning are [experimental features](https://grafana.com/docs/release-life-cycle/) introduced in Grafana v12 for open source and Enterprise editions available in [nightly releases](https://grafana.com/grafana/download/nightly). Engineering and on-call support is not available. Documentation is either limited or not provided outside of code comments. No SLA is provided.
|
||||
|
||||
{{< /admonition >}}
|
||||
|
||||
|
||||
@@ -273,6 +273,7 @@ datasources:
|
||||
prometheusVersion: 3.3.0
|
||||
cacheLevel: 'High'
|
||||
disableRecordingRules: false
|
||||
seriesEndpoint: false
|
||||
timeInterval: 10s # Prometheus scrape interval
|
||||
incrementalQueryOverlapWindow: 10m
|
||||
exemplarTraceIdDestinations:
|
||||
|
||||
+1
-1
@@ -282,5 +282,5 @@ Team membership maintenance:
|
||||
## Next steps
|
||||
|
||||
- [Troubleshoot SCIM provisioning](../troubleshooting/)
|
||||
- [Configure SCIM with Entra ID](../configure-scim-with-azuread/)
|
||||
- [Configure SCIM with Entra ID](../configure-scim-with-entraid/)
|
||||
- [Configure SCIM with Okta](../configure-scim-with-okta/)
|
||||
|
||||
@@ -22,88 +22,88 @@ For more information about feature release stages, refer to [Release life cycle
|
||||
|
||||
Most [generally available](https://grafana.com/docs/release-life-cycle/#general-availability) features are enabled by default. You can disable these feature by setting the feature flag to "false" in the configuration.
|
||||
|
||||
| Feature toggle name | Description | Enabled by default |
|
||||
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
|
||||
| `disableEnvelopeEncryption` | Disable envelope encryption (emergency only) | |
|
||||
| `publicDashboardsScene` | Enables public dashboard rendering using scenes | Yes |
|
||||
| `featureHighlights` | Highlight Grafana Enterprise features | |
|
||||
| `cloudWatchCrossAccountQuerying` | Enables cross-account querying in CloudWatch datasources | Yes |
|
||||
| `logsContextDatasourceUi` | Allow datasource to provide custom UI for context view | Yes |
|
||||
| `lokiQuerySplitting` | Split large interval queries into subqueries with smaller time intervals | Yes |
|
||||
| `influxdbBackendMigration` | Query InfluxDB InfluxQL without the proxy | Yes |
|
||||
| `dataplaneFrontendFallback` | Support dataplane contract field name change for transformations and field name matchers where the name is different | Yes |
|
||||
| `unifiedRequestLog` | Writes error logs to the request logger | Yes |
|
||||
| `logsExploreTableVisualisation` | A table visualisation for logs in Explore | Yes |
|
||||
| `awsDatasourcesTempCredentials` | Support temporary security credentials in AWS plugins for Grafana Cloud customers | Yes |
|
||||
| `transformationsRedesign` | Enables the transformations redesign | Yes |
|
||||
| `awsAsyncQueryCaching` | Enable caching for async queries for Redshift and Athena. Requires that the datasource has caching and async query support enabled | Yes |
|
||||
| `dashgpt` | Enable AI powered features in dashboards | Yes |
|
||||
| `kubernetesDashboards` | Use the kubernetes API in the frontend for dashboards | Yes |
|
||||
| `addFieldFromCalculationStatFunctions` | Add cumulative and window functions to the add field from calculation transformation | Yes |
|
||||
| `annotationPermissionUpdate` | Change the way annotation permissions work by scoping them to folders and dashboards. | Yes |
|
||||
| `dashboardSceneForViewers` | Enables dashboard rendering using Scenes for viewer roles | Yes |
|
||||
| `dashboardSceneSolo` | Enables rendering dashboards using scenes for solo panels | Yes |
|
||||
| `dashboardScene` | Enables dashboard rendering using scenes for all roles | Yes |
|
||||
| `logsInfiniteScrolling` | Enables infinite scrolling for the Logs panel in Explore and Dashboards | Yes |
|
||||
| `logRowsPopoverMenu` | Enable filtering menu displayed when text of a log line is selected | Yes |
|
||||
| `alertingQueryOptimization` | Optimizes eligible queries in order to reduce load on datasources | |
|
||||
| `onPremToCloudMigrations` | Enable the Grafana Migration Assistant, which helps you easily migrate various on-prem resources to your Grafana Cloud stack. | Yes |
|
||||
| `newPDFRendering` | New implementation for the dashboard-to-PDF rendering | Yes |
|
||||
| `cloudWatchNewLabelParsing` | Updates CloudWatch label parsing to be more accurate | Yes |
|
||||
| `pluginProxyPreserveTrailingSlash` | Preserve plugin proxy trailing slash. | |
|
||||
| `azureMonitorPrometheusExemplars` | Allows configuration of Azure Monitor as a data source that can provide Prometheus exemplars | Yes |
|
||||
| `ssoSettingsLDAP` | Use the new SSO Settings API to configure LDAP | Yes |
|
||||
| `cloudWatchRoundUpEndTime` | Round up end time for metric queries to the next minute to avoid missing data | Yes |
|
||||
| `newFiltersUI` | Enables new combobox style UI for the Ad hoc filters variable in scenes architecture | Yes |
|
||||
| `alertingQueryAndExpressionsStepMode` | Enables step mode for alerting queries and expressions | Yes |
|
||||
| `improvedExternalSessionHandling` | Enables improved support for OAuth external sessions. After enabling this feature, users might need to re-authenticate themselves. | Yes |
|
||||
| `useSessionStorageForRedirection` | Use session storage for handling the redirection after login | Yes |
|
||||
| `pluginsSriChecks` | Enables SRI checks for plugin assets | |
|
||||
| `azureMonitorDisableLogLimit` | Disables the log limit restriction for Azure Monitor when true. The limit is enabled by default. | |
|
||||
| `alertingUIOptimizeReducer` | Enables removing the reducer from the alerting UI when creating a new alert rule and using instant query | Yes |
|
||||
| `azureMonitorEnableUserAuth` | Enables user auth for Azure Monitor datasource only | Yes |
|
||||
| `alertingNotificationsStepMode` | Enables simplified step mode in the notifications section | Yes |
|
||||
| `elasticsearchCrossClusterSearch` | Enables cross cluster search in the Elasticsearch data source | |
|
||||
| `lokiLabelNamesQueryApi` | Defaults to using the Loki `/labels` API instead of `/series` | Yes |
|
||||
| `improvedExternalSessionHandlingSAML` | Enables improved support for SAML external sessions. Ensure the NameID format is correctly configured in Grafana for SAML Single Logout to function properly. | Yes |
|
||||
| `newLogsPanel` | Enables the new logs panel | Yes |
|
||||
| `alertingMigrationUI` | Enables the alerting migration UI, to migrate data source-managed rules to Grafana-managed rules | Yes |
|
||||
| `alertingImportYAMLUI` | Enables a UI feature for importing rules from a Prometheus file to Grafana-managed rules | Yes |
|
||||
| `unifiedNavbars` | Enables unified navbars | |
|
||||
| `grafanaAssistantInProfilesDrilldown` | Enables integration with Grafana Assistant in Profiles Drilldown | Yes |
|
||||
| `sharingDashboardImage` | Enables image sharing functionality for dashboards | Yes |
|
||||
| `tabularNumbers` | Use fixed-width numbers globally in the UI | |
|
||||
| `tempoSearchBackendMigration` | Run search queries through the tempo backend | |
|
||||
| Feature toggle name | Description | Enabled by default |
|
||||
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
|
||||
| `disableEnvelopeEncryption` | Disable envelope encryption (emergency only) | |
|
||||
| `publicDashboardsScene` | Enables public dashboard rendering using scenes | Yes |
|
||||
| `featureHighlights` | Highlight Grafana Enterprise features | |
|
||||
| `cloudWatchCrossAccountQuerying` | Enables cross-account querying in CloudWatch datasources | Yes |
|
||||
| `logsContextDatasourceUi` | Allow datasource to provide custom UI for context view | Yes |
|
||||
| `lokiQuerySplitting` | Split large interval queries into subqueries with smaller time intervals | Yes |
|
||||
| `influxdbBackendMigration` | Query InfluxDB InfluxQL without the proxy | Yes |
|
||||
| `dataplaneFrontendFallback` | Support dataplane contract field name change for transformations and field name matchers where the name is different | Yes |
|
||||
| `unifiedRequestLog` | Writes error logs to the request logger | Yes |
|
||||
| `logsExploreTableVisualisation` | A table visualisation for logs in Explore | Yes |
|
||||
| `awsDatasourcesTempCredentials` | Support temporary security credentials in AWS plugins for Grafana Cloud customers | Yes |
|
||||
| `transformationsRedesign` | Enables the transformations redesign | Yes |
|
||||
| `awsAsyncQueryCaching` | Enable caching for async queries for Redshift and Athena. Requires that the datasource has caching and async query support enabled | Yes |
|
||||
| `dashgpt` | Enable AI powered features in dashboards | Yes |
|
||||
| `kubernetesDashboards` | Use the kubernetes API in the frontend for dashboards | Yes |
|
||||
| `annotationPermissionUpdate` | Change the way annotation permissions work by scoping them to folders and dashboards. | Yes |
|
||||
| `dashboardSceneForViewers` | Enables dashboard rendering using Scenes for viewer roles | Yes |
|
||||
| `dashboardSceneSolo` | Enables rendering dashboards using scenes for solo panels | Yes |
|
||||
| `dashboardScene` | Enables dashboard rendering using scenes for all roles | Yes |
|
||||
| `logsInfiniteScrolling` | Enables infinite scrolling for the Logs panel in Explore and Dashboards | Yes |
|
||||
| `logRowsPopoverMenu` | Enable filtering menu displayed when text of a log line is selected | Yes |
|
||||
| `alertingQueryOptimization` | Optimizes eligible queries in order to reduce load on datasources | |
|
||||
| `onPremToCloudMigrations` | Enable the Grafana Migration Assistant, which helps you easily migrate various on-prem resources to your Grafana Cloud stack. | Yes |
|
||||
| `newPDFRendering` | New implementation for the dashboard-to-PDF rendering | Yes |
|
||||
| `cloudWatchNewLabelParsing` | Updates CloudWatch label parsing to be more accurate | Yes |
|
||||
| `pluginProxyPreserveTrailingSlash` | Preserve plugin proxy trailing slash. | |
|
||||
| `azureMonitorPrometheusExemplars` | Allows configuration of Azure Monitor as a data source that can provide Prometheus exemplars | Yes |
|
||||
| `ssoSettingsLDAP` | Use the new SSO Settings API to configure LDAP | Yes |
|
||||
| `cloudWatchRoundUpEndTime` | Round up end time for metric queries to the next minute to avoid missing data | Yes |
|
||||
| `newFiltersUI` | Enables new combobox style UI for the Ad hoc filters variable in scenes architecture | Yes |
|
||||
| `alertingQueryAndExpressionsStepMode` | Enables step mode for alerting queries and expressions | Yes |
|
||||
| `improvedExternalSessionHandling` | Enables improved support for OAuth external sessions. After enabling this feature, users might need to re-authenticate themselves. | Yes |
|
||||
| `useSessionStorageForRedirection` | Use session storage for handling the redirection after login | Yes |
|
||||
| `pluginsSriChecks` | Enables SRI checks for plugin assets | |
|
||||
| `azureMonitorDisableLogLimit` | Disables the log limit restriction for Azure Monitor when true. The limit is enabled by default. | |
|
||||
| `alertingUIOptimizeReducer` | Enables removing the reducer from the alerting UI when creating a new alert rule and using instant query | Yes |
|
||||
| `azureMonitorEnableUserAuth` | Enables user auth for Azure Monitor datasource only | Yes |
|
||||
| `alertingNotificationsStepMode` | Enables simplified step mode in the notifications section | Yes |
|
||||
| `elasticsearchCrossClusterSearch` | Enables cross cluster search in the Elasticsearch data source | |
|
||||
| `lokiLabelNamesQueryApi` | Defaults to using the Loki `/labels` API instead of `/series` | Yes |
|
||||
| `improvedExternalSessionHandlingSAML` | Enables improved support for SAML external sessions. Ensure the NameID format is correctly configured in Grafana for SAML Single Logout to function properly. | Yes |
|
||||
| `newLogsPanel` | Enables the new logs panel | Yes |
|
||||
| `alertingMigrationUI` | Enables the alerting migration UI, to migrate data source-managed rules to Grafana-managed rules | Yes |
|
||||
| `alertingImportYAMLUI` | Enables a UI feature for importing rules from a Prometheus file to Grafana-managed rules | Yes |
|
||||
| `unifiedNavbars` | Enables unified navbars | |
|
||||
| `grafanaAssistantInProfilesDrilldown` | Enables integration with Grafana Assistant in Profiles Drilldown | Yes |
|
||||
| `sharingDashboardImage` | Enables image sharing functionality for dashboards | Yes |
|
||||
| `tabularNumbers` | Use fixed-width numbers globally in the UI | |
|
||||
| `tempoSearchBackendMigration` | Run search queries through the tempo backend | |
|
||||
|
||||
## Public preview feature toggles
|
||||
|
||||
[Public preview](https://grafana.com/docs/release-life-cycle/#public-preview) features are supported by our Support teams, but might be limited to enablement, configuration, and some troubleshooting.
|
||||
|
||||
| Feature toggle name | Description |
|
||||
| ------------------------------- | ------------------------------------------------------------------------------------------------------ |
|
||||
| `panelTitleSearch` | Search for dashboards using panel title |
|
||||
| `grpcServer` | Run the GRPC server |
|
||||
| `renderAuthJWT` | Uses JWT-based auth for rendering instead of relying on remote cache |
|
||||
| `refactorVariablesTimeRange` | Refactor time range variables flow to reduce number of API calls made when query variables are chained |
|
||||
| `faroDatasourceSelector` | Enable the data source selector within the Frontend Apps section of the Frontend Observability |
|
||||
| `enableDatagridEditing` | Enables the edit functionality in the datagrid panel |
|
||||
| `reportingRetries` | Enables rendering retries for the reporting feature |
|
||||
| `externalServiceAccounts` | Automatic service account and token setup for plugins |
|
||||
| `cloudWatchBatchQueries` | Runs CloudWatch metrics queries as separate batches |
|
||||
| `pdfTables` | Enables generating table data as PDF in reporting |
|
||||
| `canvasPanelPanZoom` | Allow pan and zoom in canvas panel |
|
||||
| `alertingSaveStateCompressed` | Enables the compressed protobuf-based alert state storage. Default is enabled. |
|
||||
| `sqlExpressions` | Enables SQL Expressions, which can execute SQL queries against data source results. |
|
||||
| `queryLibrary` | Enables Saved queries (query library) feature |
|
||||
| `enableSCIM` | Enables SCIM support for user and group management |
|
||||
| `alertRuleRestore` | Enables the alert rule restore feature |
|
||||
| `azureMonitorLogsBuilderEditor` | Enables the logs builder mode for the Azure Monitor data source |
|
||||
| `localeFormatPreference` | Specifies the locale so the correct format for numbers and dates can be shown |
|
||||
| `logsPanelControls` | Enables a control component for the logs panel in Explore |
|
||||
| `interactiveLearning` | Enables the interactive learning app |
|
||||
| `azureResourcePickerUpdates` | Enables the updated Azure Monitor resource picker |
|
||||
| `newVizSuggestions` | Enable new visualization suggestions |
|
||||
| `preventPanelChromeOverflow` | Restrict PanelChrome contents with overflow: hidden; |
|
||||
| Feature toggle name | Description |
|
||||
| --------------------------------- | ------------------------------------------------------------------------------------------------------ |
|
||||
| `panelTitleSearch` | Search for dashboards using panel title |
|
||||
| `grpcServer` | Run the GRPC server |
|
||||
| `renderAuthJWT` | Uses JWT-based auth for rendering instead of relying on remote cache |
|
||||
| `refactorVariablesTimeRange` | Refactor time range variables flow to reduce number of API calls made when query variables are chained |
|
||||
| `faroDatasourceSelector` | Enable the data source selector within the Frontend Apps section of the Frontend Observability |
|
||||
| `enableDatagridEditing` | Enables the edit functionality in the datagrid panel |
|
||||
| `reportingRetries` | Enables rendering retries for the reporting feature |
|
||||
| `externalServiceAccounts` | Automatic service account and token setup for plugins |
|
||||
| `cloudWatchBatchQueries` | Runs CloudWatch metrics queries as separate batches |
|
||||
| `pdfTables` | Enables generating table data as PDF in reporting |
|
||||
| `canvasPanelPanZoom` | Allow pan and zoom in canvas panel |
|
||||
| `alertingSaveStateCompressed` | Enables the compressed protobuf-based alert state storage. Default is enabled. |
|
||||
| `sqlExpressions` | Enables SQL Expressions, which can execute SQL queries against data source results. |
|
||||
| `queryLibrary` | Enables Saved queries (query library) feature |
|
||||
| `enableSCIM` | Enables SCIM support for user and group management |
|
||||
| `alertRuleRestore` | Enables the alert rule restore feature |
|
||||
| `azureMonitorLogsBuilderEditor` | Enables the logs builder mode for the Azure Monitor data source |
|
||||
| `localeFormatPreference` | Specifies the locale so the correct format for numbers and dates can be shown |
|
||||
| `logsPanelControls` | Enables a control component for the logs panel in Explore |
|
||||
| `interactiveLearning` | Enables the interactive learning app |
|
||||
| `azureResourcePickerUpdates` | Enables the updated Azure Monitor resource picker |
|
||||
| `newVizSuggestions` | Enable new visualization suggestions |
|
||||
| `preventPanelChromeOverflow` | Restrict PanelChrome contents with overflow: hidden; |
|
||||
| `transformationsEmptyPlaceholder` | Show transformation quick-start cards in empty transformations state |
|
||||
|
||||
## Development feature toggles
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ test.describe(
|
||||
|
||||
await setScopes(page);
|
||||
|
||||
await expect(scopesSelectorInput).toHaveValue(/.+/);
|
||||
await expect(scopesSelectorInput).toHaveAttribute('data-value', /.+/);
|
||||
|
||||
expect(await adHocFilterPills.count()).toBe(3);
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ test.describe(
|
||||
|
||||
await setScopes(page);
|
||||
|
||||
await expect(scopeSelectorInput).toHaveValue(/.+/);
|
||||
await expect(scopeSelectorInput).toHaveAttribute('data-value', /.+/);
|
||||
|
||||
const firstDbName = await scopesDashboards.first().textContent();
|
||||
const scopeDashboardsCount = await scopesDashboards.count();
|
||||
@@ -60,7 +60,7 @@ test.describe(
|
||||
|
||||
await setScopes(page);
|
||||
|
||||
await expect(scopeSelectorInput).toHaveValue(/.+/);
|
||||
await expect(scopeSelectorInput).toHaveAttribute('data-value', /.+/);
|
||||
|
||||
// assert the panel is visible and has the correct value
|
||||
const markdownContent = await getMarkdownHTMLContent(dashboardPage, selectors);
|
||||
@@ -94,7 +94,7 @@ test.describe(
|
||||
|
||||
await setScopes(page, { title: 'CUJ Dashboard 3', uid: NAVIGATE_TO });
|
||||
|
||||
await expect(scopeSelectorInput).toHaveValue(/.+/);
|
||||
await expect(scopeSelectorInput).toHaveAttribute('data-value', /.+/);
|
||||
|
||||
const pills = await adhocFilterPills.allTextContents();
|
||||
const processedPills = pills
|
||||
@@ -138,7 +138,7 @@ test.describe(
|
||||
|
||||
await setScopes(page, { title: 'CUJ Dashboard 2', uid: 'cuj-dashboard-2' });
|
||||
|
||||
await expect(scopeSelectorInput).toHaveValue(/.+/);
|
||||
await expect(scopeSelectorInput).toHaveAttribute('data-value', /.+/);
|
||||
|
||||
const pillCount = await adhocFilterPills.count();
|
||||
const pillTexts = await adhocFilterPills.allTextContents();
|
||||
|
||||
@@ -40,7 +40,7 @@ test.describe(
|
||||
await test.step('1.View and select any scope', async () => {
|
||||
await gotoDashboardPage({ uid: DASHBOARD_UNDER_TEST });
|
||||
|
||||
expect.soft(scopesSelector).toHaveValue('');
|
||||
expect.soft(scopesSelector).toHaveAttribute('data-value', '');
|
||||
|
||||
const scopes = testScopes();
|
||||
await openScopesSelector(page, USE_LIVE_DATA ? undefined : scopes); //used only in mocked scopes version
|
||||
@@ -63,14 +63,13 @@ test.describe(
|
||||
|
||||
await applyScopes(page, USE_LIVE_DATA ? undefined : selectedScopes); //used only in mocked scopes version
|
||||
|
||||
expect.soft(scopesSelector).toHaveValue(scopeTitle);
|
||||
expect.soft(scopesSelector).toHaveAttribute('data-value', scopeTitle);
|
||||
});
|
||||
|
||||
await test.step('2.Select a scope across multiple types of production entities', async () => {
|
||||
await gotoDashboardPage({ uid: DASHBOARD_UNDER_TEST });
|
||||
|
||||
expect.soft(scopesSelector).toHaveValue('');
|
||||
|
||||
expect.soft(scopesSelector).toHaveAttribute('data-value', '');
|
||||
const scopes = testScopes();
|
||||
await openScopesSelector(page, USE_LIVE_DATA ? undefined : scopes); //used only in mocked scopes version
|
||||
|
||||
@@ -94,14 +93,14 @@ test.describe(
|
||||
|
||||
await applyScopes(page, USE_LIVE_DATA ? undefined : selectedScopes); //used only in mocked scopes version
|
||||
|
||||
await expect.soft(scopesSelector).toHaveValue(scopeTitles.join(' + '));
|
||||
await expect.soft(scopesSelector).toHaveAttribute('data-value', scopeTitles.join(' + '));
|
||||
});
|
||||
|
||||
await test.step('3.View and select a recently viewed scope', async () => {
|
||||
// this step depends on the previous ones because they set recent scopes
|
||||
await gotoDashboardPage({ uid: DASHBOARD_UNDER_TEST });
|
||||
|
||||
expect.soft(scopesSelector).toHaveValue('');
|
||||
expect.soft(scopesSelector).toHaveAttribute('data-value', '');
|
||||
|
||||
const scopes = testScopes();
|
||||
await openScopesSelector(page, USE_LIVE_DATA ? undefined : scopes); //used only in mocked scopes version
|
||||
@@ -114,13 +113,13 @@ test.describe(
|
||||
|
||||
await recentScope.click();
|
||||
|
||||
await expect.soft(scopesSelector).toHaveValue(scopeName!.replace(', ', ' + '));
|
||||
await expect.soft(scopesSelector).toHaveAttribute('data-value', scopeName!.replace(', ', ' + '));
|
||||
});
|
||||
|
||||
await test.step('4.View and select a scope configured by any team', async () => {
|
||||
await gotoDashboardPage({ uid: DASHBOARD_UNDER_TEST });
|
||||
|
||||
expect.soft(scopesSelector).toHaveValue('');
|
||||
expect.soft(scopesSelector).toHaveAttribute('data-value', '');
|
||||
|
||||
const scopes = testScopes();
|
||||
await openScopesSelector(page, USE_LIVE_DATA ? undefined : scopes);
|
||||
@@ -143,7 +142,7 @@ test.describe(
|
||||
|
||||
await applyScopes(page, USE_LIVE_DATA ? undefined : []); //used only in mocked scopes version
|
||||
|
||||
expect.soft(scopesSelector).toHaveValue(new RegExp(`^${scopeTitle}`));
|
||||
expect.soft(scopesSelector).toHaveAttribute('data-value', new RegExp(`^${scopeTitle}`));
|
||||
});
|
||||
|
||||
await test.step('5.View pre-completed production entity values as I type', async () => {
|
||||
|
||||
@@ -161,6 +161,7 @@ test.describe('Scope Redirect Functionality', () => {
|
||||
|
||||
await test.step('Deselect scopes and verify no redirect', async () => {
|
||||
// Click the clear button to remove all scopes
|
||||
await page.getByTestId('scopes-selector-input').hover();
|
||||
await page.getByTestId('scopes-selector-input-clear').click();
|
||||
|
||||
// Should stay on the same dashboard (cuj-dashboard-3), not redirect
|
||||
|
||||
@@ -503,6 +503,60 @@ test.describe(
|
||||
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
|
||||
).toHaveCount(3);
|
||||
});
|
||||
test('cannot add a row without a title', async ({ dashboardPage, selectors, page }) => {
|
||||
await importTestDashboard(page, selectors, 'Cannot add row without title');
|
||||
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click();
|
||||
|
||||
await groupIntoRow(page, dashboardPage, selectors);
|
||||
|
||||
await expect(
|
||||
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
|
||||
).toBeVisible();
|
||||
|
||||
// edit row title to a non-default and click away to trigger onBlur
|
||||
await dashboardPage
|
||||
.getByGrafanaSelector(selectors.components.PanelEditor.ElementEditPane.RowsLayout.titleInput)
|
||||
.fill('Test row 1');
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.backButton).click();
|
||||
|
||||
// clear the title input to simulate no title and click away to trigger onBlur
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('Test row 1')).click();
|
||||
await dashboardPage
|
||||
.getByGrafanaSelector(selectors.components.PanelEditor.ElementEditPane.RowsLayout.titleInput)
|
||||
.fill('');
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.backButton).click();
|
||||
|
||||
// title should be set to a default name
|
||||
await expect(
|
||||
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row'))
|
||||
).toBeVisible();
|
||||
|
||||
// add another row
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow).click();
|
||||
|
||||
await expect(
|
||||
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
|
||||
).toBeVisible();
|
||||
|
||||
// edit row title to a non-default and click away to trigger onBlur
|
||||
await dashboardPage
|
||||
.getByGrafanaSelector(selectors.components.PanelEditor.ElementEditPane.RowsLayout.titleInput)
|
||||
.fill('Test row 2');
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.backButton).click();
|
||||
|
||||
// clear the title input to simulate no title and click away to trigger onBlur
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('Test row 2')).click();
|
||||
await dashboardPage
|
||||
.getByGrafanaSelector(selectors.components.PanelEditor.ElementEditPane.RowsLayout.titleInput)
|
||||
.fill('');
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.backButton).click();
|
||||
|
||||
// title should be set to a default name + 1 to avoid duplicates
|
||||
await expect(
|
||||
dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1'))
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
/*
|
||||
* Tabs
|
||||
@@ -835,5 +889,51 @@ test.describe(
|
||||
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'))
|
||||
).toHaveCount(3);
|
||||
});
|
||||
|
||||
test('cannot add a tab without a title', async ({ dashboardPage, selectors, page }) => {
|
||||
await importTestDashboard(page, selectors, 'Cannot add tab without title');
|
||||
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click();
|
||||
|
||||
await groupIntoTab(page, dashboardPage, selectors);
|
||||
|
||||
await expect(dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('New tab'))).toBeVisible();
|
||||
|
||||
// edit tab title to a non-default and click away to trigger onBlur
|
||||
await dashboardPage
|
||||
.getByGrafanaSelector(selectors.components.PanelEditor.ElementEditPane.TabsLayout.titleInput)
|
||||
.fill('Test tab 1');
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.backButton).click();
|
||||
|
||||
// clear the title input to simulate no title and click away to trigger onBlur
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Test tab 1')).click();
|
||||
await dashboardPage
|
||||
.getByGrafanaSelector(selectors.components.PanelEditor.ElementEditPane.TabsLayout.titleInput)
|
||||
.fill('');
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.backButton).click();
|
||||
|
||||
// title should be set to a default name
|
||||
await expect(dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('New tab'))).toBeVisible();
|
||||
|
||||
// add another tab
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addTab).click();
|
||||
await expect(dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('New tab 1'))).toBeVisible();
|
||||
|
||||
// edit tab title to a non-default and click away to trigger onBlur
|
||||
await dashboardPage
|
||||
.getByGrafanaSelector(selectors.components.PanelEditor.ElementEditPane.TabsLayout.titleInput)
|
||||
.fill('Test tab 2');
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.backButton).click();
|
||||
|
||||
// clear the title input to simulate no title and click away to trigger onBlur
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Test tab 2')).click();
|
||||
await dashboardPage
|
||||
.getByGrafanaSelector(selectors.components.PanelEditor.ElementEditPane.TabsLayout.titleInput)
|
||||
.fill('');
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.backButton).click();
|
||||
|
||||
// title should be set to a default name + 1 to avoid duplicates
|
||||
await expect(dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('New tab 1'))).toBeVisible();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import { test, expect } from '@grafana/plugin-e2e';
|
||||
|
||||
const DASHBOARD_UID = 'MP-Di9F7k';
|
||||
|
||||
test.use({
|
||||
featureToggles: {
|
||||
timeRangePan: true,
|
||||
},
|
||||
});
|
||||
|
||||
test.describe('Panels test: Candlestick X-axis panning', { tag: ['@panels', '@candlestick'] }, () => {
|
||||
test('x-axis panning functionality', async ({ gotoDashboardPage, page, selectors }) => {
|
||||
let centerX: number;
|
||||
let centerY: number;
|
||||
let initialFromTime: number;
|
||||
let initialToTime: number;
|
||||
|
||||
const dashboardPage = await test.step('Load dashboard and verify cursor changes to grab', async () => {
|
||||
const dashboardPage = await gotoDashboardPage({ uid: DASHBOARD_UID });
|
||||
|
||||
const candlestickPanel = page.locator('.uplot').first();
|
||||
await expect(candlestickPanel, 'panel rendered').toBeVisible();
|
||||
|
||||
const xAxis = candlestickPanel.locator('.u-axis').first();
|
||||
await expect(xAxis, 'x-axis rendered').toBeVisible();
|
||||
|
||||
await xAxis.hover();
|
||||
|
||||
const cursorStyle = await xAxis.evaluate((el: HTMLElement) => window.getComputedStyle(el).cursor);
|
||||
expect(cursorStyle, 'cursor is grab').toBe('grab');
|
||||
|
||||
return dashboardPage;
|
||||
});
|
||||
|
||||
await test.step('Capture initial time range', async () => {
|
||||
const candlestickPanel = page.locator('.uplot').first();
|
||||
const xAxis = candlestickPanel.locator('.u-axis').first();
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
|
||||
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
|
||||
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
|
||||
|
||||
const initialFrom = await fromField.inputValue();
|
||||
const initialTo = await toField.inputValue();
|
||||
initialFromTime = new Date(initialFrom).getTime();
|
||||
initialToTime = new Date(initialTo).getTime();
|
||||
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
const axisBox = await xAxis.boundingBox();
|
||||
if (!axisBox) {
|
||||
throw new Error('X-axis bounding box not found');
|
||||
}
|
||||
|
||||
centerX = axisBox.x + axisBox.width / 2;
|
||||
centerY = axisBox.y + axisBox.height / 2;
|
||||
});
|
||||
|
||||
await test.step('Drag right pans backward in time', async () => {
|
||||
await page.mouse.move(centerX, centerY);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(centerX + 100, centerY);
|
||||
await page.mouse.up();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
|
||||
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
|
||||
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
|
||||
|
||||
const afterRightFrom = await fromField.inputValue();
|
||||
const afterRightTo = await toField.inputValue();
|
||||
const afterRightFromTime = new Date(afterRightFrom).getTime();
|
||||
const afterRightToTime = new Date(afterRightTo).getTime();
|
||||
|
||||
expect(afterRightFromTime, 'panned backward').toBeLessThan(initialFromTime);
|
||||
expect(afterRightToTime, 'panned backward').toBeLessThan(initialToTime);
|
||||
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
initialFromTime = afterRightFromTime;
|
||||
initialToTime = afterRightToTime;
|
||||
});
|
||||
|
||||
await test.step('Drag left pans forward in time', async () => {
|
||||
await page.mouse.move(centerX, centerY);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(centerX - 100, centerY);
|
||||
await page.mouse.up();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
|
||||
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
|
||||
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
|
||||
|
||||
const afterLeftFrom = await fromField.inputValue();
|
||||
const afterLeftTo = await toField.inputValue();
|
||||
const afterLeftFromTime = new Date(afterLeftFrom).getTime();
|
||||
const afterLeftToTime = new Date(afterLeftTo).getTime();
|
||||
|
||||
expect(afterLeftFromTime, 'panned forward').toBeGreaterThan(initialFromTime);
|
||||
expect(afterLeftToTime, 'panned forward').toBeGreaterThan(initialToTime);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,8 +1,7 @@
|
||||
import { test, expect } from '@grafana/plugin-e2e';
|
||||
|
||||
const DASHBOARD_UID = '5Y0jv6pVz';
|
||||
|
||||
// test.use();
|
||||
const TIME_RANGE_PAN_DASHBOARD_UID = 'YoacZIq7z';
|
||||
|
||||
test.describe('Panels test: Heatmap', { tag: ['@panels', '@heatmap'] }, () => {
|
||||
test('renders successfully', async ({ gotoDashboardPage, selectors, page }) => {
|
||||
@@ -34,3 +33,112 @@ test.describe('Panels test: Heatmap', { tag: ['@panels', '@heatmap'] }, () => {
|
||||
|
||||
// TODO tooltips, legends, and panel editing
|
||||
});
|
||||
|
||||
test.use({
|
||||
featureToggles: {
|
||||
timeRangePan: true,
|
||||
},
|
||||
});
|
||||
|
||||
test.describe('Panels test: Heatmap X-axis panning', { tag: ['@panels', '@heatmap'] }, () => {
|
||||
test('x-axis panning functionality', async ({ gotoDashboardPage, page, selectors }) => {
|
||||
let centerX: number;
|
||||
let centerY: number;
|
||||
let initialFromTime: number;
|
||||
let initialToTime: number;
|
||||
|
||||
const dashboardPage = await test.step('Load dashboard and verify cursor changes to grab', async () => {
|
||||
const dashboardPage = await gotoDashboardPage({ uid: TIME_RANGE_PAN_DASHBOARD_UID });
|
||||
|
||||
const heatmapPanel = page.locator('.uplot').first();
|
||||
await expect(heatmapPanel, 'panel rendered').toBeVisible();
|
||||
|
||||
const xAxis = heatmapPanel.locator('.u-axis').first();
|
||||
await expect(xAxis, 'x-axis rendered').toBeVisible();
|
||||
|
||||
await xAxis.hover();
|
||||
|
||||
const cursorStyle = await xAxis.evaluate((el: HTMLElement) => window.getComputedStyle(el).cursor);
|
||||
expect(cursorStyle, 'cursor is grab').toBe('grab');
|
||||
|
||||
return dashboardPage;
|
||||
});
|
||||
|
||||
await test.step('Capture initial time range', async () => {
|
||||
const heatmapPanel = page.locator('.uplot').first();
|
||||
const xAxis = heatmapPanel.locator('.u-axis').first();
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
|
||||
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
|
||||
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
|
||||
|
||||
const initialFrom = await fromField.inputValue();
|
||||
const initialTo = await toField.inputValue();
|
||||
initialFromTime = new Date(initialFrom).getTime();
|
||||
initialToTime = new Date(initialTo).getTime();
|
||||
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
const axisBox = await xAxis.boundingBox();
|
||||
if (!axisBox) {
|
||||
throw new Error('X-axis bounding box not found');
|
||||
}
|
||||
|
||||
centerX = axisBox.x + axisBox.width / 2;
|
||||
centerY = axisBox.y + axisBox.height / 2;
|
||||
});
|
||||
|
||||
await test.step('Drag right pans backward in time', async () => {
|
||||
await page.mouse.move(centerX, centerY);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(centerX + 100, centerY);
|
||||
await page.mouse.up();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
|
||||
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
|
||||
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
|
||||
|
||||
const afterRightFrom = await fromField.inputValue();
|
||||
const afterRightTo = await toField.inputValue();
|
||||
const afterRightFromTime = new Date(afterRightFrom).getTime();
|
||||
const afterRightToTime = new Date(afterRightTo).getTime();
|
||||
|
||||
expect(afterRightFromTime, 'panned backward').toBeLessThan(initialFromTime);
|
||||
expect(afterRightToTime, 'panned backward').toBeLessThan(initialToTime);
|
||||
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
initialFromTime = afterRightFromTime;
|
||||
initialToTime = afterRightToTime;
|
||||
});
|
||||
|
||||
await test.step('Drag left pans forward in time', async () => {
|
||||
await page.mouse.move(centerX, centerY);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(centerX - 100, centerY);
|
||||
await page.mouse.up();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
|
||||
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
|
||||
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
|
||||
|
||||
const afterLeftFrom = await fromField.inputValue();
|
||||
const afterLeftTo = await toField.inputValue();
|
||||
const afterLeftFromTime = new Date(afterLeftFrom).getTime();
|
||||
const afterLeftToTime = new Date(afterLeftTo).getTime();
|
||||
|
||||
expect(afterLeftFromTime, 'panned forward').toBeGreaterThan(initialFromTime);
|
||||
expect(afterLeftToTime, 'panned forward').toBeGreaterThan(initialToTime);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -87,3 +87,112 @@ test.describe('Panels test: StateTimeine', { tag: ['@panels', '@state-timeline']
|
||||
await expect(tooltip, 'tooltip is not shown when disabled').toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
test.use({
|
||||
featureToggles: {
|
||||
timeRangePan: true,
|
||||
},
|
||||
});
|
||||
|
||||
test.describe('Panels test: State Timeline X-axis panning', { tag: ['@panels', '@state-timeline'] }, () => {
|
||||
test('x-axis panning functionality', async ({ gotoDashboardPage, page, selectors }) => {
|
||||
let centerX: number;
|
||||
let centerY: number;
|
||||
let initialFromTime: number;
|
||||
let initialToTime: number;
|
||||
|
||||
const dashboardPage = await test.step('Load dashboard and verify cursor changes to grab', async () => {
|
||||
const dashboardPage = await gotoDashboardPage({ uid: DASHBOARD_UID });
|
||||
|
||||
const stateTimelinePanel = page.locator('.uplot').first();
|
||||
await expect(stateTimelinePanel, 'panel rendered').toBeVisible();
|
||||
|
||||
const xAxis = stateTimelinePanel.locator('.u-axis').first();
|
||||
await expect(xAxis, 'x-axis rendered').toBeVisible();
|
||||
|
||||
await xAxis.hover();
|
||||
|
||||
const cursorStyle = await xAxis.evaluate((el: HTMLElement) => window.getComputedStyle(el).cursor);
|
||||
expect(cursorStyle, 'cursor is grab').toBe('grab');
|
||||
|
||||
return dashboardPage;
|
||||
});
|
||||
|
||||
await test.step('Capture initial time range', async () => {
|
||||
const stateTimelinePanel = page.locator('.uplot').first();
|
||||
const xAxis = stateTimelinePanel.locator('.u-axis').first();
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
|
||||
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
|
||||
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
|
||||
|
||||
const initialFrom = await fromField.inputValue();
|
||||
const initialTo = await toField.inputValue();
|
||||
initialFromTime = new Date(initialFrom).getTime();
|
||||
initialToTime = new Date(initialTo).getTime();
|
||||
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
const axisBox = await xAxis.boundingBox();
|
||||
if (!axisBox) {
|
||||
throw new Error('X-axis bounding box not found');
|
||||
}
|
||||
|
||||
centerX = axisBox.x + axisBox.width / 2;
|
||||
centerY = axisBox.y + axisBox.height / 2;
|
||||
});
|
||||
|
||||
await test.step('Drag right pans backward in time', async () => {
|
||||
await page.mouse.move(centerX, centerY);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(centerX + 100, centerY);
|
||||
await page.mouse.up();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
|
||||
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
|
||||
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
|
||||
|
||||
const afterRightFrom = await fromField.inputValue();
|
||||
const afterRightTo = await toField.inputValue();
|
||||
const afterRightFromTime = new Date(afterRightFrom).getTime();
|
||||
const afterRightToTime = new Date(afterRightTo).getTime();
|
||||
|
||||
expect(afterRightFromTime, 'panned backward').toBeLessThan(initialFromTime);
|
||||
expect(afterRightToTime, 'panned backward').toBeLessThan(initialToTime);
|
||||
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
initialFromTime = afterRightFromTime;
|
||||
initialToTime = afterRightToTime;
|
||||
});
|
||||
|
||||
await test.step('Drag left pans forward in time', async () => {
|
||||
await page.mouse.move(centerX, centerY);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(centerX - 100, centerY);
|
||||
await page.mouse.up();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
|
||||
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
|
||||
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
|
||||
|
||||
const afterLeftFrom = await fromField.inputValue();
|
||||
const afterLeftTo = await toField.inputValue();
|
||||
const afterLeftFromTime = new Date(afterLeftFrom).getTime();
|
||||
const afterLeftToTime = new Date(afterLeftTo).getTime();
|
||||
|
||||
expect(afterLeftFromTime, 'panned forward').toBeGreaterThan(initialFromTime);
|
||||
expect(afterLeftToTime, 'panned forward').toBeGreaterThan(initialToTime);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -85,3 +85,112 @@ test.describe('Panels test: StatusHistory', { tag: ['@panels', '@status-history'
|
||||
await expect(tooltip, 'tooltip is not shown when disabled').toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
test.use({
|
||||
featureToggles: {
|
||||
timeRangePan: true,
|
||||
},
|
||||
});
|
||||
|
||||
test.describe('Panels test: Status History X-axis panning', { tag: ['@panels', '@status-history'] }, () => {
|
||||
test('x-axis panning functionality', async ({ gotoDashboardPage, page, selectors }) => {
|
||||
let centerX: number;
|
||||
let centerY: number;
|
||||
let initialFromTime: number;
|
||||
let initialToTime: number;
|
||||
|
||||
const dashboardPage = await test.step('Load dashboard and verify cursor changes to grab', async () => {
|
||||
const dashboardPage = await gotoDashboardPage({ uid: DASHBOARD_UID });
|
||||
|
||||
const statusHistoryPanel = page.locator('.uplot').first();
|
||||
await expect(statusHistoryPanel, 'panel rendered').toBeVisible();
|
||||
|
||||
const xAxis = statusHistoryPanel.locator('.u-axis').first();
|
||||
await expect(xAxis, 'x-axis rendered').toBeVisible();
|
||||
|
||||
await xAxis.hover();
|
||||
|
||||
const cursorStyle = await xAxis.evaluate((el: HTMLElement) => window.getComputedStyle(el).cursor);
|
||||
expect(cursorStyle, 'cursor is grab').toBe('grab');
|
||||
|
||||
return dashboardPage;
|
||||
});
|
||||
|
||||
await test.step('Capture initial time range', async () => {
|
||||
const statusHistoryPanel = page.locator('.uplot').first();
|
||||
const xAxis = statusHistoryPanel.locator('.u-axis').first();
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
|
||||
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
|
||||
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
|
||||
|
||||
const initialFrom = await fromField.inputValue();
|
||||
const initialTo = await toField.inputValue();
|
||||
initialFromTime = new Date(initialFrom).getTime();
|
||||
initialToTime = new Date(initialTo).getTime();
|
||||
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
const axisBox = await xAxis.boundingBox();
|
||||
if (!axisBox) {
|
||||
throw new Error('X-axis bounding box not found');
|
||||
}
|
||||
|
||||
centerX = axisBox.x + axisBox.width / 2;
|
||||
centerY = axisBox.y + axisBox.height / 2;
|
||||
});
|
||||
|
||||
await test.step('Drag right pans backward in time', async () => {
|
||||
await page.mouse.move(centerX, centerY);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(centerX + 100, centerY);
|
||||
await page.mouse.up();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
|
||||
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
|
||||
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
|
||||
|
||||
const afterRightFrom = await fromField.inputValue();
|
||||
const afterRightTo = await toField.inputValue();
|
||||
const afterRightFromTime = new Date(afterRightFrom).getTime();
|
||||
const afterRightToTime = new Date(afterRightTo).getTime();
|
||||
|
||||
expect(afterRightFromTime, 'panned backward').toBeLessThan(initialFromTime);
|
||||
expect(afterRightToTime, 'panned backward').toBeLessThan(initialToTime);
|
||||
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
initialFromTime = afterRightFromTime;
|
||||
initialToTime = afterRightToTime;
|
||||
});
|
||||
|
||||
await test.step('Drag left pans forward in time', async () => {
|
||||
await page.mouse.move(centerX, centerY);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(centerX - 100, centerY);
|
||||
await page.mouse.up();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
|
||||
const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField);
|
||||
const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField);
|
||||
|
||||
const afterLeftFrom = await fromField.inputValue();
|
||||
const afterLeftTo = await toField.inputValue();
|
||||
const afterLeftFromTime = new Date(afterLeftFrom).getTime();
|
||||
const afterLeftToTime = new Date(afterLeftTo).getTime();
|
||||
|
||||
expect(afterLeftFromTime, 'panned forward').toBeGreaterThan(initialFromTime);
|
||||
expect(afterLeftToTime, 'panned forward').toBeGreaterThan(initialToTime);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,8 +9,13 @@ test.use({
|
||||
});
|
||||
|
||||
test.describe('Panels test: TimeSeries X-axis panning', { tag: ['@panels', '@timeseries'] }, () => {
|
||||
test('cursor changes to grab hand over x-axis', async ({ gotoDashboardPage, page }) => {
|
||||
await test.step('Load dashboard and verify cursor changes to grab', async () => {
|
||||
test('x-axis panning functionality', async ({ gotoDashboardPage, page, selectors }) => {
|
||||
let centerX: number;
|
||||
let centerY: number;
|
||||
let initialFromTime: number;
|
||||
let initialToTime: number;
|
||||
|
||||
const dashboardPage = await test.step('Load dashboard and verify cursor changes to grab', async () => {
|
||||
const dashboardPage = await gotoDashboardPage({ uid: DASHBOARD_UID });
|
||||
|
||||
const timeseriesPanel = page.locator('.uplot').first();
|
||||
@@ -23,23 +28,13 @@ test.describe('Panels test: TimeSeries X-axis panning', { tag: ['@panels', '@tim
|
||||
|
||||
const cursorStyle = await xAxis.evaluate((el: HTMLElement) => window.getComputedStyle(el).cursor);
|
||||
expect(cursorStyle, 'cursor is grab').toBe('grab');
|
||||
|
||||
return dashboardPage;
|
||||
});
|
||||
});
|
||||
|
||||
test('drag right pans backward in time, drag left pans forward', async ({ gotoDashboardPage, page, selectors }) => {
|
||||
let centerX: number;
|
||||
let centerY: number;
|
||||
let initialFromTime: number;
|
||||
let initialToTime: number;
|
||||
|
||||
const dashboardPage = await test.step('Load dashboard and capture initial time range', async () => {
|
||||
const dashboardPage = await gotoDashboardPage({ uid: DASHBOARD_UID });
|
||||
|
||||
await test.step('Capture initial time range', async () => {
|
||||
const timeseriesPanel = page.locator('.uplot').first();
|
||||
await expect(timeseriesPanel, 'panel rendered').toBeVisible();
|
||||
|
||||
const xAxis = timeseriesPanel.locator('.u-axis').first();
|
||||
await expect(xAxis, 'x-axis rendered').toBeVisible();
|
||||
|
||||
const timePickerButton = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton);
|
||||
await timePickerButton.click();
|
||||
@@ -61,8 +56,6 @@ test.describe('Panels test: TimeSeries X-axis panning', { tag: ['@panels', '@tim
|
||||
|
||||
centerX = axisBox.x + axisBox.width / 2;
|
||||
centerY = axisBox.y + axisBox.height / 2;
|
||||
|
||||
return dashboardPage;
|
||||
});
|
||||
|
||||
await test.step('Drag right pans backward in time', async () => {
|
||||
|
||||
@@ -3154,16 +3154,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/plugins/extensions/usePluginComponents.tsx": {
|
||||
"@typescript-eslint/consistent-type-assertions": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/plugins/extensions/usePluginFunctions.tsx": {
|
||||
"@typescript-eslint/consistent-type-assertions": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/plugins/sandbox/distortions.ts": {
|
||||
"@typescript-eslint/consistent-type-assertions": {
|
||||
"count": 1
|
||||
|
||||
@@ -103,7 +103,7 @@ require (
|
||||
github.com/grafana/grafana-cloud-migration-snapshot v1.9.0 // @grafana/grafana-operator-experience-squad
|
||||
github.com/grafana/grafana-google-sdk-go v0.4.2 // @grafana/partner-datasources
|
||||
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 // @grafana/grafana-backend-group
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0 // @grafana/plugins-platform-backend
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0 // @grafana/plugins-platform-backend
|
||||
github.com/grafana/loki/pkg/push v0.0.0-20250823105456-332df2b20000 // @grafana/alerting-backend
|
||||
github.com/grafana/loki/v3 v3.2.1 // @grafana/observability-logs
|
||||
github.com/grafana/nanogit v0.0.0-20251106115617-c622d3e0fc4b // indirect; @grafana/grafana-git-ui-sync-team
|
||||
@@ -112,7 +112,7 @@ require (
|
||||
github.com/grafana/pyroscope/api v1.2.1-0.20250415190842-3ff7247547ae // @grafana/observability-traces-and-profiling
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // @grafana/grafana-search-and-storage
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // @grafana/plugins-platform-backend
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // @grafana/grafana-backend-group
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // @grafana/grafana-backend-group
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // @grafana/identity-access-team
|
||||
github.com/hashicorp/go-hclog v1.6.3 // @grafana/plugins-platform-backend
|
||||
github.com/hashicorp/go-multierror v1.1.1 // @grafana/alerting-squad
|
||||
@@ -157,7 +157,7 @@ require (
|
||||
github.com/prometheus/alertmanager v0.28.0 // @grafana/alerting-backend
|
||||
github.com/prometheus/client_golang v1.23.2 // @grafana/alerting-backend
|
||||
github.com/prometheus/client_model v0.6.2 // @grafana/grafana-backend-group
|
||||
github.com/prometheus/common v0.67.1 // @grafana/alerting-backend
|
||||
github.com/prometheus/common v0.67.2 // @grafana/alerting-backend
|
||||
github.com/prometheus/prometheus v0.303.1 // @grafana/alerting-backend
|
||||
github.com/prometheus/sigv4 v0.1.2 // @grafana/alerting-backend
|
||||
github.com/puzpuzpuz/xsync/v4 v4.2.0 // @grafana/grafana-backend-group
|
||||
@@ -203,7 +203,7 @@ require (
|
||||
golang.org/x/exp v0.0.0-20251002181428-27f1f14c8bb9 // @grafana/alerting-backend
|
||||
golang.org/x/mod v0.30.0 // indirect; @grafana/grafana-backend-group
|
||||
golang.org/x/net v0.47.0 // @grafana/oss-big-tent @grafana/partner-datasources
|
||||
golang.org/x/oauth2 v0.32.0 // @grafana/identity-access-team
|
||||
golang.org/x/oauth2 v0.33.0 // @grafana/identity-access-team
|
||||
golang.org/x/sync v0.18.0 // @grafana/alerting-backend
|
||||
golang.org/x/text v0.31.0 // @grafana/grafana-backend-group
|
||||
golang.org/x/time v0.14.0 // @grafana/grafana-backend-group
|
||||
|
||||
@@ -1647,8 +1647,8 @@ github.com/grafana/grafana-google-sdk-go v0.4.2 h1:F44hQF1y6UVJhlJPi+Mz+GCJsioVg
|
||||
github.com/grafana/grafana-google-sdk-go v0.4.2/go.mod h1:U73+w9DlbEtUonhQUzERwlXnzWTtfRoyrtKH8d3VY40=
|
||||
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 h1:r+mU5bGMzcXCRVAuOrTn54S80qbfVkvTdUJZfSfTNbs=
|
||||
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79/go.mod h1:wc6Hbh3K2TgCUSfBC/BOzabItujtHMESZeFk5ZhdxhQ=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0 h1:V8dGyatzcOLQeivFhBV2JWMwTSZH/clDnpfKG9p3dTA=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0/go.mod h1:3I0g+v6jAwVmrt6BEjDUP4V6pkhGP5QKY5NkXY4Ayr4=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0 h1:9JT9E6T0h8HsK9emTZ5s01uCKaf0Ok4PjYbb7M/iOjM=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0/go.mod h1:20qhoYxIgbZRmwCEO1KMP8q2yq/Kge5+xE/99/hLEk0=
|
||||
github.com/grafana/grafana/apps/example v0.0.0-20251027162426-edef69fdc82b h1:6Bo65etvjQ4tStkaA5+N3A3ENbO4UAWj53TxF6g2Hdk=
|
||||
github.com/grafana/grafana/apps/example v0.0.0-20251027162426-edef69fdc82b/go.mod h1:6+wASOCN8LWt6FJ8dc0oODUBIEY5XHaE6ABi8g0mR+k=
|
||||
github.com/grafana/grafana/pkg/promlib v0.0.8 h1:VUWsqttdf0wMI4j9OX9oNrykguQpZcruudDAFpJJVw0=
|
||||
@@ -1683,8 +1683,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDa
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
|
||||
@@ -2295,8 +2295,8 @@ github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGy
|
||||
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
||||
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||
github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI=
|
||||
github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4=
|
||||
github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI=
|
||||
@@ -2974,8 +2974,8 @@ golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -924,6 +924,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
|
||||
@@ -1309,6 +1310,7 @@ github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkq
|
||||
github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common/assets v0.2.0 h1:0P5OrzoHrYBOSM1OigWL3mY8ZvV2N4zIE/5AahrSrfM=
|
||||
github.com/prometheus/exporter-toolkit v0.10.1-0.20230714054209-2f4150c63f97/go.mod h1:LoBCZeRh+5hX+fSULNyFnagYlQG/gBsyA/deNzROkq8=
|
||||
github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ=
|
||||
@@ -1904,6 +1906,7 @@ golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbht
|
||||
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
@@ -1999,6 +2002,7 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:pKLAc5OolXC3ViWGI62vvC0n10CpwAtRcTNCFwTKBEw=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250512202823-5a2f75b736a9/go.mod h1:W3S/3np0/dPWsWLi1h/UymYctGXaGBM2StwzD0y140U=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250715232539-7130f93afb79/go.mod h1:HKJDgKsFUnv5VAGeQjz8kxcgDP0HoE0iZNp0OdZNlhE=
|
||||
@@ -2019,6 +2023,7 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250715232539-7130f93afb79/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
|
||||
+7
-6
@@ -76,6 +76,7 @@
|
||||
"plugin:test:ci": "nx run-many -t test:ci --projects='tag:scope:plugin' --maxParallel=2",
|
||||
"plugin:i18n-extract": "nx run-many -t i18n-extract --projects='tag:scope:plugin'",
|
||||
"generate-apis": "yarn workspace @grafana/api-clients generate-apis",
|
||||
"generate-enterprise-apis": "yarn workspace @grafana/api-clients process-specs && NODE_OPTIONS='--disable-warning=ExperimentalWarning' rtk-query-codegen-openapi ./local/generate-enterprise-apis.ts",
|
||||
"generate:api-client": "yarn workspace @grafana/api-clients generate:api-client"
|
||||
},
|
||||
"grafana": {
|
||||
@@ -136,7 +137,7 @@
|
||||
"@types/lodash": "4.17.20",
|
||||
"@types/logfmt": "^1.2.3",
|
||||
"@types/lucene": "^2",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/node-forge": "^1",
|
||||
"@types/ol-ext": "npm:@siedlerchr/types-ol-ext@3.3.0",
|
||||
"@types/pluralize": "^0.0.33",
|
||||
@@ -206,7 +207,7 @@
|
||||
"fishery": "^2.2.2",
|
||||
"fork-ts-checker-webpack-plugin": "9.1.0",
|
||||
"github-codeowners": "^0.2.1",
|
||||
"glob": "11.0.3",
|
||||
"glob": "11.1.0",
|
||||
"html-loader": "5.1.0",
|
||||
"html-webpack-plugin": "5.6.3",
|
||||
"http-server": "14.1.1",
|
||||
@@ -323,7 +324,7 @@
|
||||
"@react-aria/overlays": "3.30.0",
|
||||
"@react-aria/utils": "3.31.0",
|
||||
"@react-awesome-query-builder/ui": "6.6.15",
|
||||
"@reduxjs/toolkit": "2.9.0",
|
||||
"@reduxjs/toolkit": "2.10.1",
|
||||
"@visx/event": "3.12.0",
|
||||
"@visx/gradient": "3.12.0",
|
||||
"@visx/group": "3.12.0",
|
||||
@@ -381,7 +382,7 @@
|
||||
"moveable": "0.53.0",
|
||||
"nanoid": "^5.0.9",
|
||||
"node-forge": "^1.3.1",
|
||||
"ol": "10.6.1",
|
||||
"ol": "10.7.0",
|
||||
"ol-ext": "4.0.36",
|
||||
"ol-mapbox-style": "^13.0.1",
|
||||
"pluralize": "^8.0.0",
|
||||
@@ -427,7 +428,7 @@
|
||||
"slate": "0.47.9",
|
||||
"slate-plain-serializer": "0.7.13",
|
||||
"slate-react": "0.22.10",
|
||||
"swagger-ui-react": "5.28.1",
|
||||
"swagger-ui-react": "5.30.2",
|
||||
"symbol-observable": "4.0.0",
|
||||
"systemjs": "6.15.1",
|
||||
"tslib": "2.8.1",
|
||||
@@ -468,7 +469,7 @@
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 22 <23"
|
||||
"node": ">= 22 <25"
|
||||
},
|
||||
"packageManager": "yarn@4.11.0",
|
||||
"dependenciesMeta": {
|
||||
|
||||
@@ -19,7 +19,7 @@ First, check if the `group` and the `version` are already present in [openapi_te
|
||||
}
|
||||
```
|
||||
|
||||
Afterwards, you need to run the `TestIntegrationOpenAPIs` test. Note that it will fail the first time you run it. On the second run, it will generate the corresponding OpenAPI spec, which you can find in [openapi_snapshots](../../pkg/tests/apis/openapi_snapshots).
|
||||
Afterwards, you need to run the `TestIntegrationOpenAPIs` test with `go test ./pkg/tests/apis -run TestIntegrationOpenAPIs`. Note that it will fail the first time you run it. On the second run, it will generate the corresponding OpenAPI spec, which you can find in [openapi_snapshots](../../pkg/tests/apis/openapi_snapshots).
|
||||
|
||||
> Note: You don't need to follow these two steps if the `group` you're working with is already in the `openapi_test.go` file.
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
"marked-mangle": "1.1.12",
|
||||
"moment": "2.30.1",
|
||||
"moment-timezone": "0.5.47",
|
||||
"ol": "10.6.1",
|
||||
"ol": "10.7.0",
|
||||
"papaparse": "5.5.3",
|
||||
"react-use": "17.6.0",
|
||||
"rxjs": "7.8.2",
|
||||
@@ -89,7 +89,7 @@
|
||||
"@testing-library/react": "16.3.0",
|
||||
"@types/history": "4.7.11",
|
||||
"@types/lodash": "4.17.20",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/papaparse": "5.3.16",
|
||||
"@types/react": "18.3.18",
|
||||
"@types/react-dom": "18.3.5",
|
||||
|
||||
+8
-10
@@ -327,11 +327,6 @@ export interface FeatureToggles {
|
||||
*/
|
||||
cachingOptimizeSerializationMemoryUsage?: boolean;
|
||||
/**
|
||||
* Add cumulative and window functions to the add field from calculation transformation
|
||||
* @default true
|
||||
*/
|
||||
addFieldFromCalculationStatFunctions?: boolean;
|
||||
/**
|
||||
* Enable Grafana to sync configuration and state with a remote Alertmanager.
|
||||
*/
|
||||
alertmanagerRemoteSecondary?: boolean;
|
||||
@@ -894,11 +889,6 @@ export interface FeatureToggles {
|
||||
*/
|
||||
alertingImportYAMLUI?: boolean;
|
||||
/**
|
||||
* Enables the unified storage history pruner
|
||||
* @default true
|
||||
*/
|
||||
unifiedStorageHistoryPruner?: boolean;
|
||||
/**
|
||||
* Enables the logs builder mode for the Azure Monitor data source
|
||||
* @default false
|
||||
*/
|
||||
@@ -1200,4 +1190,12 @@ export interface FeatureToggles {
|
||||
* @default false
|
||||
*/
|
||||
awsDatasourcesHttpProxy?: boolean;
|
||||
/**
|
||||
* Show transformation quick-start cards in empty transformations state
|
||||
*/
|
||||
transformationsEmptyPlaceholder?: boolean;
|
||||
/**
|
||||
* Enable TTL plugin instance manager
|
||||
*/
|
||||
ttlPluginInstanceManager?: boolean;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-node-resolve": "16.0.1",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/semver": "7.7.1",
|
||||
"esbuild": "0.25.8",
|
||||
"rimraf": "6.0.1",
|
||||
|
||||
@@ -683,6 +683,11 @@ export const versionedComponents = {
|
||||
'12.2.0': 'data-testid tab title input',
|
||||
},
|
||||
},
|
||||
RowsLayout: {
|
||||
titleInput: {
|
||||
'12.3.0': 'data-testid row title input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
PanelInspector: {
|
||||
@@ -915,6 +920,10 @@ export const versionedComponents = {
|
||||
'10.1.0': 'data-testid add transformation button',
|
||||
[MIN_GRAFANA_VERSION]: 'add transformation button',
|
||||
},
|
||||
goToQueriesButton: {
|
||||
'10.4.0': 'data-testid go to queries button',
|
||||
[MIN_GRAFANA_VERSION]: 'go to queries button',
|
||||
},
|
||||
removeAllTransformationsButton: {
|
||||
'10.4.0': 'data-testid remove all transformations button',
|
||||
},
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
"@types/d3": "^7",
|
||||
"@types/jest": "^29.5.4",
|
||||
"@types/lodash": "4.17.20",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/react": "18.3.18",
|
||||
"@types/react-virtualized-auto-sizer": "1.0.8",
|
||||
"@types/tinycolor2": "1.4.6",
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"@testing-library/react": "16.3.0",
|
||||
"@testing-library/user-event": "14.6.1",
|
||||
"@types/jest": "^29.5.4",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/react": "18.3.18",
|
||||
"@types/systemjs": "6.15.3",
|
||||
"jest": "^29.6.4",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"eslint": "9.32.0",
|
||||
"eslint-webpack-plugin": "5.0.2",
|
||||
"fork-ts-checker-webpack-plugin": "9.1.0",
|
||||
"glob": "11.0.3",
|
||||
"glob": "11.1.0",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"imports-loader": "^5.0.0",
|
||||
"jest-canvas-mock": "2.5.2",
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
"@lezer/highlight": "1.2.3",
|
||||
"@lezer/lr": "1.4.3",
|
||||
"@prometheus-io/lezer-promql": "0.307.3",
|
||||
"@reduxjs/toolkit": "2.9.0",
|
||||
"@reduxjs/toolkit": "2.10.1",
|
||||
"@types/debounce-promise": "3.1.9",
|
||||
"@types/lodash": "4.17.20",
|
||||
"@types/react": "18.3.18",
|
||||
@@ -87,7 +87,7 @@
|
||||
"@testing-library/react": "16.3.0",
|
||||
"@testing-library/user-event": "14.6.1",
|
||||
"@types/jest": "29.5.14",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/pluralize": "^0.0.33",
|
||||
"@types/prismjs": "1.26.5",
|
||||
"esbuild": "0.25.8",
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"@testing-library/user-event": "14.6.1",
|
||||
"@types/jest": "^29.5.4",
|
||||
"@types/lodash": "4.17.20",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/react": "18.3.18",
|
||||
"@types/react-dom": "18.3.5",
|
||||
"@types/react-virtualized-auto-sizer": "1.0.8",
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"@types/chance": "^1.1.7",
|
||||
"@types/jest": "29.5.14",
|
||||
"@types/lodash": "4.17.20",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/node": "24.10.1",
|
||||
"jest": "29.7.0",
|
||||
"typescript": "5.9.2"
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
"micro-memoize": "^4.1.2",
|
||||
"moment": "2.30.1",
|
||||
"monaco-editor": "0.34.1",
|
||||
"ol": "10.6.1",
|
||||
"ol": "10.7.0",
|
||||
"prismjs": "1.30.0",
|
||||
"rc-cascader": "3.34.0",
|
||||
"rc-drawer": "7.3.0",
|
||||
@@ -165,7 +165,7 @@
|
||||
"@types/is-hotkey": "0.1.10",
|
||||
"@types/jest": "29.5.14",
|
||||
"@types/mock-raf": "1.0.6",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/prismjs": "1.26.5",
|
||||
"@types/react": "18.3.18",
|
||||
"@types/react-color": "3.0.13",
|
||||
|
||||
@@ -6,35 +6,40 @@ import { Trans } from '@grafana/i18n';
|
||||
import { useCombinedRefs } from '../../utils/useCombinedRefs';
|
||||
import { Button } from '../Button/Button';
|
||||
import { Icon } from '../Icon/Icon';
|
||||
import { Input } from '../Input/Input';
|
||||
import { Input, Props as InputProps } from '../Input/Input';
|
||||
|
||||
export interface Props extends Omit<HTMLProps<HTMLInputElement>, 'onChange'> {
|
||||
value: string | undefined;
|
||||
width?: number;
|
||||
onChange: (value: string) => void;
|
||||
escapeRegex?: boolean;
|
||||
suffix?: InputProps['suffix'];
|
||||
}
|
||||
|
||||
export const FilterInput = forwardRef<HTMLInputElement, Props>(
|
||||
({ value, width, onChange, escapeRegex = true, ...restProps }, ref) => {
|
||||
({ value, width, onChange, escapeRegex = true, suffix: _suffix, ...restProps }, ref) => {
|
||||
const innerRef = useRef<HTMLInputElement | null>(null);
|
||||
const combinedRef = useCombinedRefs<HTMLInputElement>(ref, innerRef);
|
||||
|
||||
const suffix =
|
||||
value !== '' ? (
|
||||
<Button
|
||||
icon="times"
|
||||
fill="text"
|
||||
size="sm"
|
||||
onClick={(e) => {
|
||||
innerRef.current?.focus();
|
||||
onChange('');
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<Trans i18nKey="grafana-ui.filter-input.clear">Clear</Trans>
|
||||
</Button>
|
||||
) : null;
|
||||
const suffix = (
|
||||
<>
|
||||
{value !== '' && (
|
||||
<Button
|
||||
icon="times"
|
||||
fill="text"
|
||||
size="sm"
|
||||
onClick={(e) => {
|
||||
innerRef.current?.focus();
|
||||
onChange('');
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<Trans i18nKey="grafana-ui.filter-input.clear">Clear</Trans>
|
||||
</Button>
|
||||
)}
|
||||
{_suffix}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<Input
|
||||
|
||||
@@ -5,7 +5,7 @@ import { FixedSizeList as List, ListChildComponentProps } from 'react-window';
|
||||
|
||||
import { GrafanaTheme2, formattedValueToString, getValueFormat, SelectableValue } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { Trans } from '@grafana/i18n';
|
||||
import { t, Trans } from '@grafana/i18n';
|
||||
|
||||
import { useStyles2, useTheme2 } from '../../../../themes/ThemeContext';
|
||||
import { Checkbox } from '../../../Forms/Checkbox';
|
||||
@@ -24,7 +24,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const ITEM_HEIGHT = 28;
|
||||
const MIN_HEIGHT = ITEM_HEIGHT * 5;
|
||||
const MIN_HEIGHT = ITEM_HEIGHT * 4.5; // split an item in the middle to imply there are more items to scroll
|
||||
|
||||
export const REGEX_OPERATOR = operatorSelectableValues['Contains'];
|
||||
const XPR_OPERATOR = operatorSelectableValues['Expression'];
|
||||
@@ -109,21 +109,31 @@ export const FilterList = ({ options, values, caseSensitive, onChange, searchFil
|
||||
() => selectedItems.length > 0 && items.length > selectedItems.length,
|
||||
[items, selectedItems]
|
||||
);
|
||||
const selectCheckLabel = useMemo(
|
||||
() => (selectedItems.length ? `${selectedItems.length} selected` : `Select all`),
|
||||
[selectedItems]
|
||||
);
|
||||
const selectCheckLabel = useMemo(() => {
|
||||
if (!values.length) {
|
||||
return t('grafana-ui.table.filter.select-all', 'Select all');
|
||||
}
|
||||
if (values.length !== selectedItems.length) {
|
||||
return t('grafana-ui.table.filter.selected-some-hidden', '{{ numSelected }} selected ({{ numHidden }} hidden)', {
|
||||
numSelected: values.length,
|
||||
numHidden: values.length - selectedItems.length,
|
||||
});
|
||||
}
|
||||
return t('grafana-ui.table.filter.selected', '{{ numSelected }} selected', {
|
||||
numSelected: values.length,
|
||||
});
|
||||
}, [selectedItems.length, values.length]);
|
||||
const selectCheckDescription = useMemo(
|
||||
() =>
|
||||
items.length !== selectedItems.length
|
||||
? 'Add all displayed values to the filter'
|
||||
: 'Remove all displayed values from the filter',
|
||||
? t('grafana-ui.table.filter.add-all', 'Add all displayed values to the filter')
|
||||
: t('grafana-ui.table.filter.remove-all', 'Remove all displayed values from the filter'),
|
||||
[items, selectedItems]
|
||||
);
|
||||
|
||||
const styles = useStyles2(getStyles);
|
||||
const theme = useTheme2();
|
||||
const gutter = theme.spacing.gridSize;
|
||||
const gutter = theme.spacing.gridSize / 2;
|
||||
const height = useMemo(() => Math.min(items.length * ITEM_HEIGHT, MIN_HEIGHT) + gutter, [gutter, items.length]);
|
||||
|
||||
const onCheckedChanged = useCallback(
|
||||
@@ -207,9 +217,8 @@ function ItemRenderer({ index, style, data: { onCheckedChanged, items, values, c
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
filterList: css({
|
||||
label: 'filterList',
|
||||
backgroundColor: theme.components.input.background,
|
||||
border: `1px solid ${theme.colors.border.medium}`,
|
||||
borderRadius: theme.shape.radius.default,
|
||||
marginBottom: theme.spacing(0.5),
|
||||
borderBottom: `1px solid ${theme.colors.border.weak}`,
|
||||
}),
|
||||
filterListRow: css({
|
||||
label: 'filterListRow',
|
||||
@@ -223,12 +232,6 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||
backgroundColor: theme.colors.action.hover,
|
||||
},
|
||||
}),
|
||||
selectDivider: css({
|
||||
label: 'selectDivider',
|
||||
width: '100%',
|
||||
borderTop: `1px solid ${theme.colors.border.medium}`,
|
||||
padding: theme.spacing(0.5, 2),
|
||||
}),
|
||||
noValuesLabel: css({
|
||||
paddingTop: theme.spacing(1),
|
||||
}),
|
||||
|
||||
@@ -118,27 +118,28 @@ export const FilterPopup = ({
|
||||
ref={containerRef}
|
||||
>
|
||||
<Stack direction="column">
|
||||
<Stack alignItems="center">
|
||||
{field && <Label className={styles.label}>{getDisplayName(field)}</Label>}
|
||||
<ButtonSelect
|
||||
variant="canvas"
|
||||
options={OPERATORS}
|
||||
onChange={setOperator}
|
||||
value={operator}
|
||||
tooltip={operator.description}
|
||||
root={containerRef.current ?? undefined}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
<div className={styles.listDivider} />
|
||||
<Stack alignItems="center">{field && <Label className={styles.label}>{getDisplayName(field)}</Label>}</Stack>
|
||||
|
||||
<Stack gap={1}>
|
||||
<FilterInput
|
||||
placeholder={filterInputPlaceholder}
|
||||
title={filterInputPlaceholder}
|
||||
onChange={setSearchFilter}
|
||||
value={searchFilter}
|
||||
/>
|
||||
<div className={styles.inputContainer}>
|
||||
<FilterInput
|
||||
placeholder={filterInputPlaceholder}
|
||||
title={filterInputPlaceholder}
|
||||
onChange={setSearchFilter}
|
||||
value={searchFilter}
|
||||
suffix={
|
||||
<ButtonSelect
|
||||
className={styles.buttonSelectOverrides}
|
||||
options={OPERATORS}
|
||||
onChange={setOperator}
|
||||
value={operator}
|
||||
tooltip={operator.description}
|
||||
narrow
|
||||
root={containerRef.current ?? undefined}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
tooltip={t('grafana-ui.table.filter-popup-aria-label-match-case', 'Match case')}
|
||||
variant="secondary"
|
||||
@@ -159,21 +160,17 @@ export const FilterPopup = ({
|
||||
operator={operator}
|
||||
/>
|
||||
|
||||
<Stack gap={3}>
|
||||
<Stack>
|
||||
<Button size="sm" onClick={onFilter}>
|
||||
<Trans i18nKey="grafana-ui.table.filter-popup-apply">Ok</Trans>
|
||||
</Button>
|
||||
<Button size="sm" variant="secondary" onClick={onCancel}>
|
||||
<Trans i18nKey="grafana-ui.table.filter-popup-cancel">Cancel</Trans>
|
||||
</Button>
|
||||
</Stack>
|
||||
<Stack justifyContent="end" direction="row-reverse">
|
||||
<Button size="sm" onClick={onFilter}>
|
||||
<Trans i18nKey="grafana-ui.table.filter-popup-apply">Ok</Trans>
|
||||
</Button>
|
||||
<Button size="sm" variant="secondary" onClick={onCancel}>
|
||||
<Trans i18nKey="grafana-ui.table.filter-popup-cancel">Cancel</Trans>
|
||||
</Button>
|
||||
{clearFilterVisible && (
|
||||
<Stack>
|
||||
<Button fill="text" size="sm" onClick={onClearFilter}>
|
||||
<Trans i18nKey="grafana-ui.table.filter-popup-clear">Clear filter</Trans>
|
||||
</Button>
|
||||
</Stack>
|
||||
<Button fill="text" size="sm" onClick={onClearFilter}>
|
||||
<Trans i18nKey="grafana-ui.table.filter-popup-clear">Clear filter</Trans>
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
@@ -186,7 +183,7 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||
filterContainer: css({
|
||||
label: 'filterContainer',
|
||||
width: '100%',
|
||||
minWidth: '250px',
|
||||
minWidth: '320px',
|
||||
height: '100%',
|
||||
backgroundColor: theme.colors.background.primary,
|
||||
border: `1px solid ${theme.colors.border.weak}`,
|
||||
@@ -194,14 +191,19 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||
boxShadow: theme.shadows.z3,
|
||||
borderRadius: theme.shape.radius.default,
|
||||
}),
|
||||
listDivider: css({
|
||||
label: 'listDivider',
|
||||
width: '100%',
|
||||
borderTop: `1px solid ${theme.colors.border.medium}`,
|
||||
}),
|
||||
label: css({
|
||||
marginBottom: 0,
|
||||
}),
|
||||
inputContainer: css({
|
||||
width: 300,
|
||||
}),
|
||||
buttonSelectOverrides: css({
|
||||
fontSize: 12,
|
||||
'&:hover, &:focus, &:active': {
|
||||
color: theme.colors.text.primary,
|
||||
background: 'transparent',
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const stopPropagation = (event: React.MouseEvent) => {
|
||||
|
||||
@@ -4,7 +4,7 @@ go 1.25.3
|
||||
|
||||
require (
|
||||
github.com/emicklei/go-restful/v3 v3.13.0
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e
|
||||
github.com/grafana/grafana/pkg/semconv v0.0.0-20250514132646-acbc7b54ed9e
|
||||
github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38
|
||||
@@ -59,7 +59,7 @@ require (
|
||||
github.com/grafana/otel-profiling-go v0.5.1 // indirect
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
@@ -90,7 +90,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/spf13/cobra v1.10.1 // indirect
|
||||
@@ -122,7 +122,7 @@ require (
|
||||
golang.org/x/exp v0.0.0-20251002181428-27f1f14c8bb9 // indirect
|
||||
golang.org/x/mod v0.30.0 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 // indirect
|
||||
|
||||
@@ -101,8 +101,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0 h1:V8dGyatzcOLQeivFhBV2JWMwTSZH/clDnpfKG9p3dTA=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0/go.mod h1:3I0g+v6jAwVmrt6BEjDUP4V6pkhGP5QKY5NkXY4Ayr4=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0 h1:9JT9E6T0h8HsK9emTZ5s01uCKaf0Ok4PjYbb7M/iOjM=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0/go.mod h1:20qhoYxIgbZRmwCEO1KMP8q2yq/Kge5+xE/99/hLEk0=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e/go.mod h1:IA4SOwun8QyST9c5UNs/fN37XL6boXXDvRYFcFwbipg=
|
||||
github.com/grafana/grafana/pkg/semconv v0.0.0-20250514132646-acbc7b54ed9e h1:vheR6iPO1np+G/ARjcWx9yiWd7BnTDgyTgsnMhOvx70=
|
||||
@@ -113,8 +113,8 @@ github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasn
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
|
||||
@@ -208,8 +208,8 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
@@ -333,8 +333,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
@@ -48,7 +48,7 @@ require (
|
||||
github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // indirect
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
@@ -64,7 +64,7 @@ require (
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.1 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
@@ -86,7 +86,7 @@ require (
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.44.0 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.32.0 // indirect
|
||||
golang.org/x/oauth2 v0.33.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
|
||||
@@ -77,8 +77,8 @@ github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e/go.mod h1:IA4SOwun8QyST9c5UNs/fN37XL6boXXDvRYFcFwbipg=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
|
||||
@@ -129,8 +129,8 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
@@ -222,8 +222,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
+4
-3
@@ -4,11 +4,11 @@ go 1.25.3
|
||||
|
||||
require (
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0
|
||||
github.com/grafana/grafana/apps/scope v0.0.0-20251007093103-792853df9134
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/prometheus/common v0.67.1
|
||||
github.com/prometheus/common v0.67.2
|
||||
github.com/prometheus/prometheus v0.303.1
|
||||
github.com/stretchr/testify v1.11.1
|
||||
go.opentelemetry.io/otel v1.38.0
|
||||
@@ -54,7 +54,7 @@ require (
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect
|
||||
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
github.com/hashicorp/go-plugin v1.7.0 // indirect
|
||||
@@ -76,6 +76,7 @@ require (
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/oklog/ulid/v2 v2.1.1 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
|
||||
+10
-8
@@ -130,8 +130,8 @@ github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81
|
||||
github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI=
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0 h1:V8dGyatzcOLQeivFhBV2JWMwTSZH/clDnpfKG9p3dTA=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.281.0/go.mod h1:3I0g+v6jAwVmrt6BEjDUP4V6pkhGP5QKY5NkXY4Ayr4=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0 h1:9JT9E6T0h8HsK9emTZ5s01uCKaf0Ok4PjYbb7M/iOjM=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.282.0/go.mod h1:20qhoYxIgbZRmwCEO1KMP8q2yq/Kge5+xE/99/hLEk0=
|
||||
github.com/grafana/grafana/apps/scope v0.0.0-20251007093103-792853df9134 h1:xly75v5lFNR37q+wXnwA5yU/fPW9IOSYbhFpt4tQyt8=
|
||||
github.com/grafana/grafana/apps/scope v0.0.0-20251007093103-792853df9134/go.mod h1:zijsUNa1zi476JJIR2Lcm/Paz1nRCno9XCp6hbS6G9o=
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20251007081214-26e147d01f0a h1:L7xgV9mP6MRF3L2/vDOjNR7heaBPbXPMGTDN9/jXSFQ=
|
||||
@@ -144,8 +144,8 @@ github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrR
|
||||
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
|
||||
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
|
||||
@@ -223,6 +223,8 @@ github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
|
||||
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
|
||||
github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
@@ -237,8 +239,8 @@ github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/prometheus/prometheus v0.303.1 h1:He/2jRE6sB23Ew38AIoR1WRR3fCMgPlJA2E0obD2WSY=
|
||||
@@ -333,8 +335,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user