merge with main

This commit is contained in:
Will Browne
2025-02-27 10:58:29 +00:00
275 changed files with 4841 additions and 1980 deletions
+2 -95
View File
@@ -518,120 +518,30 @@ exports[`better eslint`] = {
"packages/grafana-sql/src/components/visual-query-builder/AwesomeQueryBuilder.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"packages/grafana-ui/src/components/Alert/Alert.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"packages/grafana-ui/src/components/Card/Card.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"packages/grafana-ui/src/components/Cascader/Cascader.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"packages/grafana-ui/src/components/ColorPicker/NamedColorsPalette.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"packages/grafana-ui/src/components/Combobox/ValuePill.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"packages/grafana-ui/src/components/Combobox/useOptions.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"packages/grafana-ui/src/components/ConfirmModal/ConfirmContent.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"packages/grafana-ui/src/components/DataLinks/DataLinkEditor.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "3"]
],
"packages/grafana-ui/src/components/DataLinks/DataLinkInput.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"packages/grafana-ui/src/components/DataLinks/DataLinkSuggestions.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"packages/grafana-ui/src/components/DataSourceSettings/AlertingSettings.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"packages/grafana-ui/src/components/DataSourceSettings/BasicAuthSettings.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "3"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "4"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "5"],
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
[0, 0, 0, "Unexpected any. Specify a different type.", "7"]
],
"packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "3"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "4"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "5"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "6"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "7"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "8"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "9"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "10"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "11"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "12"]
],
"packages/grafana-ui/src/components/DataSourceSettings/HttpProxySettings.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "3"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "4"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "5"]
],
"packages/grafana-ui/src/components/DataSourceSettings/SecureSocksProxySettings.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"packages/grafana-ui/src/components/DataSourceSettings/TLSAuthSettings.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "3"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "4"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "5"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "6"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "7"]
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"packages/grafana-ui/src/components/DataSourceSettings/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"packages/grafana-ui/src/components/DateTimePickers/DateTimePicker/DateTimePicker.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"]
],
"packages/grafana-ui/src/components/DateTimePickers/RelativeTimeRangePicker/RelativeTimeRangePicker.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"]
],
"packages/grafana-ui/src/components/FileDropzone/FileDropzone.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
@@ -1575,9 +1485,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "6"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "7"]
],
"public/app/features/alerting/unified/RuleViewer.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"]
],
"public/app/features/alerting/unified/Settings.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "1"],
+41 -41
View File
@@ -18,7 +18,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd
@@ -69,7 +69,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- go install github.com/bazelbuild/buildtools/buildifier@latest
@@ -112,7 +112,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -170,7 +170,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -309,7 +309,7 @@ steps:
path: /github-app
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -427,7 +427,7 @@ steps:
path: /github-app
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -517,7 +517,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd
@@ -642,7 +642,7 @@ steps:
path: /github-app
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- mkdir -p bin
@@ -713,7 +713,7 @@ steps:
-a targz:grafana:linux/arm/v7 -a docker:grafana:linux/amd64 -a docker:grafana:linux/amd64:ubuntu
-a docker:grafana:linux/arm64 -a docker:grafana:linux/arm64:ubuntu -a docker:grafana:linux/arm/v7
-a docker:grafana:linux/arm/v7:ubuntu --go-version=1.23.5 --yarn-cache=$$YARN_CACHE_FOLDER
--build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.20.6
--build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.21.3
--tag-format='{{ .version_base }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{
.version_base }}-{{ .buildID }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD
> packages.txt
@@ -770,7 +770,7 @@ steps:
GF_APP_MODE: development
GF_SERVER_HTTP_PORT: "3001"
GF_SERVER_ROUTER_LOGGING: "1"
image: alpine:3.20.6
image: alpine:3.21.3
name: grafana-server
- commands:
- ./bin/build e2e-tests --port 3001 --suite dashboards-suite
@@ -1114,7 +1114,7 @@ steps:
name: compile-build-cmd
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -1280,7 +1280,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -1637,7 +1637,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -1708,7 +1708,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -1766,7 +1766,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -1842,7 +1842,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -1922,7 +1922,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd
@@ -1988,7 +1988,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -2063,7 +2063,7 @@ steps:
path: /github-app
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- mkdir -p bin
@@ -2133,7 +2133,7 @@ steps:
-a targz:grafana:linux/arm/v7 -a docker:grafana:linux/amd64 -a docker:grafana:linux/amd64:ubuntu
-a docker:grafana:linux/arm64 -a docker:grafana:linux/arm64:ubuntu -a docker:grafana:linux/arm/v7
-a docker:grafana:linux/arm/v7:ubuntu --go-version=1.23.5 --yarn-cache=$$YARN_CACHE_FOLDER
--build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.20.6
--build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.21.3
--tag-format='{{ .version_base }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{
.version_base }}-{{ .buildID }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD
> packages.txt
@@ -2194,7 +2194,7 @@ steps:
GF_APP_MODE: development
GF_SERVER_HTTP_PORT: "3001"
GF_SERVER_ROUTER_LOGGING: "1"
image: alpine:3.20.6
image: alpine:3.21.3
name: grafana-server
- commands:
- ./bin/build e2e-tests --port 3001 --suite dashboards-suite
@@ -2611,7 +2611,7 @@ steps:
name: compile-build-cmd
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -2856,7 +2856,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -2912,7 +2912,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -2986,7 +2986,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -3064,7 +3064,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd
@@ -3169,7 +3169,7 @@ steps:
name: compile-build-cmd
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -3372,7 +3372,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- mkdir -p bin
@@ -3504,7 +3504,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- mkdir -p bin
@@ -3994,7 +3994,7 @@ steps:
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
ALPINE_BASE: alpine:3.20.6
ALPINE_BASE: alpine:3.21.3
CDN_DESTINATION:
from_secret: rgm_cdn_destination
DESTINATION:
@@ -4069,7 +4069,7 @@ steps:
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
ALPINE_BASE: alpine:3.20.6
ALPINE_BASE: alpine:3.21.3
CDN_DESTINATION:
from_secret: rgm_cdn_destination
DESTINATION:
@@ -4186,7 +4186,7 @@ steps:
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
ALPINE_BASE: alpine:3.20.6
ALPINE_BASE: alpine:3.21.3
CDN_DESTINATION:
from_secret: rgm_cdn_destination
DESTINATION:
@@ -4288,7 +4288,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -4342,7 +4342,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -4423,7 +4423,7 @@ steps:
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
ALPINE_BASE: alpine:3.20.6
ALPINE_BASE: alpine:3.21.3
CDN_DESTINATION:
from_secret: rgm_cdn_destination
DESTINATION:
@@ -4567,7 +4567,7 @@ steps:
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
ALPINE_BASE: alpine:3.20.6
ALPINE_BASE: alpine:3.21.3
CDN_DESTINATION:
from_secret: rgm_cdn_destination
DESTINATION:
@@ -4695,7 +4695,7 @@ steps:
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
ALPINE_BASE: alpine:3.20.6
ALPINE_BASE: alpine:3.21.3
CDN_DESTINATION:
from_secret: rgm_cdn_destination
DESTINATION:
@@ -4838,7 +4838,7 @@ steps:
name: grabpl
- commands:
- echo $DRONE_RUNNER_NAME
image: alpine:3.20.6
image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -5262,7 +5262,7 @@ steps:
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM node:22-bookworm
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM google/cloud-sdk:431.0.0
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM grafana/grafana-ci-deploy:1.3.3
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM alpine:3.20.6
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM alpine:3.21.3
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM ubuntu:22.04
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM byrnedo/alpine-curl:0.1.8
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM plugins/slack
@@ -5300,7 +5300,7 @@ steps:
- trivy --exit-code 1 --severity HIGH,CRITICAL node:22-bookworm
- trivy --exit-code 1 --severity HIGH,CRITICAL google/cloud-sdk:431.0.0
- trivy --exit-code 1 --severity HIGH,CRITICAL grafana/grafana-ci-deploy:1.3.3
- trivy --exit-code 1 --severity HIGH,CRITICAL alpine:3.20.6
- trivy --exit-code 1 --severity HIGH,CRITICAL alpine:3.21.3
- trivy --exit-code 1 --severity HIGH,CRITICAL ubuntu:22.04
- trivy --exit-code 1 --severity HIGH,CRITICAL byrnedo/alpine-curl:0.1.8
- trivy --exit-code 1 --severity HIGH,CRITICAL plugins/slack
@@ -5564,6 +5564,6 @@ kind: secret
name: gcr_credentials
---
kind: signature
hmac: 558d477c002eb799c23f6631aafc7df933518e445e59f34ceb989e73f4dc60bc
hmac: f16a4715c7a4e6a4ffb1fe041b42fb966310fd5da455239614e9a239493aff82
...
+1
View File
@@ -776,6 +776,7 @@ embed.go @grafana/grafana-as-code
/.github/workflows/doc-validator.yml @grafana/docs-tooling
/.github/workflows/deploy-pr-preview.yml @grafana/docs-tooling
/.github/workflows/epic-add-to-platform-ux-parent-project.yml @meanmina
/.github/workflows/feature-toggles-ci.yml @grafana/docs-tooling
/.github/workflows/github-release.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/issue-opened.yml @grafana/grafana-community-support
/.github/workflows/metrics-collector.yml @torkelo
+2 -2
View File
@@ -640,7 +640,7 @@
"name": "area/configuration",
"action": "addToProject",
"addToProject": {
"url": "https://github.com/orgs/grafana/projects/96"
"url": "https://github.com/orgs/grafana/projects/665"
}
},
{
@@ -744,7 +744,7 @@
"name": "area/backend/db/postgres",
"action": "addToProject",
"addToProject": {
"url": "https://github.com/orgs/grafana/projects/96"
"url": "https://github.com/orgs/grafana/projects/835"
}
},
{
+4 -3
View File
@@ -13,6 +13,7 @@ jobs:
permissions:
contents: write
pull-requests: write
id-token: write
steps:
- name: Checkout repository
@@ -93,8 +94,8 @@ jobs:
uses: grafana/shared-workflows/actions/get-vault-secrets@28361cdb22223e5f1e34358c86c20908e7248760 # 1.1.0
with:
repo_secrets: |
GITHUB_APP_ID=github-app:app-id
GITHUB_APP_PRIVATE_KEY=github-app:private-key
GITHUB_APP_ID=alerting-team:app-id
GITHUB_APP_PRIVATE_KEY=alerting-team:private-key
- name: "Generate token"
id: generate_token
@@ -127,4 +128,4 @@ jobs:
if: steps.create-pr.outputs.pull-request-url != ''
run: |
echo "## Pull Request Created" >> $GITHUB_STEP_SUMMARY
echo "🔗 [View Pull Request](${{ steps.create-pr.outputs.pull-request-url }})" >> $GITHUB_STEP_SUMMARY
echo "🔗 [View Pull Request](${{ steps.create-pr.outputs.pull-request-url }})" >> $GITHUB_STEP_SUMMARY
+25
View File
@@ -0,0 +1,25 @@
name: Feature toggles CI
on:
pull_request:
paths:
- 'pkg/services/featuremgmt/toggles_gen_test.go'
- 'pkg/services/featuremgmt/registry.go'
- 'docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
cache: true
- name: Run feature toggle tests
run: go test -v -run TestFeatureToggleFiles ./pkg/services/featuremgmt/
+1
View File
@@ -113,6 +113,7 @@ profile.cov
/pkg/extensions/*
!/pkg/extensions/.keep
!/pkg/extensions/main.go
!/pkg/extensions/enterprise_imports.go
/public/app/extensions
!/public/app/extensions/.keep
+1 -1
View File
@@ -3,7 +3,7 @@
# to maintain formatting of multiline commands in vscode, add the following to settings.json:
# "docker.languageserver.formatter.ignoreMultilineInstructions": true
ARG BASE_IMAGE=alpine:3.20
ARG BASE_IMAGE=alpine:3.21
ARG JS_IMAGE=node:22-alpine
ARG JS_PLATFORM=linux/amd64
ARG GO_IMAGE=golang:1.23.5-alpine
+2 -2
View File
@@ -32,7 +32,7 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
@@ -83,7 +83,7 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.70.0 // indirect
google.golang.org/protobuf v1.36.4 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+4 -4
View File
@@ -60,8 +60,8 @@ github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl76
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -269,8 +269,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+2 -2
View File
@@ -27,7 +27,7 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
@@ -73,7 +73,7 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.70.0 // indirect
google.golang.org/protobuf v1.36.4 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.32.1 // indirect
+4 -4
View File
@@ -40,8 +40,8 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -195,8 +195,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+2 -2
View File
@@ -28,7 +28,7 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
@@ -74,7 +74,7 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.70.0 // indirect
google.golang.org/protobuf v1.36.4 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.32.1 // indirect
+4 -4
View File
@@ -40,8 +40,8 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -195,8 +195,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+8
View File
@@ -136,6 +136,14 @@ datasources:
tsdbResolution: 1
tsdbVersion: 3
- name: gdev-opentsdb-v2.4
type: opentsdb
access: proxy
url: http://localhost:4242
jsonData:
tsdbResolution: 1
tsdbVersion: 4
- name: gdev-elasticsearch
type: elasticsearch
uid: gdev-elasticsearch
+6 -2
View File
@@ -62,7 +62,7 @@ To configure basic settings for the data source, complete the following steps:
| **Default** | Default data source that will be be pre-selected for new panels. |
| **URL** | The HTTP protocol, IP, and port of your OpenTSDB server (default port is usually 4242). |
| **Allowed cookies** | Listing of cookies to forward to the data source. |
| **Version** | The OpenTSDB version. |
| **Version** | The OpenTSDB version (supported versions are: 2.4, 2.3, 2.2 and versions less than 2.1). |
| **Resolution** | Metrics from OpenTSDB may have data points with either second or millisecond resolution. |
| **Lookup limit** | Default is 1000. |
@@ -98,9 +98,13 @@ can be used to query OpenTSDB. Fill Policy is also introduced in OpenTSDB 2.2.
While using OpenTSDB 2.2 data source, make sure you use either Filters or Tags as they are mutually exclusive. If used together, might give you weird results.
{{% /admonition %}}
{{% admonition type="note" %}}
When using OpenTSDB 2.4 with alerting, queries are executed with the parameter `arrays=true`. This causes OpenTSDB to return data points as an array of arrays instead of a map of key-value pairs. Grafana then converts this data into the appropriate data frame format.
{{% /admonition %}}
### Auto complete suggestions
As soon as you start typing metric names, tag names and tag values , you should see highlighted auto complete suggestions for them.
As you begin typing metric names, tag names, or tag values, highlighted autocomplete suggestions will appear.
The autocomplete only works if the OpenTSDB suggest API is enabled.
## Templating queries
@@ -55,7 +55,7 @@ To add the Prometheus data source, complete the following steps:
1. Click **Connections** in the left-side menu.
1. Under **Connections**, click **Add new connection**.
1. Enter `Prometheus` in the search bar.
1. Select **Prometheus**.
1. Click **Prometheus data source**.
1. Click **Add new data source** in the upper right.
1. Enter a name for the data source.
@@ -18,11 +18,16 @@ labels:
- cloud
- enterprise
- oss
menuTitle: Configure data links
title: Configure data links
menuTitle: Configure data links and actions
title: Configure data links and actions
description: Configure data links to create links between dashboards and link to external resources
weight: 80
refs:
api-settings:
- pattern: /docs/grafana/
destination: /docs/grafana/<GRAFANA_VERSION>/panels-visualizations/visualizations/canvas/#button-api-options
- pattern: /docs/grafana-cloud/
destination: /docs/grafana/latest/panels-visualizations/visualizations/canvas/#button-api-options
global-variables:
- pattern: /docs/grafana/
destination: /docs/grafana/<GRAFANA_VERSION>/dashboards/variables/add-template-variables/#__from-and-__to
@@ -125,9 +130,14 @@ refs:
destination: /docs/grafana-cloud/visualizations/panels-visualizations/visualizations/bar-chart/
---
# Configure data links
# Configure data links and actions
Data links allow you to link to other panels, dashboards, and external resources while maintaining the context of the source panel. You can create links that include the series name or even the value under the cursor. For example, if your visualization shows four servers, you can add a data link to one or two of them.
_Data links_ allow you to link to other panels, dashboards, and external resources and _actions_ let you trigger basic, unauthenticated, API calls.
In both cases, you can carry out these tasks while maintaining the context of the source panel.
## Data links
With data links, you can create links that include the series name or even the value under the cursor. For example, if your visualization shows four servers, you can add a data link to one or two of them.
The link itself is accessible in different ways depending on the visualization. For the time series visualization you need to click a data point or line:
@@ -139,7 +149,7 @@ For visualizations like stat, gauge, or bar gauge you can click anywhere on the
If there's only one data link in the visualization, clicking anywhere on the visualization opens the link rather than the context menu.
## Supported visualizations
### Supported visualizations
You can configure data links for the following visualizations:
@@ -164,11 +174,32 @@ You can configure data links for the following visualizations:
{{< /column-list >}}
## Data link variables
## Actions
Variables in data links let you send people to a detailed dashboard with preserved data filters. For example, you could use variables to specify a label, time range, series, or variable selection.
Using actions, you can trigger processes like starting or shutting down a server, directly from a dashboard panel. [API settings](ref:api-settings) are configured in the **Add action** dialog box. You can also pass variables in the API editor.
To see a list of available variables, enter `$` in the data link **URL** field.
### Supported visualizations
You can configure actions for the following visualizations:
{{< column-list >}}
- [Bar chart](ref:bar-chart)
- [Candlestick](ref:candlestick)
- [State timeline](ref:state-timeline)
- [Status history](ref:status-history)
- [Table](ref:table)
- [Time series](ref:time-series)
- [Trend](ref:trend)
- [XY chart](ref:xy-chart)
{{< /column-list >}}
## Data link and action variables {#data-link-variables}
Variables in data links and actions let you send people to a detailed dashboard or trigger an API call with preserved data filters. For example, you could use variables to specify a label, time range, series, or variable selection.
To see a list of available variables, enter `$` in the data link or action **URL** field.
{{% admonition type="note" %}}
These variables changed in 6.4 so if you have an older version of Grafana, then use the version picker to select docs for an older version of Grafana.
@@ -176,11 +207,11 @@ These variables changed in 6.4 so if you have an older version of Grafana, then
Azure Monitor, [CloudWatch](ref:cloudwatch), and [Google Cloud Monitoring](ref:google-cloud-monitoring) have pre-configured data links called _deep links_.
You can also use template variables in your data links URLs. For more information, refer to [Templates and variables](ref:templates-and-variables).
You can also use template variables in your data links or actions URLs. For more information, refer to [Templates and variables](ref:templates-and-variables).
### Time range panel variables
These variables allow you to include the current time range in the data link URL:
These variables allow you to include the current time range in the data link or action URL:
| Variable | Description |
| ------------------ | ------------------------------------------------------------------------ |
@@ -188,7 +219,7 @@ These variables allow you to include the current time range in the data link URL
| `__from` | For more information, refer to [Global variables](ref:global-variables). |
| `__to` | For more information, refer to [Global variables](ref:global-variables). |
When you create data links using time range variables like `__url_time_range` in the URL, you have to form the query parameter syntax yourself; that is, you must format the URL by appending query parameters using the question mark (`?`) and ampersand (`&`) syntax. These characters aren't automatically generated.
When you create data links and actions using time range variables like `__url_time_range` in the URL, you have to form the query parameter syntax yourself; that is, you must format the URL by appending query parameters using the question mark (`?`) and ampersand (`&`) syntax. These characters aren't automatically generated.
### Series variables
@@ -219,9 +250,9 @@ Value-specific variables are available under `__value` namespace:
| `__value.text` | Text representation of a value |
| `__value.calc` | Calculation name if the value is result of calculation |
Using value-specific variables in data links can show different results depending on the set option of Tooltip mode.
Using value-specific variables in data links and actions can show different results depending on the set option of Tooltip mode.
When you create data links using time range variables like `__value.time` in the URL, you have to form the query parameter syntax yourself; that is, you must add the question mark (`?`) and ampersand (`&`). These characters aren't automatically generated.
When you create data links and actions using time range variables like `__value.time` in the URL, you have to form the query parameter syntax yourself; that is, you must add the question mark (`?`) and ampersand (`&`). These characters aren't automatically generated.
### Data variables
@@ -247,20 +278,29 @@ When linking to another dashboard that uses template variables, select variable
If you want to add all of the current dashboard's variables to the URL, then use `${__all_variables}`.
## Add a data link
## Add data links or actions {#add-a-data-link}
The following tasks describe how to configure data links and actions.
{{< tabs >}}
{{< tab-content name="Add data links" >}}
To add a data link, follow these steps:
1. Navigate to the panel to which you want to add the data link.
1. Hover over any part of the panel to display the menu icon in the upper-right corner.
1. Click the menu icon and select **Edit** to open the panel editor.
1. In the panel edit pane, scroll down to the **Data links** section and expand it.
1. Scroll down to the **Data links and actions** section and expand it.
1. Click **+ Add link**.
1. In the dialog box that opens, enter a **Title**. This is a human-readable label for the link displayed in the UI. This is a required field.
1. Enter the **URL** or variable to which you want to link. This is a required field.
1. In the dialog box that opens, enter a **Title**.
To add a data link variable, click in the **URL** field and enter `$` or press Ctrl+Space or Cmd+Space to see a list of available variables.
This is a human-readable label for the link displayed in the UI. This is a required field.
1. Enter the **URL** to which you want to link.
To add a data link variable, click in the **URL** field and enter `$` or press Ctrl+Space or Cmd+Space to see a list of available variables. This is a required field.
1. If you want the link to open in a new tab, toggle the **Open in a new tab** switch.
1. If you want the data link to open with a single click, toggle the **One click** switch.
1. If you want the data link to open with a single click on the visualization, toggle the **One click** switch.
Only one data link can have **One click** enabled at a time. **One click** is only supported for some visualizations.
@@ -268,4 +308,37 @@ If you want to add all of the current dashboard's variables to the URL, then use
1. Click **Save dashboard**.
1. Click **Back to dashboard** and then **Exit edit**.
If you add multiple data links, you can control the order in which they appear in the visualization. To do this, click and drag the data link to the desired position.
{{< /tab-content >}}
{{< tab-content name="Add actions" >}}
{{< admonition type="note">}}
Actions are not supported for all visualizations. For the list of supported visualizations, refer to [Supported visualizations](#supported-visualizations-1).
{{< /admonition >}}
To add an action, by follow these steps:
1. Navigate to the panel to which you want to add the action.
1. Hover over any part of the panel to display the menu icon in the upper-right corner.
1. Click the menu icon and select **Edit** to open the panel editor.
1. Scroll down to the **Data links and actions** section and expand it.
1. Click **+ Add action**.
1. In the dialog box that opens, define the API call settings:
| Option | Description |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Title | A human-readable label for the action that's displayed in the UI. |
| Confirmation message | A descriptive prompt to confirm or cancel the action. |
| Method | Select from **POST**, **PUT**, or **GET**. |
| URL | The request URL.</p><p>To add a variable, click in the **URL** field and enter `$` or press Ctrl+Space or Cmd+Space to see a list of available variables. |
| Query parameters | **Key** and **Value** pairs. Click the **+** icon to add as many key/value pairs as you need. |
| Headers | Comprised of **Key** and **Value** pairs and a **Content-Type**.</p><p>Click the **+** icon to add as many key/value pairs as you need. |
| Content-Type | Select from the following: **application/json**, **text/plain**, **application/XML**, and **application/x-www-form-urlencoded**. |
| Body | The body of the request. |
1. Click **Save** to save changes and close the dialog box.
1. Click **Save dashboard**.
1. Click **Back to dashboard** and then **Exit edit**.
{{< /tab-content >}}
{{< /tabs >}}
If you add multiple data links or actions, you can control the order in which they appear in the visualization. To do this, click and drag the data link or action to the desired position.
@@ -199,7 +199,7 @@ You can set standard min/max options to define hard limits of the Y-axis. For mo
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
### Data links
### Data links and actions
{{< docs/shared lookup="visualizations/datalink-options-2.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -211,7 +211,7 @@ This option only applies when bar size is set to manual.
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
## Data links
## Data links and actions
{{< docs/shared lookup="visualizations/datalink-options-1.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -136,7 +136,7 @@ The candlestick visualization is based on the time series visualization. It can
{{< docs/shared lookup="visualizations/tooltip-options-2.md" source="grafana" version="<GRAFANA_VERSION>" >}}
## Data links
## Data links and actions
{{< docs/shared lookup="visualizations/datalink-options-2.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -171,7 +171,7 @@ Adjust the sizes of the gauge text.
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
### Data links
### Data links and actions
{{< docs/shared lookup="visualizations/datalink-options-1.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -711,7 +711,7 @@ Displays debug information in the upper right corner. This can be useful for deb
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
### Data links
### Data links and actions
{{< docs/shared lookup="visualizations/datalink-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -208,7 +208,7 @@ Choose whether you want to display the heatmap legend on the visualization by to
Set the color used to show exemplar data.
### Data links
### Data links and actions
{{< docs/shared lookup="visualizations/datalink-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -157,7 +157,7 @@ Choose from the following:
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
## Data links
## Data links and actions
{{< docs/shared lookup="visualizations/datalink-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -174,7 +174,7 @@ Use these settings to define how the legend appears in your visualization. For m
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
### Data links
### Data links and actions
{{< docs/shared lookup="visualizations/datalink-options-1.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -172,7 +172,7 @@ Adjust the sizes of the gauge text.
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
### Data links
### Data links and actions
{{< docs/shared lookup="visualizations/datalink-options-1.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -157,7 +157,7 @@ The **Page size** option lets you paginate the state timeline visualization to l
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
### Data links
### Data links and actions
{{< docs/shared lookup="visualizations/datalink-options-2.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -143,7 +143,7 @@ Controls the opacity of state regions.
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
## Data links
## Data links and actions
{{< docs/shared lookup="visualizations/datalink-options-2.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -246,6 +246,7 @@ If you want to apply a cell type to only some fields instead of all fields, you
| Data links | If you've configured data links, when the cell type is **Auto**, the cell text becomes clickable. If you change the cell type to **Data links**, the cell text reflects the titles of the configured data links. To control the application of data link text more granularly, use a **Cell option > Cell type > Data links** field override. |
| [JSON View](#json-view) | Shows values formatted as code. |
| [Image](#image) | If the field value is an image URL or a base64 encoded image, the table displays the image. |
| [Actions](#actions) | The cell displays a button that triggers a basic, unauthenticated API call when clicked. |
##### Sparkline
@@ -333,6 +334,23 @@ Set the following options:
- **Alt text** - Set the alternative text of an image. The text will be available for screen readers and in cases when images can't be loaded.
- **Title text** - Set the text that's displayed when the image is hovered over with a cursor.
##### Actions
The cell displays a button that triggers a basic, unauthenticated API call when clicked.
Configure the API call with the following options:
<!-- prettier-ignore-start -->
| Option | Description |
| ------- | ------------ |
| Endpoint | Enter the endpoint URL. |
| Method | Choose from **GET**, **POST**, and **PUT**. |
| Content-Type | Select an option in the drop-down list. Choose from: JSON, Text, JavaScript, HTML, XML, and x-www-form-urlencoded. |
| Query parameters | Enter as many **Key**, **Value** pairs as you need. |
| Header parameters | Enter as many **Key**, **Value** pairs as you need. |
| Payload | Enter the body of the API call. |
<!-- prettier-ignore-end -->
#### Wrap text
{{< admonition type="note" >}}
@@ -362,9 +380,9 @@ If you want to apply this setting to only some fields instead of all fields, you
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
### Data links
### Data links and actions
{{< docs/shared lookup="visualizations/datalink-options-1.md" source="grafana" version="<GRAFANA_VERSION>" >}}
{{< docs/shared lookup="visualizations/datalink-options-3.md" source="grafana" version="<GRAFANA_VERSION>" >}}
### Value mappings
@@ -362,7 +362,7 @@ Set the position of the bar relative to a data point. In the examples below, **S
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
### Data links
### Data links and actions
{{< docs/shared lookup="visualizations/datalink-options-2.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -60,7 +60,7 @@ For example, you could represent engine power and torque versus speed where spee
{{< docs/shared lookup="visualizations/tooltip-options-2.md" source="grafana" version="<GRAFANA_VERSION>" >}}
## Data links
## Data links and actions
{{< docs/shared lookup="visualizations/datalink-options-2.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -308,7 +308,7 @@ You can customize the following standard options:
To learn more, refer to [Configure standard options](ref:configure-standard-options).
## Data links
## Data links and actions
{{< docs/shared lookup="visualizations/datalink-options-2.md" source="grafana" version="<GRAFANA_VERSION>" >}}
@@ -28,7 +28,6 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general-
| `featureHighlights` | Highlight Grafana Enterprise features | |
| `correlations` | Correlations page | Yes |
| `cloudWatchCrossAccountQuerying` | Enables cross-account querying in CloudWatch datasources | Yes |
| `accessControlOnCall` | Access control primitives for OnCall | Yes |
| `nestedFolders` | Enable folder nesting | Yes |
| `logsContextDatasourceUi` | Allow datasource to provide custom UI for context view | Yes |
| `lokiQuerySplitting` | Split large interval queries into subqueries with smaller time intervals | Yes |
@@ -131,7 +130,6 @@ Experimental features might be changed or removed without prior notice.
| `lokiExperimentalStreaming` | Support new streaming approach for loki (prototype, needs special loki build) |
| `storage` | Configurable storage for dashboards, datasources, and resources |
| `canvasPanelNesting` | Allow elements nesting |
| `vizActions` | Allow actions in visualizations |
| `disableSecretsCompatibility` | Disable duplicated secret storage in legacy tables |
| `logRequestsInstrumentedAsUnknown` | Logs the path for requests that are instrumented as unknown |
| `showDashboardValidationWarnings` | Show warnings when dashboards do not validate against the schema |
@@ -1,12 +1,16 @@
---
title: Data link options
title: Data links and actions options
comments: |
This file is used in the following visualizations: bar gauge, gauge, pie chart, stat, table
This file is used in the following visualizations: bar gauge, gauge, pie chart, stat
---
Data links allow you to link to other panels, dashboards, and external resources while maintaining the context of the source panel.
You can create links that include the series name or even the value under the cursor.
To learn more, refer to [Configure data links](../../configure-data-links/).
To learn more, refer to [Configure data links and actions](../../configure-data-links/).
{{< admonition type="note" >}}
Actions are not supported for this visualization.
{{< /admonition >}}
For each data link, set the following options:
@@ -14,4 +18,5 @@ For each data link, set the following options:
- **URL**
- **Open in new tab**
Data links for this visualization don't include the **One click** switch, however, if there's only one data link configured, that data link has single-click functionality. If multiple data links are configured, then clicking the visualization opens a menu that displays all the data links.
Data links for this visualization don't include the **One click** switch, however, if there's only one data link configured, that data link has single-click functionality.
If multiple data links are configured, then clicking the visualization opens a menu that displays all the data links.
@@ -1,10 +1,11 @@
---
title: Data link options
title: Data links and actions options
comments: |
This file is used in the following visualizations: bar chart, candlestick, state timeline, status history, time series, trend, xy chart
---
Data links allow you to link to other panels, dashboards, and external resources while maintaining the context of the source panel. You can create links that include the series name or even the value under the cursor.
_Data links_ allow you to link to other panels, dashboards, and external resources and _actions_ let you trigger basic, unauthenticated, API calls.
In both cases, you can carry out these tasks while maintaining the context of the source panel.
For each data link, set the following options:
@@ -13,4 +14,21 @@ For each data link, set the following options:
- **Open in new tab**
- **One click** - Opens the data link with a single click. Only one data link can have **One click** enabled at a time.
To learn more, refer to [Configure data links](../../configure-data-links/).
For each action, define the following API call settings:
<!-- prettier-ignore-start -->
| Option | Description |
| -------------------- | ----------------------------------------------------------------- |
| Title | A human-readable label for the action that's displayed in the UI. |
| Confirmation message | A descriptive prompt to confirm or cancel the action. |
| Method | Select from **POST**, **PUT**, or **GET**. |
| URL | The request URL.</p><p>To add a variable, click in the **URL** field and enter `$` or press Ctrl+Space or Cmd+Space to see a list of available variables. |
| Query parameters | **Key** and **Value** pairs. Click the **+** icon to add as many key/value pairs as you need. |
| Headers | Comprised of **Key** and **Value** pairs and a **Content-Type**.</p><p>Click the **+** icon to add as many key/value pairs as you need. |
| Content-Type | Select from the following: **application/json**, **text/plain**, **application/XML**, and **application/x-www-form-urlencoded**. |
| Body | The body of the request. |
<!-- prettier-ignore-end -->
To learn more, refer to [Configure data links and actions](../../configure-data-links/).
@@ -0,0 +1,36 @@
---
title: Data links and actions options
comments: |
This file is used in the following visualizations: table
---
_Data links_ allow you to link to other panels, dashboards, and external resources and _actions_ let you trigger basic, unauthenticated, API calls.
In both cases, you can carry out these tasks while maintaining the context of the source panel.
For each data link, set the following options:
- **Title**
- **URL**
- **Open in new tab**
Data links for this visualization don't include the **One click** switch, however, if there's only one data link configured, that data link has single-click functionality.
If multiple data links are configured, then clicking the visualization opens a menu that displays all the data links.
For each action, define the following API call settings:
<!-- prettier-ignore-start -->
| Option | Description |
| -------------------- | ----------------------------------------------------------------- |
| Title | A human-readable label for the action that's displayed in the UI. |
| Confirmation message | A descriptive prompt to confirm or cancel the action. |
| Method | Select from **POST**, **PUT**, or **GET**. |
| URL | The request URL.</p><p>To add a variable, click in the **URL** field and enter `$` or press Ctrl+Space or Cmd+Space to see a list of available variables. |
| Query parameters | **Key** and **Value** pairs. Click the **+** icon to add as many key/value pairs as you need. |
| Headers | Comprised of **Key** and **Value** pairs and a **Content-Type**.</p><p>Click the **+** icon to add as many key/value pairs as you need. |
| Content-Type | Select from the following: **application/json**, **text/plain**, **application/XML**, and **application/x-www-form-urlencoded**. |
| Body | The body of the request. |
<!-- prettier-ignore-end -->
To learn more, refer to [Configure data links and actions](../../configure-data-links/).
@@ -1,10 +1,15 @@
---
title: Data link options
title: Data links and actions options
comments: |
This file is used in the following visualizations: geomap, heatmap, histogram
---
Data links allow you to link to other panels, dashboards, and external resources while maintaining the context of the source panel. You can create links that include the series name or even the value under the cursor.
Data links allow you to link to other panels, dashboards, and external resources while maintaining the context of the source panel.
You can create links that include the series name or even the value under the cursor.
{{< admonition type="note" >}}
Actions are not supported for this visualization.
{{< /admonition >}}
For each data link, set the following options:
@@ -12,4 +17,4 @@ For each data link, set the following options:
- **URL**
- **Open in new tab**
To learn more, refer to [Configure data links](../../configure-data-links/).
To learn more, refer to [Configure data links and actions](../../configure-data-links/).
+15 -6
View File
@@ -6,6 +6,7 @@ require (
buf.build/gen/go/parca-dev/parca/connectrpc/go v1.17.0-20240902100956-02fd72488966.1 // @grafana/observability-traces-and-profiling
buf.build/gen/go/parca-dev/parca/protocolbuffers/go v1.34.2-20240902100956-02fd72488966.2 // @grafana/observability-traces-and-profiling
cloud.google.com/go/kms v1.20.0 // @grafana/grafana-backend-group
cloud.google.com/go/spanner v1.70.0 // @grafana/grafana-search-and-storage
cloud.google.com/go/storage v1.43.0 // @grafana/grafana-backend-group
connectrpc.com/connect v1.17.0 // @grafana/observability-traces-and-profiling
cuelang.org/go v0.11.1 // @grafana/grafana-as-code
@@ -64,7 +65,7 @@ require (
github.com/golang/mock v1.7.0-rc.1 // @grafana/alerting-backend
github.com/golang/protobuf v1.5.4 // @grafana/grafana-backend-group
github.com/golang/snappy v0.0.4 // @grafana/alerting-backend
github.com/google/go-cmp v0.6.0 // @grafana/grafana-backend-group
github.com/google/go-cmp v0.7.0 // @grafana/grafana-backend-group
github.com/google/go-querystring v1.1.0 // indirect; @grafana/oss-big-tent
github.com/google/uuid v1.6.0 // @grafana/grafana-backend-group
github.com/google/wire v0.6.0 // @grafana/grafana-backend-group
@@ -72,8 +73,8 @@ require (
github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group
github.com/gorilla/websocket v1.5.3 // @grafana/grafana-app-platform-squad
github.com/grafana/alerting v0.0.0-20250224133628-2acbeef29642 // @grafana/alerting-backend
github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7 // @grafana/identity-access-team
github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31 // @grafana/identity-access-team
github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 // @grafana/identity-access-team
github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 // @grafana/identity-access-team
github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics
github.com/grafana/dataplane/sdata v0.0.9 // @grafana/observability-metrics
github.com/grafana/dskit v0.0.0-20241105154643-a6b453a88040 // @grafana/grafana-backend-group
@@ -87,7 +88,7 @@ require (
github.com/grafana/grafana-cloud-migration-snapshot v1.6.0 // @grafana/grafana-operator-experience-squad
github.com/grafana/grafana-google-sdk-go v0.2.1 // @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.266.0 // @grafana/plugins-platform-backend
github.com/grafana/grafana-plugin-sdk-go v0.267.0 // @grafana/plugins-platform-backend
github.com/grafana/loki/v3 v3.2.1 // @grafana/observability-logs
github.com/grafana/otel-profiling-go v0.5.1 // @grafana/grafana-backend-group
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // @grafana/observability-traces-and-profiling
@@ -179,7 +180,7 @@ require (
gonum.org/v1/gonum v0.15.1 // @grafana/oss-big-tent
google.golang.org/api v0.216.0 // @grafana/grafana-backend-group
google.golang.org/grpc v1.70.0 // @grafana/plugins-platform-backend
google.golang.org/protobuf v1.36.4 // @grafana/plugins-platform-backend
google.golang.org/protobuf v1.36.5 // @grafana/plugins-platform-backend
gopkg.in/ini.v1 v1.67.0 // @grafana/alerting-backend
gopkg.in/mail.v2 v2.3.1 // @grafana/grafana-backend-group
gopkg.in/yaml.v3 v3.0.1 // @grafana/alerting-backend
@@ -226,6 +227,7 @@ require (
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/iam v1.2.1 // indirect
cloud.google.com/go/longrunning v0.6.1 // indirect
cloud.google.com/go/monitoring v1.21.1 // indirect
cuelabs.dev/go/oci/ociregistry v0.0.0-20240906074133-82eb438dd565 // indirect
dario.cat/mergo v1.0.1 // indirect
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
@@ -241,6 +243,8 @@ require (
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 // indirect
github.com/FZambia/eagle v0.1.0 // indirect
github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect
github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
@@ -304,12 +308,14 @@ require (
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500 // indirect
github.com/caio/go-tdigest v3.1.0+incompatible // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
github.com/centrifugal/protocol v0.13.4 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cheekybits/genny v1.0.0 // indirect
github.com/chromedp/cdproto v0.0.0-20240810084448-b931b754e476 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
@@ -325,10 +331,11 @@ require (
github.com/dolthub/maphash v0.1.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/edsrzf/mmap-go v1.2.0 // indirect
github.com/elazarl/goproxy v1.7.0 // indirect
github.com/elazarl/goproxy v1.7.1 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/emicklei/proto v1.13.2 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/envoyproxy/go-control-plane v0.13.1 // indirect
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
@@ -512,9 +519,11 @@ require (
go.mongodb.org/mongo-driver v1.16.1 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.32.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/mock v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
+30 -11
View File
@@ -187,6 +187,7 @@ cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvj
cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA=
cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs=
cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU=
cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE=
cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI=
cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU=
@@ -390,6 +391,8 @@ cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhI
cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4=
cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w=
cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw=
cloud.google.com/go/monitoring v1.21.1 h1:zWtbIoBMnU5LP9A/fz8LmWMGHpk4skdfeiaa66QdFGc=
cloud.google.com/go/monitoring v1.21.1/go.mod h1:Rj++LKrlht9uBi8+Eb530dIrzG/cU/lB8mt+lbeFK1c=
cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA=
cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o=
cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM=
@@ -536,6 +539,8 @@ cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+
cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos=
cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk=
cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M=
cloud.google.com/go/spanner v1.70.0 h1:nj6p/GJTgMDiSQ1gQ034ItsKuJgHiMOjtOlONOg8PSo=
cloud.google.com/go/spanner v1.70.0/go.mod h1:X5T0XftydYp0K1adeJQDJtdWpbrOeJ7wHecM4tK6FiE=
cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM=
cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ=
cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0=
@@ -706,6 +711,10 @@ github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/FZambia/eagle v0.1.0 h1:9gyX6x+xjoIfglgyPTcYm7dvY7FJ93us1QY5De4CyXA=
github.com/FZambia/eagle v0.1.0/go.mod h1:YjGSPVkQTNcVLfzEUQJNgW9ScPR0K4u/Ky0yeFa4oDA=
github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0 h1:oVLqHXhnYtUwM89y9T1fXGaK9wTkXHgNp8/ZNMQzUxE=
github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0/go.mod h1:dppbR7CwXD4pgtV9t3wD1812RaLDcBjtblcDF5f1vI0=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM=
github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM=
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU=
@@ -954,6 +963,7 @@ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK3
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
github.com/centrifugal/centrifuge v0.33.3 h1:uyqBc27oM+qnC3NX5imvZxuk9+u2ze6QGWHDICZeoSc=
github.com/centrifugal/centrifuge v0.33.3/go.mod h1:GaOF4CiREY5x6lW7zYUz46Qrc6aUZ6J/AMV/kROc2+U=
@@ -992,6 +1002,7 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI=
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
@@ -1083,8 +1094,8 @@ github.com/edsrzf/mmap-go v1.2.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8E
github.com/efficientgo/core v1.0.0-rc.3 h1:X6CdgycYWDcbYiJr1H1+lQGzx13o7bq3EUkbB9DsSPc=
github.com/efficientgo/core v1.0.0-rc.3/go.mod h1:FfGdkzWarkuzOlY04VY+bGfb1lWrjaL6x/GLcQ4vJps=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v1.7.0 h1:EXv2nV4EjM60ZtsEVLYJG4oBXhDGutMKperpHsZ/v+0=
github.com/elazarl/goproxy v1.7.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ=
github.com/elazarl/goproxy v1.7.1 h1:1P7LPSxbqtNxusFnXclj6O56pjfq1xOQZ6a0mwwKUlY=
github.com/elazarl/goproxy v1.7.1/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
@@ -1103,12 +1114,14 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34=
github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI=
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q=
github.com/envoyproxy/go-control-plane v0.13.1 h1:vPfJZCkob6yTMEgS+0TwfTUfbHjfy/6vOJ8hUWX/uXE=
github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo=
github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM=
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
@@ -1409,8 +1422,9 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
@@ -1513,10 +1527,10 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grafana/alerting v0.0.0-20250224133628-2acbeef29642 h1:iQ0h/h+QoguSZDF+ZpPxcM/C+m1kjh+aXjMpxywowPA=
github.com/grafana/alerting v0.0.0-20250224133628-2acbeef29642/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM=
github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7 h1:NTMmow+74I3Jb033xhbRgWQS7A//5TDhiM4tl7bsVP4=
github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7/go.mod h1:T3X4z0ejGfJOiOmZLFeKCRT/yxWJq/RtclAc/PHj/w4=
github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31 h1:EokLC5grHwLPs4tXW8T6E8187H1e5G9AP0QQ5B60HbA=
github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 h1:FTuDRy/Shw8yOdG+v1DnkeuaCAl8fvwgcfaG9Wccuhg=
github.com/grafana/authlib v0.0.0-20250225105729-99e678595501/go.mod h1:XVpdLhaeYqz414FmGnW00/0vTe1x8c0GRH3KaeRtyg0=
github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 h1:DnRUYiAotHXnrfYJCvhH1NkiyWVcPm5Pd+P7Ugqt/d8=
github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
github.com/grafana/dataplane/examples v0.0.1 h1:K9M5glueWyLoL4//H+EtTQq16lXuHLmOhb6DjSCahzA=
github.com/grafana/dataplane/examples v0.0.1/go.mod h1:h5YwY8s407/17XF5/dS8XrUtsTVV2RnuW8+m1Mp46mg=
github.com/grafana/dataplane/sdata v0.0.9 h1:AGL1LZnCUG4MnQtnWpBPbQ8ZpptaZs14w6kE/MWfg7s=
@@ -1545,8 +1559,8 @@ github.com/grafana/grafana-google-sdk-go v0.2.1 h1:XeFdKnkXBjOJjXc1gf4iMx4h5aCHT
github.com/grafana/grafana-google-sdk-go v0.2.1/go.mod h1:RiITSHwBhqVTTd3se3HQq5Ncs/wzzhTB9OK5N0J0PEU=
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.266.0 h1:YP+iEpXH3HRX9Xo4NHjsrJhN2W7uVTtkLNzMHYbmiLI=
github.com/grafana/grafana-plugin-sdk-go v0.266.0/go.mod h1:bxkXrBQ4QSmOncsWdIOcpgP+M6wajQNMAPXlbWrqAWY=
github.com/grafana/grafana-plugin-sdk-go v0.267.0 h1:4AcuLEE0UeFG0Eo3P8r1FDS89hgZZ73K550DRz1fgjQ=
github.com/grafana/grafana-plugin-sdk-go v0.267.0/go.mod h1:OuwS4c/JYgn0rr/w5zhJBpLo4gKm/vw15RsfpYAvK9Q=
github.com/grafana/grafana/apps/advisor v0.0.0-20250220163425-b4c4b9abbdc8 h1:mG/6nDlEBVxWlo2GQJVASzucw3ByPIBsec06XcPrjgQ=
github.com/grafana/grafana/apps/advisor v0.0.0-20250220163425-b4c4b9abbdc8/go.mod h1:9I1dKV3Dqr0NPR9Af0WJGxOytp5/6W3JLiNChOz8r+c=
github.com/grafana/grafana/apps/alerting/notifications v0.0.0-20250220163425-b4c4b9abbdc8 h1:w42GlvkmHG4nM/p1kb2nKmROVP+AHtL3qWEYMhnhCVM=
@@ -2316,6 +2330,7 @@ github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
@@ -2448,6 +2463,8 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/collector/pdata v1.22.0 h1:3yhjL46NLdTMoP8rkkcE9B0pzjf2973crn0KKhX5UrI=
go.opentelemetry.io/collector/pdata v1.22.0/go.mod h1:nLLf6uDg8Kn5g3WNZwGyu8+kf77SwOqQvMTb5AXEbEY=
go.opentelemetry.io/contrib/detectors/gcp v1.32.0 h1:P78qWqkLSShicHmAzfECaTgvslqHxblNE9j62Ws1NK8=
go.opentelemetry.io/contrib/detectors/gcp v1.32.0/go.mod h1:TVqo0Sda4Cv8gCIixd7LuLwW4EylumVWfhjZJjDD4DU=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4=
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.55.0/go.mod h1:rsg1EO8LXSs2po50PB5CeY/MSVlhghuKBgXlKnqm6ks=
@@ -3314,9 +3331,11 @@ google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCD
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
@@ -3339,8 +3358,8 @@ google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
+3 -12
View File
@@ -142,8 +142,6 @@ cloud.google.com/go/memcache v1.11.1 h1:2FGuyd3WY7buNDAkMBdmeIOheNWA3gwaXrttLrEd
cloud.google.com/go/memcache v1.11.1/go.mod h1:3zF+dEqmEmElHuO4NtHiShekQY5okQtssjPBv7jpmZ8=
cloud.google.com/go/metastore v1.14.1 h1:kGx+IUSSYCVn8LisCT4fpxCC9rauEVonzi7RlygdqWY=
cloud.google.com/go/metastore v1.14.1/go.mod h1:WDvsAcbQLl9M4xL+eIpbKogH7aEaPWMhO9aRBcFOnJE=
cloud.google.com/go/monitoring v1.21.1 h1:zWtbIoBMnU5LP9A/fz8LmWMGHpk4skdfeiaa66QdFGc=
cloud.google.com/go/monitoring v1.21.1/go.mod h1:Rj++LKrlht9uBi8+Eb530dIrzG/cU/lB8mt+lbeFK1c=
cloud.google.com/go/networkconnectivity v1.15.1 h1:EizN+cFGHzRAyiFTK8jT1PqTo+cSnbc2IGh6OmllS7Y=
cloud.google.com/go/networkconnectivity v1.15.1/go.mod h1:tYAcT4Ahvq+BiePXL/slYipf/8FF0oNJw3MqFhBnSPI=
cloud.google.com/go/networkmanagement v1.14.1 h1:0x3hVI6xbp3N/choffKPHMSxbzaPdHSD92cBElebXEk=
@@ -204,8 +202,6 @@ cloud.google.com/go/servicemanagement v1.8.0 h1:fopAQI/IAzlxnVeiKn/8WiV6zKndjFkv
cloud.google.com/go/serviceusage v1.6.0 h1:rXyq+0+RSIm3HFypctp7WoXxIA563rn206CfMWdqXX4=
cloud.google.com/go/shell v1.8.1 h1:etoJal+LB7Pn8+5vE2aAh6QcFbBmerIOh5MxNDoXykw=
cloud.google.com/go/shell v1.8.1/go.mod h1:jaU7OHeldDhTwgs3+clM0KYEDYnBAPevUI6wNLf7ycE=
cloud.google.com/go/spanner v1.70.0 h1:nj6p/GJTgMDiSQ1gQ034ItsKuJgHiMOjtOlONOg8PSo=
cloud.google.com/go/spanner v1.70.0/go.mod h1:X5T0XftydYp0K1adeJQDJtdWpbrOeJ7wHecM4tK6FiE=
cloud.google.com/go/speech v1.25.1 h1:iGZJS3wrdkje/Vqiacx1+r+zVwUZoXVMdklYIVsvfNw=
cloud.google.com/go/speech v1.25.1/go.mod h1:WgQghvghkZ1htG6BhYn98mP7Tg0mti8dBFDLMVXH/vM=
cloud.google.com/go/storagetransfer v1.11.1 h1:Hd7H1zXGQGEWyWXxWVXDMuNCGasNQim1y9CIaMZIBX8=
@@ -280,10 +276,6 @@ github.com/DmitriyVTitov/size v1.5.0 h1:/PzqxYrOyOUX1BXj6J9OuVRVGe+66VL4D9FlUaW5
github.com/DmitriyVTitov/size v1.5.0/go.mod h1:le6rNI4CoLQV1b9gzp1+3d7hMAD/uu2QcJ+aYbNgiU0=
github.com/GoogleCloudPlatform/cloudsql-proxy v1.36.0 h1:kAtNAWwvTt5+iew6baV0kbOrtjYTXPtWNSyOFlcxkBU=
github.com/GoogleCloudPlatform/cloudsql-proxy v1.36.0/go.mod h1:VRKXU8C7Y/aUKjRBTGfw0Ndv4YqNxlB8zAPJJDxbASE=
github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0 h1:oVLqHXhnYtUwM89y9T1fXGaK9wTkXHgNp8/ZNMQzUxE=
github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0/go.mod h1:dppbR7CwXD4pgtV9t3wD1812RaLDcBjtblcDF5f1vI0=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM=
github.com/IBM/go-sdk-core/v5 v5.17.4 h1:VGb9+mRrnS2HpHZFM5hy4J6ppIWnwNrw0G+tLSgcJLc=
github.com/IBM/go-sdk-core/v5 v5.17.4/go.mod h1:KsAAI7eStAWwQa4F96MLy+whYSh39JzNjklZRbN/8ns=
github.com/IBM/ibm-cos-sdk-go v1.11.0 h1:Jp55NLN3OvBwucMGpP5wNybyjncsmTZ9+GPHai/1cE8=
@@ -387,7 +379,6 @@ github.com/bytedance/sonic v1.10.0-rc3 h1:uNSnscRapXTwUgTyOF0GVljYD08p9X/Lbr9Mwe
github.com/bytedance/sonic v1.10.0-rc3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/campoy/embedmd v1.0.0 h1:V4kI2qTJJLf4J29RzI/MAt2c3Bl4dQSYPuflzwFH2hY=
github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8=
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
@@ -510,6 +501,7 @@ github.com/elastic/go-sysinfo v1.11.2/go.mod h1:GKqR8bbMK/1ITnez9NIsIfXQr25aLhRJ
github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0=
github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss=
github.com/elazarl/goproxy v1.3.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ=
github.com/elazarl/goproxy v1.7.1 h1:1P7LPSxbqtNxusFnXclj6O56pjfq1xOQZ6a0mwwKUlY=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
@@ -593,6 +585,7 @@ github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs0
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/cel-go v0.22.0/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-jsonnet v0.18.0 h1:/6pTy6g+Jh1a1I2UMoAODkqELFiVIdOxbNwv0DDzoOg=
github.com/google/go-jsonnet v0.18.0/go.mod h1:C3fTzyVJDslXdiTqw/bTFk7vSGyCtH3MGRbDfvEwGd0=
@@ -908,7 +901,6 @@ github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad h1:fiWzISvDn0Csy5H0iwgAuJ
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stoewer/parquet-cli v0.0.7 h1:rhdZODIbyMS3twr4OM3am8BPPT5pbfMcHLH93whDM5o=
github.com/stoewer/parquet-cli v0.0.7/go.mod h1:bskxHdj8q3H1EmfuCqjViFoeO3NEvs5lzZAQvI8Nfjk=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/substrait-io/substrait v0.57.1 h1:GW8nnYfSowMseHR8Os82/X6lNtQGIK7p4p+lr6r+auw=
github.com/substrait-io/substrait v0.57.1/go.mod h1:q9s+tjo+gK0lsA+SqYB0lhojNuxvdPdfYlGUP0hjbrA=
github.com/substrait-io/substrait-go v1.2.0 h1:3ZNRkc8FYD7ifCagKEOZQtUcgMceMQfwo2N1NGaK4Q4=
@@ -1056,8 +1048,6 @@ go.opentelemetry.io/contrib/bridges/prometheus v0.53.0 h1:BdkKDtcrHThgjcEia1737O
go.opentelemetry.io/contrib/bridges/prometheus v0.53.0/go.mod h1:ZkhVxcJgeXlL/lVyT/vxNHVFiSG5qOaDwYaSgD8IfZo=
go.opentelemetry.io/contrib/config v0.7.0 h1:b1rK5tGTuhhPirJiMxOcyQfZs76j2VapY6ODn3b2Dbs=
go.opentelemetry.io/contrib/config v0.7.0/go.mod h1:8tdiFd8N5etOi3XzBmAoMxplEzI3TcL8dU5rM5/xcOQ=
go.opentelemetry.io/contrib/detectors/gcp v1.32.0 h1:P78qWqkLSShicHmAzfECaTgvslqHxblNE9j62Ws1NK8=
go.opentelemetry.io/contrib/detectors/gcp v1.32.0/go.mod h1:TVqo0Sda4Cv8gCIixd7LuLwW4EylumVWfhjZJjDD4DU=
go.opentelemetry.io/contrib/exporters/autoexport v0.53.0 h1:13K+tY7E8GJInkrvRiPAhC0gi/7vKjzDNhtmCf+QXG8=
go.opentelemetry.io/contrib/exporters/autoexport v0.53.0/go.mod h1:lyQF6xQ4iDnMg4sccNdFs1zf62xd79YI8vZqKjOTwMs=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
@@ -1198,6 +1188,7 @@ google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojt
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
@@ -36,14 +36,12 @@ export interface FeatureToggles {
autoMigrateStatPanel?: boolean;
disableAngular?: boolean;
canvasPanelNesting?: boolean;
vizActions?: boolean;
disableSecretsCompatibility?: boolean;
logRequestsInstrumentedAsUnknown?: boolean;
grpcServer?: boolean;
cloudWatchCrossAccountQuerying?: boolean;
showDashboardValidationWarnings?: boolean;
mysqlAnsiQuotes?: boolean;
accessControlOnCall?: boolean;
nestedFolders?: boolean;
alertingBacktesting?: boolean;
editPanelCSVDragAndDrop?: boolean;
@@ -173,7 +171,6 @@ export interface FeatureToggles {
newDashboardSharingComponent?: boolean;
alertingListViewV2?: boolean;
dashboardRestore?: boolean;
datasourceProxyDisableRBAC?: boolean;
alertingDisableSendAlertsExternal?: boolean;
preserveDashboardStateWhenNavigating?: boolean;
alertingCentralAlertHistory?: boolean;
@@ -4,6 +4,7 @@ export enum UnaryOperationID {
Abs = 'abs',
Exp = 'exp',
Ln = 'ln',
Round = 'round',
Floor = 'floor',
Ceil = 'ceil',
}
@@ -35,6 +36,12 @@ export const unaryOperators = new Registry<UnaryOperatorInfo>(() => {
operation: (value: number) => Math.log(value),
unaryOperationID: UnaryOperationID.Ln,
},
{
id: UnaryOperationID.Round,
name: 'Round',
operation: (value: number) => Math.round(value),
unaryOperationID: UnaryOperationID.Round,
},
{
id: UnaryOperationID.Floor,
name: 'Floor',
@@ -7,6 +7,7 @@ import { selectors } from '@grafana/e2e-selectors';
import { useTheme2 } from '../../themes';
import { IconName } from '../../types/icon';
import { t } from '../../utils/i18n';
import { Button } from '../Button/Button';
import { Icon } from '../Icon/Icon';
import { Box } from '../Layout/Box/Box';
@@ -53,6 +54,8 @@ export const Alert = React.forwardRef<HTMLDivElement, Props>(
const role = restProps['role'] || rolesBySeverity[severity];
const ariaLabel = restProps['aria-label'] || title;
const closeLabel = t('grafana-ui.alert.close-button', 'Close alert');
return (
<div ref={ref} className={cx(styles.wrapper, className)} role={role} aria-label={ariaLabel} {...restProps}>
<Box
@@ -83,7 +86,7 @@ export const Alert = React.forwardRef<HTMLDivElement, Props>(
{onRemove && !buttonContent && (
<div className={styles.close}>
<Button
aria-label="Close alert"
aria-label={closeLabel}
icon="times"
onClick={onRemove}
type="button"
@@ -95,7 +98,7 @@ export const Alert = React.forwardRef<HTMLDivElement, Props>(
{onRemove && buttonContent && (
<Box marginLeft={1} display="flex" alignItems="center">
<Button aria-label="Close alert" variant="secondary" onClick={onRemove} type="button">
<Button aria-label={closeLabel} variant="secondary" onClick={onRemove} type="button">
{buttonContent}
</Button>
</Box>
@@ -6,6 +6,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '../../themes';
import { getFocusStyles } from '../../themes/mixins';
import { t } from '../../utils/i18n';
import { CardContainer, CardContainerProps, getCardContainerStyles } from './CardContainer';
@@ -102,6 +103,7 @@ const Heading = ({ children, className, 'aria-label': ariaLabel }: ChildProps &
onClick: undefined,
isSelected: undefined,
};
const optionLabel = t('grafana-ui.card.option', 'option');
return (
<h2 className={cx(styles.heading, className)}>
@@ -117,7 +119,7 @@ const Heading = ({ children, className, 'aria-label': ariaLabel }: ChildProps &
<>{children}</>
)}
{/* Input must be readonly because we are providing a value for the checked prop with no onChange handler */}
{isSelected !== undefined && <input aria-label="option" type="radio" checked={isSelected} readOnly />}
{isSelected !== undefined && <input aria-label={optionLabel} type="radio" checked={isSelected} readOnly />}
</h2>
);
};
@@ -8,6 +8,7 @@ import { SelectableValue } from '@grafana/data';
import { withTheme2 } from '../../themes';
import { Themeable2 } from '../../types';
import { t } from '../../utils/i18n';
import { Icon } from '../Icon/Icon';
import { IconButton } from '../IconButton/IconButton';
import { Input } from '../Input/Input';
@@ -286,7 +287,7 @@ class UnthemedCascader extends PureComponent<CascaderProps, CascaderState> {
{isClearable && activeLabel !== '' && (
<IconButton
name="times"
aria-label="Clear selection"
aria-label={t('grafana-ui.cascader.clear-button', 'Clear selection')}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
@@ -3,6 +3,7 @@ import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2, useTheme2 } from '../../themes/ThemeContext';
import { t } from '../../utils/i18n';
import { ColorSwatch } from './ColorSwatch';
import NamedColorsGroup from './NamedColorsGroup';
@@ -28,13 +29,13 @@ export const NamedColorsPalette = ({ color, onChange }: NamedColorsPaletteProps)
<ColorSwatch
isSelected={color === 'transparent'}
color={'rgba(0,0,0,0)'}
label="Transparent"
label={t('grafana-ui.named-colors-palette.transparent-swatch', 'Transparent')}
onClick={() => onChange('transparent')}
/>
<ColorSwatch
isSelected={color === 'text'}
color={theme.colors.text.primary}
label="Text color"
label={t('grafana-ui.named-colors-palette.text-color-swatch', 'Text color')}
onClick={() => onChange('text')}
/>
</div>
@@ -1,4 +1,5 @@
import { withTheme2 } from '../../themes';
import { t } from '../../utils/i18n';
import { InlineField } from '../Forms/InlineField';
import { InlineSwitch } from '../Switch/Switch';
import { PopoverContentProps } from '../Tooltip';
@@ -12,15 +13,15 @@ export interface SeriesColorPickerPopoverProps extends ColorPickerProps, Popover
export const SeriesColorPickerPopover = (props: SeriesColorPickerPopoverProps) => {
const { yaxis, onToggleAxis, color, ...colorPickerProps } = props;
const yAxisLabel = t('grafana-ui.series-color-picker-popover.y-axis-usage', 'Use right y-axis');
const customPickers = onToggleAxis
? {
yaxis: {
name: 'Y-Axis',
tabComponent() {
return (
<InlineField labelWidth={20} label="Use right y-axis">
<InlineSwitch value={yaxis === 2} label="Use right y-axis" onChange={onToggleAxis} />
<InlineField labelWidth={20} label={yAxisLabel}>
<InlineSwitch value={yaxis === 2} label={yAxisLabel} onChange={onToggleAxis} />
</InlineField>
);
},
@@ -4,6 +4,7 @@ import { forwardRef } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '../../themes';
import { t } from '../../utils/i18n';
import { IconButton } from '../IconButton/IconButton';
interface ValuePillProps {
@@ -15,6 +16,7 @@ interface ValuePillProps {
export const ValuePill = forwardRef<HTMLSpanElement, ValuePillProps>(
({ children, onRemove, disabled, ...rest }, ref) => {
const styles = useStyles2(getValuePillStyles, disabled);
const removeButtonLabel = t('grafana-ui.value-pill.remove-button', 'Remove {{children}}', { children });
return (
<span className={styles.wrapper} {...rest} ref={ref}>
<span className={styles.text}>{children}</span>
@@ -24,7 +26,7 @@ export const ValuePill = forwardRef<HTMLSpanElement, ValuePillProps>(
<IconButton
name="times"
size="md"
aria-label={`Remove ${children}`}
aria-label={removeButtonLabel}
onClick={(e) => {
e.stopPropagation();
onRemove();
@@ -7,6 +7,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { useStyles2 } from '../../themes';
import { t } from '../../utils/i18n';
import { Button, ButtonVariant } from '../Button';
import { Field } from '../Forms/Field';
import { Input } from '../Input/Input';
@@ -90,7 +91,9 @@ export const ConfirmContent = ({
};
const { handleSubmit } = useForm();
const placeholder = t('grafana-ui.confirm-content.placeholder', 'Type "{{confirmPromptText}}" to confirm', {
confirmPromptText,
});
return (
<form onSubmit={handleSubmit(onConfirmClick)}>
<div className={styles.text}>
@@ -100,7 +103,7 @@ export const ConfirmContent = ({
<div className={styles.confirmationInput}>
<Stack alignItems="flex-start">
<Field disabled={disabled}>
<Input placeholder={`Type "${confirmPromptText}" to confirm`} onChange={onConfirmationTextChange} />
<Input placeholder={placeholder} onChange={onConfirmationTextChange} />
</Field>
</Stack>
</div>
@@ -53,15 +53,19 @@ export const DataLinkEditor = memo(
return (
<div className={styles.listItem}>
<Field label="Title">
<Input value={value.title} onChange={onTitleChange} placeholder="Show details" />
<Field label={t('grafana-ui.data-link-editor.title-label', 'Title')}>
<Input
value={value.title}
onChange={onTitleChange}
placeholder={t('grafana-ui.data-link-editor.title-placeholder', 'Show details')}
/>
</Field>
<Field label="URL">
<Field label={t('grafana-ui.data-link-editor.url-label', 'URL')}>
<DataLinkInput value={value.url} onChange={onUrlChange} suggestions={suggestions} />
</Field>
<Field label="Open in new tab">
<Field label={t('grafana-ui.data-link-editor.new-tab-label', 'Open in new tab')}>
<Switch value={value.targetBlank || false} onChange={onOpenInNewTabChanged} />
</Field>
@@ -6,7 +6,7 @@ import { DataLinksContextMenu } from './DataLinksContextMenu';
const fakeAriaLabel = 'fake aria label';
describe('DataLinksContextMenu', () => {
it('renders context menu when there are more than one data links or actions', () => {
it('renders context menu when there are more than one data links', () => {
render(
<DataLinksContextMenu
links={() => [
@@ -23,7 +23,6 @@ describe('DataLinksContextMenu', () => {
origin: {},
},
]}
actions={[{ title: 'Action1', onClick: () => {} }]}
>
{() => {
return <div aria-label="fake aria label" />;
@@ -35,43 +34,7 @@ describe('DataLinksContextMenu', () => {
expect(screen.queryAllByLabelText(selectors.components.DataLinksContextMenu.singleLink)).toHaveLength(0);
});
it('renders context menu when there are actions and one data link', () => {
render(
<DataLinksContextMenu
links={() => [
{
href: '/link1',
title: 'Link1',
target: '_blank',
origin: {},
},
]}
actions={[{ title: 'Action1', onClick: () => {} }]}
>
{() => {
return <div aria-label="fake aria label" />;
}}
</DataLinksContextMenu>
);
expect(screen.getByLabelText(fakeAriaLabel)).toBeInTheDocument();
expect(screen.queryAllByLabelText(selectors.components.DataLinksContextMenu.singleLink)).toHaveLength(0);
});
it('renders context menu when there are only actions', () => {
render(
<DataLinksContextMenu links={() => []} actions={[{ title: 'Action1', onClick: () => {} }]}>
{() => {
return <div aria-label="fake aria label" />;
}}
</DataLinksContextMenu>
);
expect(screen.getByLabelText(fakeAriaLabel)).toBeInTheDocument();
expect(screen.queryAllByLabelText(selectors.components.DataLinksContextMenu.singleLink)).toHaveLength(0);
});
it('renders link when there is a single data link and no actions', () => {
it('renders link when there is a single data link', () => {
render(
<DataLinksContextMenu
links={() => [
@@ -2,11 +2,11 @@ import { css } from '@emotion/css';
import { CSSProperties } from 'react';
import * as React from 'react';
import { ActionModel, GrafanaTheme2, LinkModel } from '@grafana/data';
import { GrafanaTheme2, LinkModel } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { useStyles2 } from '../../themes';
import { actionModelToContextMenuItems, linkModelToContextMenuItems } from '../../utils/dataLinks';
import { linkModelToContextMenuItems } from '../../utils/dataLinks';
import { WithContextMenu } from '../ContextMenu/WithContextMenu';
import { MenuGroup, MenuItemsGroup } from '../Menu/MenuGroup';
import { MenuItem } from '../Menu/MenuItem';
@@ -15,7 +15,6 @@ export interface DataLinksContextMenuProps {
children: (props: DataLinksContextMenuApi) => JSX.Element;
links: () => LinkModel[];
style?: CSSProperties;
actions?: ActionModel[];
}
export interface DataLinksContextMenuApi {
@@ -23,16 +22,12 @@ export interface DataLinksContextMenuApi {
targetClassName?: string;
}
export const DataLinksContextMenu = ({ children, links, actions, style }: DataLinksContextMenuProps) => {
export const DataLinksContextMenu = ({ children, links, style }: DataLinksContextMenuProps) => {
const styles = useStyles2(getStyles);
const itemsGroup: MenuItemsGroup[] = [
{ items: linkModelToContextMenuItems(links), label: Boolean(links().length) ? 'Data links' : '' },
];
const hasActions = Boolean(actions?.length);
if (hasActions) {
itemsGroup.push({ items: actionModelToContextMenuItems(actions!), label: 'Actions' });
}
const linksCounter = itemsGroup[0].items.length;
const renderMenuGroupItems = () => {
@@ -59,7 +54,7 @@ export const DataLinksContextMenu = ({ children, links, actions, style }: DataLi
cursor: 'context-menu',
});
if (linksCounter > 1 || hasActions) {
if (linksCounter > 1) {
return (
<WithContextMenu renderMenuItems={renderMenuGroupItems}>
{({ openMenu }) => {
@@ -1,7 +1,7 @@
import { DataSourceJsonData, DataSourcePluginOptionsEditorProps } from '@grafana/data';
import { InlineSwitch } from '../../components/Switch/Switch';
import { Trans } from '../../utils/i18n';
import { t, Trans } from '../../utils/i18n';
import { InlineField } from '../Forms/InlineField';
export interface Props<T extends DataSourceJsonData>
@@ -22,9 +22,12 @@ export function AlertingSettings<T extends AlertingConfig>({ options, onOptionsC
<div className="gf-form">
<InlineField
labelWidth={29}
label="Manage alert rules in Alerting UI"
label={t('grafana-ui.data-source-settings.alerting-settings-label', 'Manage alert rules in Alerting UI')}
disabled={options.readOnly}
tooltip="Manage alert rules for this data source. To manage other alerting resources, add an Alertmanager data source."
tooltip={t(
'grafana-ui.data-source-settings.alerting-settings-tooltip',
'Manage alert rules for this data source. To manage other alerting resources, add an Alertmanager data source.'
)}
>
<InlineSwitch
value={options.jsonData.manageAlerts !== false}
@@ -1,6 +1,7 @@
import * as React from 'react';
import { InlineField } from '../../components/Forms/InlineField';
import { t } from '../../utils/i18n';
import { FormField } from '../FormField/FormField';
import { SecretFormField } from '../SecretFormField/SecretFormField';
@@ -37,10 +38,10 @@ export const BasicAuthSettings = ({ dataSourceConfig, onChange }: HttpSettingsPr
<>
<InlineField disabled={dataSourceConfig.readOnly}>
<FormField
label="User"
label={t('grafana-ui.data-source-basic-auth-settings.user-label', 'User')}
labelWidth={10}
inputWidth={18}
placeholder="user"
placeholder={t('grafana-ui.data-source-basic-auth-settings.user-placeholder', 'user')}
value={dataSourceConfig.basicAuthUser}
onChange={(event) => onChange({ ...dataSourceConfig, basicAuthUser: event.currentTarget.value })}
/>
@@ -5,7 +5,7 @@ import { PureComponent } from 'react';
import { DataSourceSettings } from '@grafana/data';
import { useStyles2 } from '../../themes';
import { Trans } from '../../utils/i18n';
import { t, Trans } from '../../utils/i18n';
import { Button } from '../Button';
import { FormField } from '../FormField/FormField';
import { Icon } from '../Icon/Icon';
@@ -59,8 +59,9 @@ const CustomHeaderRow = ({ header, onBlur, onChange, onRemove, onReset }: Custom
return (
<div className={styles.layout}>
<FormField
label="Header"
label={t('grafana-ui.data-source-settings.custom-headers-header', 'Header')}
name="name"
// eslint-disable-next-line @grafana/no-untranslated-strings
placeholder="X-Custom-Header"
labelWidth={5}
value={header.name || ''}
@@ -68,21 +69,21 @@ const CustomHeaderRow = ({ header, onBlur, onChange, onRemove, onReset }: Custom
onBlur={onBlur}
/>
<SecretFormField
label="Value"
aria-label="Value"
label={t('grafana-ui.data-source-settings.custom-headers-header-value', 'Value')}
aria-label={t('grafana-ui.data-source-settings.custom-headers-header-value', 'Value')}
name="value"
isConfigured={header.configured}
value={header.value}
labelWidth={5}
inputWidth={header.configured ? 11 : 12}
placeholder="Header Value"
placeholder={t('grafana-ui.data-source-settings.custom-headers-header-placeholder', 'Header Value')}
onReset={() => onReset(header.id)}
onChange={(e) => onChange({ ...header, value: e.target.value })}
onBlur={onBlur}
/>
<Button
type="button"
aria-label="Remove header"
aria-label={t('grafana-ui.data-source-settings.custom-headers-header-remove', 'Remove header')}
variant="secondary"
size="xs"
onClick={(_e) => onRemove(header.id)}
@@ -5,7 +5,7 @@ import { SelectableValue } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { useTheme2 } from '../../themes';
import { Trans } from '../../utils/i18n';
import { t, Trans } from '../../utils/i18n';
import { Alert } from '../Alert/Alert';
import { FormField } from '../FormField/FormField';
import { InlineFormLabel } from '../FormLabel/FormLabel';
@@ -26,22 +26,23 @@ import { HttpSettingsProps } from './types';
const ACCESS_OPTIONS: Array<SelectableValue<string>> = [
{
label: 'Server (default)',
label: t('grafana-ui.data-source-http-settings.access-options-proxy', 'Server (default)'),
value: 'proxy',
},
{
label: 'Browser',
label: t('grafana-ui.data-source-http-settings.access-options-browser', 'Browser'),
value: 'direct',
},
];
const DEFAULT_ACCESS_OPTION = {
label: 'Server (default)',
label: t('grafana-ui.data-source-http-settings.access-options-proxy', 'Server (default)'),
value: 'proxy',
};
const HttpAccessHelp = () => {
return (
// eslint-disable-next-line @grafana/no-untranslated-strings
<Alert severity="info" title="" topSpacing={3}>
<p>
<Trans i18nKey="grafana-ui.data-source-http-settings.access-help-details">
@@ -161,7 +162,7 @@ export const DataSourceHttpSettings = (props: HttpSettingsProps) => {
const accessSelect = (
<Select
aria-label="Access"
aria-label={t('grafana-ui.data-source-http-settings.default-url-access-select', 'Access')}
className="width-20 gf-form-input"
options={ACCESS_OPTIONS}
value={ACCESS_OPTIONS.filter((o) => o.value === dataSourceConfig.access)[0] || DEFAULT_ACCESS_OPTION}
@@ -204,7 +205,7 @@ export const DataSourceHttpSettings = (props: HttpSettingsProps) => {
<div className="gf-form">
<FormField
interactive={urlDocs ? true : false}
label={urlLabel ?? 'URL'}
label={urlLabel ?? t('grafana-ui.data-source-http-settings.url-label', 'URL')}
labelWidth={13}
tooltip={urlTooltip}
inputEl={urlInput}
@@ -215,7 +216,12 @@ export const DataSourceHttpSettings = (props: HttpSettingsProps) => {
<>
<div className="gf-form-inline">
<div className="gf-form">
<FormField label="Access" labelWidth={13} inputWidth={20} inputEl={accessSelect} />
<FormField
label={t('grafana-ui.data-source-http-settings.access-label', 'Access')}
labelWidth={13}
inputWidth={20}
inputEl={accessSelect}
/>
</div>
<div className="gf-form">
<button
@@ -238,7 +244,10 @@ export const DataSourceHttpSettings = (props: HttpSettingsProps) => {
<div className="gf-form">
<InlineFormLabel
width={13}
tooltip="Grafana proxy deletes forwarded cookies by default. Specify cookies by name that should be forwarded to the data source."
tooltip={t(
'grafana-ui.data-source-http-settings.allowed-cookies-tooltip',
'Grafana proxy deletes forwarded cookies by default. Specify cookies by name that should be forwarded to the data source.'
)}
>
<Trans i18nKey="grafana-ui.data-source-http-settings.allowed-cookies">Allowed cookies</Trans>
</InlineFormLabel>
@@ -253,13 +262,13 @@ export const DataSourceHttpSettings = (props: HttpSettingsProps) => {
</div>
<div className="gf-form">
<FormField
label="Timeout"
label={t('grafana-ui.data-source-http-settings.timeout-form-label', 'Timeout')}
type="number"
labelWidth={13}
inputWidth={20}
tooltip="HTTP request timeout in seconds"
placeholder="Timeout in seconds"
aria-label="Timeout in seconds"
tooltip={t('grafana-ui.data-source-http-settings.timeout-tooltip', 'HTTP request timeout in seconds')}
placeholder={t('grafana-ui.data-source-http-settings.timeout-label', 'Timeout in seconds')}
aria-label={t('grafana-ui.data-source-http-settings.timeout-label', 'Timeout in seconds')}
value={dataSourceConfig.jsonData.timeout}
onChange={(event) => {
onSettingsChange({
@@ -280,7 +289,11 @@ export const DataSourceHttpSettings = (props: HttpSettingsProps) => {
</h3>
<div className="gf-form-group">
<div className="gf-form-inline">
<InlineField label="Basic auth" labelWidth={LABEL_WIDTH} disabled={dataSourceConfig.readOnly}>
<InlineField
label={t('grafana-ui.data-source-http-settings.basic-auth-label', 'Basic auth')}
labelWidth={LABEL_WIDTH}
disabled={dataSourceConfig.readOnly}
>
<InlineSwitch
id="http-settings-basic-auth"
value={dataSourceConfig.basicAuth}
@@ -291,8 +304,11 @@ export const DataSourceHttpSettings = (props: HttpSettingsProps) => {
</InlineField>
<InlineField
label="With Credentials"
tooltip="Whether credentials such as cookies or auth headers should be sent with cross-site requests."
label={t('grafana-ui.data-source-http-settings.with-credential-label', 'With Credentials')}
tooltip={t(
'grafana-ui.data-source-http-settings.with-credential-tooltip',
'Whether credentials such as cookies or auth headers should be sent with cross-site requests.'
)}
labelWidth={LABEL_WIDTH}
disabled={dataSourceConfig.readOnly}
>
@@ -309,8 +325,11 @@ export const DataSourceHttpSettings = (props: HttpSettingsProps) => {
{azureAuthSettings?.azureAuthSupported && (
<div className="gf-form-inline">
<InlineField
label="Azure Authentication"
tooltip="Use Azure authentication for Azure endpoint."
label={t('grafana-ui.data-source-http-settings.azure-auth-label', 'Azure Authentication')}
tooltip={t(
'grafana-ui.data-source-http-settings.azure-auth-tooltip',
'Use Azure authentication for Azure endpoint.'
)}
labelWidth={LABEL_WIDTH}
disabled={dataSourceConfig.readOnly}
>
@@ -329,7 +348,12 @@ export const DataSourceHttpSettings = (props: HttpSettingsProps) => {
{sigV4AuthToggleEnabled && (
<div className="gf-form-inline">
<InlineField label="SigV4 auth" labelWidth={LABEL_WIDTH} disabled={dataSourceConfig.readOnly}>
<InlineField
// eslint-disable-next-line @grafana/no-untranslated-strings
label="SigV4 auth"
labelWidth={LABEL_WIDTH}
disabled={dataSourceConfig.readOnly}
>
<InlineSwitch
id="http-settings-sigv4-auth"
value={dataSourceConfig.jsonData.sigV4Auth || false}
@@ -1,3 +1,4 @@
import { t } from '../../utils/i18n';
import { InlineField } from '../Forms/InlineField';
import { InlineSwitch } from '../Switch/Switch';
@@ -13,7 +14,11 @@ export const HttpProxySettings = ({
return (
<>
<div className="gf-form-inline">
<InlineField label="TLS Client Auth" labelWidth={LABEL_WIDTH} disabled={dataSourceConfig.readOnly}>
<InlineField
label={t('grafana-ui.data-source-http-proxy-settings.ts-client-auth-label', 'TLS Client Auth')}
labelWidth={LABEL_WIDTH}
disabled={dataSourceConfig.readOnly}
>
<InlineSwitch
id="http-settings-tls-client-auth"
value={dataSourceConfig.jsonData.tlsAuth || false}
@@ -21,8 +26,11 @@ export const HttpProxySettings = ({
/>
</InlineField>
<InlineField
label="With CA Cert"
tooltip="Needed for verifying self-signed TLS Certs"
label={t('grafana-ui.data-source-http-proxy-settings.with-ca-cert-label', 'With CA Cert')}
tooltip={t(
'grafana-ui.data-source-http-proxy-settings.with-ca-cert-tooltip',
'Needed for verifying self-signed TLS Certs'
)}
labelWidth={LABEL_WIDTH}
disabled={dataSourceConfig.readOnly}
>
@@ -36,7 +44,11 @@ export const HttpProxySettings = ({
</InlineField>
</div>
<div className="gf-form-inline">
<InlineField label="Skip TLS Verify" labelWidth={LABEL_WIDTH} disabled={dataSourceConfig.readOnly}>
<InlineField
label={t('grafana-ui.data-source-http-proxy-settings.skip-tls-verify-label', 'Skip TLS Verify')}
labelWidth={LABEL_WIDTH}
disabled={dataSourceConfig.readOnly}
>
<InlineSwitch
id="http-settings-skip-tls-verify"
value={dataSourceConfig.jsonData.tlsSkipVerify || false}
@@ -49,8 +61,11 @@ export const HttpProxySettings = ({
{showForwardOAuthIdentityOption && (
<div className="gf-form-inline">
<InlineField
label="Forward OAuth Identity"
tooltip="Forward the user's upstream OAuth identity to the data source (Their access token gets passed along)."
label={t('grafana-ui.data-source-http-proxy-settings.oauth-identity-label', 'Forward OAuth Identity')}
tooltip={t(
'grafana-ui.data-source-http-proxy-settings.oauth-identity-tooltip',
"Forward the user's upstream OAuth identity to the data source (Their access token gets passed along)."
)}
labelWidth={LABEL_WIDTH}
disabled={dataSourceConfig.readOnly}
>
@@ -1,7 +1,7 @@
import { DataSourceJsonData, DataSourcePluginOptionsEditorProps } from '@grafana/data';
import { InlineSwitch } from '../../components/Switch/Switch';
import { Trans } from '../../utils/i18n';
import { t, Trans } from '../../utils/i18n';
import { InlineField } from '../Forms/InlineField';
export interface Props<T extends DataSourceJsonData>
@@ -25,8 +25,11 @@ export function SecureSocksProxySettings<T extends SecureSocksProxyConfig>({
<div className="gf-form">
<InlineField
labelWidth={26}
label="Enabled"
tooltip="Connect to this datasource via the secure socks proxy."
label={t('grafana-ui.data-source-settings.secure-socks-label', 'Enabled')}
tooltip={t(
'grafana-ui.data-source-settings.secure-socks-tooltip',
'Connect to this datasource via the secure socks proxy.'
)}
>
<InlineSwitch
value={options.jsonData.enableSecureSocksProxy ?? false}
@@ -3,7 +3,7 @@ import * as React from 'react';
import { KeyValue } from '@grafana/data';
import { Trans } from '../../utils/i18n';
import { t, Trans } from '../../utils/i18n';
import { FormField } from '../FormField/FormField';
import { Icon } from '../Icon/Icon';
import { Tooltip } from '../Tooltip/Tooltip';
@@ -49,6 +49,9 @@ export const TLSAuthSettings = ({ dataSourceConfig, onChange }: HttpSettingsBase
});
};
const certificateBeginsWith = '-----BEGIN CERTIFICATE-----';
const privateKeyBeginsWith = '-----BEGIN RSA PRIVATE KEY-----';
return (
<div className="gf-form-group">
<div
@@ -64,7 +67,10 @@ export const TLSAuthSettings = ({ dataSourceConfig, onChange }: HttpSettingsBase
</h6>
<Tooltip
placement="right-end"
content="TLS/SSL Certs are encrypted and stored in the Grafana database."
content={t(
'grafana-ui.data-source-settings.tls-tooltip',
'TLS/SSL Certs are encrypted and stored in the Grafana database.'
)}
theme="info"
>
<Icon name="info-circle" size="xs" style={{ marginLeft: '10px' }} />
@@ -75,8 +81,12 @@ export const TLSAuthSettings = ({ dataSourceConfig, onChange }: HttpSettingsBase
<CertificationKey
hasCert={!!hasTLSCACert}
onChange={onCertificateChangeFactory('tlsCACert')}
placeholder="Begins with -----BEGIN CERTIFICATE-----"
label="CA Cert"
placeholder={t(
'grafana-ui.data-source-settings.tls-certification-placeholder',
'Begins with {{certificateBeginsWith}}',
{ certificateBeginsWith }
)}
label={t('grafana-ui.data-source-settings.tls-certification-label', 'CA Cert')}
onClick={onResetClickFactory('tlsCACert')}
/>
)}
@@ -85,9 +95,10 @@ export const TLSAuthSettings = ({ dataSourceConfig, onChange }: HttpSettingsBase
<>
<div className="gf-form">
<FormField
label="ServerName"
label={t('grafana-ui.data-source-settings.tls-server-name-label', 'ServerName')}
labelWidth={7}
inputWidth={30}
// eslint-disable-next-line @grafana/no-untranslated-strings
placeholder="domain.example.com"
value={hasServerName && dataSourceConfig.jsonData.serverName}
onChange={onServerNameLabelChange}
@@ -95,16 +106,24 @@ export const TLSAuthSettings = ({ dataSourceConfig, onChange }: HttpSettingsBase
</div>
<CertificationKey
hasCert={!!hasTLSClientCert}
label="Client Cert"
label={t('grafana-ui.data-source-settings.tls-client-certification-label', 'Client Cert')}
onChange={onCertificateChangeFactory('tlsClientCert')}
placeholder="Begins with -----BEGIN CERTIFICATE-----"
placeholder={t(
'grafana-ui.data-source-settings.tls-certification-placeholder',
'Begins with {{certificateBeginsWith}}',
{ certificateBeginsWith }
)}
onClick={onResetClickFactory('tlsClientCert')}
/>
<CertificationKey
hasCert={!!hasTLSClientKey}
label="Client Key"
placeholder="Begins with -----BEGIN RSA PRIVATE KEY-----"
label={t('grafana-ui.data-source-settings.tls-client-key-label', 'Client Key')}
placeholder={t(
'grafana-ui.data-source-settings.tls-client-key-placeholder',
'Begins with {{privateKeyBeginsWith}}',
{ privateKeyBeginsWith }
)}
onChange={onCertificateChangeFactory('tlsClientKey')}
onClick={onResetClickFactory('tlsClientKey')}
/>
@@ -21,7 +21,7 @@ import {
import { Components } from '@grafana/e2e-selectors';
import { useStyles2, useTheme2 } from '../../../themes';
import { Trans } from '../../../utils/i18n';
import { t, Trans } from '../../../utils/i18n';
import { Button } from '../../Button/Button';
import { InlineField } from '../../Forms/InlineField';
import { Icon } from '../../Icon/Icon';
@@ -253,7 +253,14 @@ const DateTimeInput = React.forwardRef<HTMLInputElement, InputProps>(
onChange();
}, [onChange]);
const icon = <Button aria-label="Time picker" icon="calendar-alt" variant="secondary" onClick={onOpen} />;
const icon = (
<Button
aria-label={t('grafana-ui.date-time-picker.calendar-icon-label', 'Time picker')}
icon="calendar-alt"
variant="secondary"
onClick={onOpen}
/>
);
return (
<InlineField label={label} invalid={!!(internalDate.value && internalDate.invalid)} className={styles.field}>
<Input
@@ -262,7 +269,7 @@ const DateTimeInput = React.forwardRef<HTMLInputElement, InputProps>(
value={internalDate.value}
onBlur={onBlur}
data-testid={Components.DateTimePicker.input}
placeholder="Select date/time"
placeholder={t('grafana-ui.date-time-picker.select-placeholder', 'Select date/time')}
ref={ref}
suffix={
clearable &&
@@ -343,9 +350,9 @@ const DateTimeCalendar = React.forwardRef<HTMLDivElement, DateTimeCalendarProps>
prev2Label={null}
value={reactCalendarDate}
nextLabel={<Icon name="angle-right" />}
nextAriaLabel="Next month"
nextAriaLabel={t('grafana-ui.date-time-picker.next-label', 'Next month')}
prevLabel={<Icon name="angle-left" />}
prevAriaLabel="Previous month"
prevAriaLabel={t('grafana-ui.date-time-picker.previous-label', 'Previous month')}
onChange={onChangeDate}
locale="en"
className={calendarStyles.body}
@@ -179,7 +179,11 @@ export function RelativeTimeRangePicker(props: RelativeTimeRangePickerProps) {
</Tooltip>
</TimePickerTitle>
</div>
<Field label="From" invalid={!from.validation.isValid} error={from.validation.errorMessage}>
<Field
label={t('time-picker.time-range.from-label', 'From')}
invalid={!from.validation.isValid}
error={from.validation.errorMessage}
>
<Input
onClick={(event) => event.stopPropagation()}
onBlur={() => setFrom({ ...from, validation: isRangeValid(from.value) })}
@@ -187,7 +191,11 @@ export function RelativeTimeRangePicker(props: RelativeTimeRangePickerProps) {
value={from.value}
/>
</Field>
<Field label="To" invalid={!to.validation.isValid} error={to.validation.errorMessage}>
<Field
label={t('time-picker.time-range.to-label', 'To')}
invalid={!to.validation.isValid}
error={to.validation.errorMessage}
>
<Input
onClick={(event) => event.stopPropagation()}
onBlur={() => setTo({ ...to, validation: isRangeValid(to.value) })}
@@ -195,7 +203,10 @@ export function RelativeTimeRangePicker(props: RelativeTimeRangePickerProps) {
value={to.value}
/>
</Field>
<Button aria-label="TimePicker submit button" onClick={onApply}>
<Button
aria-label={t('time-picker.time-range.submit-button-label', 'TimePicker submit button')}
onClick={onApply}
>
<Trans i18nKey="time-picker.time-range.apply">Apply time range</Trans>
</Button>
</div>
@@ -24,7 +24,7 @@ const defaultScale: ThresholdsConfig = {
};
export const BarGaugeCell = (props: TableCellProps) => {
const { field, innerWidth, tableStyles, cell, cellProps, row, actions } = props;
const { field, innerWidth, tableStyles, cell, cellProps, row } = props;
const displayValue = field.display!(cell.value);
const cellOptions = getCellOptions(field);
@@ -56,7 +56,6 @@ export const BarGaugeCell = (props: TableCellProps) => {
};
const hasLinks = Boolean(getLinks().length);
const hasActions = Boolean(actions?.length);
const alignmentFactors = getAlignmentFactor(field, displayValue, cell.row.index);
const renderComponent = (menuProps: DataLinksContextMenuApi) => {
@@ -85,8 +84,8 @@ export const BarGaugeCell = (props: TableCellProps) => {
return (
<div {...cellProps} className={tableStyles.cellContainer}>
{hasLinks || hasActions ? (
<DataLinksContextMenu links={getLinks} actions={actions} style={{ display: 'flex', width: '100%' }}>
{hasLinks ? (
<DataLinksContextMenu links={getLinks} style={{ display: 'flex', width: '100%' }}>
{(api) => renderComponent(api)}
</DataLinksContextMenu>
) : (
@@ -17,8 +17,7 @@ import { TableCellProps, CustomCellRendererProps, TableCellOptions } from './typ
import { getCellColors, getCellOptions } from './utils';
export const DefaultCell = (props: TableCellProps) => {
const { field, cell, tableStyles, row, cellProps, frame, rowStyled, rowExpanded, textWrapped, height, actions } =
props;
const { field, cell, tableStyles, row, cellProps, frame, rowStyled, rowExpanded, textWrapped, height } = props;
const inspectEnabled = Boolean(field.config.custom?.inspect);
const displayValue = field.display!(cell.value);
@@ -26,7 +25,6 @@ export const DefaultCell = (props: TableCellProps) => {
const showActions = (showFilters && cell.value !== undefined) || inspectEnabled;
const cellOptions = getCellOptions(field);
const hasLinks = Boolean(getCellLinks(field, row)?.length);
const hasActions = Boolean(actions?.length);
const clearButtonStyle = useStyles2(clearLinkButtonStyles);
let value: string | ReactElement;
@@ -81,8 +79,8 @@ export const DefaultCell = (props: TableCellProps) => {
return (
<div key={key} {...rest} className={cellStyle}>
{hasLinks || hasActions ? (
<DataLinksContextMenu links={() => getCellLinks(field, row) || []} actions={actions}>
{hasLinks ? (
<DataLinksContextMenu links={() => getCellLinks(field, row) || []}>
{(api) => {
if (api.openMenu) {
return (
@@ -9,13 +9,12 @@ import { getCellOptions } from './utils';
const DATALINKS_HEIGHT_OFFSET = 10;
export const ImageCell = (props: TableCellProps) => {
const { field, cell, tableStyles, row, cellProps, actions } = props;
const { field, cell, tableStyles, row, cellProps } = props;
const cellOptions = getCellOptions(field);
const { title, alt } =
cellOptions.type === TableCellDisplayMode.Image ? cellOptions : { title: undefined, alt: undefined };
const displayValue = field.display!(cell.value);
const hasLinks = Boolean(getCellLinks(field, row)?.length);
const hasActions = Boolean(actions?.length);
// The image element
const img = (
@@ -32,11 +31,10 @@ export const ImageCell = (props: TableCellProps) => {
<div {...cellProps} className={tableStyles.cellContainer}>
{/* If there are data links/actions, we render them with image */}
{/* Otherwise we simply render the image */}
{hasLinks || hasActions ? (
{hasLinks ? (
<DataLinksContextMenu
style={{ height: tableStyles.cellHeight - DATALINKS_HEIGHT_OFFSET, width: 'auto' }}
links={() => getCellLinks(field, row) || []}
actions={actions}
>
{(api) => {
if (api.openMenu) {
@@ -11,7 +11,7 @@ import { TableCellInspectorMode } from './TableCellInspector';
import { TableCellProps } from './types';
export function JSONViewCell(props: TableCellProps): JSX.Element {
const { cell, tableStyles, cellProps, field, row, actions } = props;
const { cell, tableStyles, cellProps, field, row } = props;
const inspectEnabled = Boolean(field.config.custom?.inspect);
const txt = css({
cursor: 'pointer',
@@ -30,14 +30,13 @@ export function JSONViewCell(props: TableCellProps): JSX.Element {
}
const hasLinks = Boolean(getCellLinks(field, row)?.length);
const hasActions = Boolean(actions?.length);
const clearButtonStyle = useStyles2(clearLinkButtonStyles);
return (
<div {...cellProps} className={inspectEnabled ? tableStyles.cellContainerNoOverflow : tableStyles.cellContainer}>
<div className={cx(tableStyles.cellText, txt)}>
{hasLinks || hasActions ? (
<DataLinksContextMenu links={() => getCellLinks(field, row) || []} actions={actions}>
{hasLinks ? (
<DataLinksContextMenu links={() => getCellLinks(field, row) || []}>
{(api) => {
if (api.openMenu) {
return (
+1 -12
View File
@@ -1,4 +1,4 @@
import { ActionModel, LinkModel } from '@grafana/data';
import { LinkModel } from '@grafana/data';
import { MenuItemProps } from '../components/Menu/MenuItem';
@@ -18,14 +18,3 @@ export const linkModelToContextMenuItems: (links: () => LinkModel[]) => MenuItem
};
});
};
export const actionModelToContextMenuItems: (actions: ActionModel[]) => MenuItemProps[] = (actions) => {
return actions.map((action) => {
return {
label: action.title,
ariaLabel: action.title,
icon: 'record-audio',
onClick: action.onClick,
};
});
};
+4 -4
View File
@@ -6,7 +6,7 @@ toolchain go1.23.6
require (
github.com/emicklei/go-restful/v3 v3.11.0
github.com/grafana/grafana-plugin-sdk-go v0.266.0
github.com/grafana/grafana-plugin-sdk-go v0.267.0
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435
github.com/grafana/grafana/pkg/semconv v0.0.0-20240808213237-f4d2e064f435
github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38
@@ -39,7 +39,7 @@ require (
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/elazarl/goproxy v1.7.0 // indirect
github.com/elazarl/goproxy v1.7.1 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/fatih/color v1.17.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
@@ -59,7 +59,7 @@ require (
github.com/google/cel-go v0.22.1 // indirect
github.com/google/flatbuffers v24.3.25+incompatible // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
@@ -150,7 +150,7 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.70.0 // indirect
google.golang.org/protobuf v1.36.4 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
+8 -7
View File
@@ -49,8 +49,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/elazarl/goproxy v1.7.0 h1:EXv2nV4EjM60ZtsEVLYJG4oBXhDGutMKperpHsZ/v+0=
github.com/elazarl/goproxy v1.7.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ=
github.com/elazarl/goproxy v1.7.1 h1:1P7LPSxbqtNxusFnXclj6O56pjfq1xOQZ6a0mwwKUlY=
github.com/elazarl/goproxy v1.7.1/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -118,8 +118,9 @@ github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvR
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -134,8 +135,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grafana/grafana-plugin-sdk-go v0.266.0 h1:YP+iEpXH3HRX9Xo4NHjsrJhN2W7uVTtkLNzMHYbmiLI=
github.com/grafana/grafana-plugin-sdk-go v0.266.0/go.mod h1:bxkXrBQ4QSmOncsWdIOcpgP+M6wajQNMAPXlbWrqAWY=
github.com/grafana/grafana-plugin-sdk-go v0.267.0 h1:4AcuLEE0UeFG0Eo3P8r1FDS89hgZZ73K550DRz1fgjQ=
github.com/grafana/grafana-plugin-sdk-go v0.267.0/go.mod h1:OuwS4c/JYgn0rr/w5zhJBpLo4gKm/vw15RsfpYAvK9Q=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435 h1:lmw60EW7JWlAEvgggktOyVkH4hF1m/+LSF/Ap0NCyi8=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240808213237-f4d2e064f435/go.mod h1:ORVFiW/KNRY52lNjkGwnFWCxNVfE97bJG2jr2fetq0I=
github.com/grafana/grafana/pkg/semconv v0.0.0-20240808213237-f4d2e064f435 h1:SNEeqY22DrGr5E9kGF1mKSqlOom14W9+b1u4XEGJowA=
@@ -495,8 +496,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
-7
View File
@@ -66,18 +66,11 @@ func (hs *HTTPServer) declareFixedRoles() error {
{
Action: ac.ActionDatasourcesExplore,
},
{
Action: ac.ActionDatasourcesDrilldown,
},
},
},
Grants: []string{string(org.RoleEditor)},
}
if hs.Cfg.ViewersCanEdit {
datasourcesExplorerRole.Grants = append(datasourcesExplorerRole.Grants, string(org.RoleViewer))
}
datasourcesReaderRole := ac.RoleRegistration{
Role: ac.RoleDTO{
Name: "fixed:datasources:reader",
+2 -2
View File
@@ -66,7 +66,7 @@ func (hs *HTTPServer) registerRoutes() {
reqSignedInNoAnonymous := middleware.ReqSignedInNoAnonymous
reqGrafanaAdmin := middleware.ReqGrafanaAdmin
reqOrgAdmin := middleware.ReqOrgAdmin
reqRoleForAppRoute := middleware.RoleAppPluginAuth(hs.AccessControl, hs.pluginStore, hs.Features, hs.log)
reqRoleForAppRoute := middleware.RoleAppPluginAuth(hs.AccessControl, hs.pluginStore, hs.log)
reqSnapshotPublicModeOrCreate := middleware.SnapshotPublicModeOrCreate(hs.Cfg, hs.AccessControl)
reqSnapshotPublicModeOrDelete := middleware.SnapshotPublicModeOrDelete(hs.Cfg, hs.AccessControl)
redirectFromLegacyPanelEditURL := middleware.RedirectFromLegacyPanelEditURL(hs.Cfg)
@@ -183,7 +183,7 @@ func (hs *HTTPServer) registerRoutes() {
}
r.Get("/explore", authorize(ac.EvalPermission(ac.ActionDatasourcesExplore)), hs.Index)
r.Get("/drilldown", authorize(ac.EvalPermission(ac.ActionDatasourcesDrilldown)), hs.Index)
r.Get("/drilldown", authorize(ac.EvalPermission(ac.ActionDatasourcesExplore)), hs.Index)
r.Get("/playlists/", reqSignedIn, hs.Index)
r.Get("/playlists/*", reqSignedIn, hs.Index)
+3 -12
View File
@@ -306,16 +306,8 @@ func (proxy *DataSourceProxy) validateRequest() error {
continue
}
if proxy.features.IsEnabled(proxy.ctx.Req.Context(), featuremgmt.FlagDatasourceProxyDisableRBAC) {
// TODO(aarongodin): following logic can be removed with FlagDatasourceProxyDisableRBAC as it is covered by
// proxy.hasAccessToRoute(..)
if route.ReqRole.IsValid() && !proxy.ctx.HasUserRole(route.ReqRole) {
return errors.New("plugin proxy route access denied")
}
} else {
if !proxy.hasAccessToRoute(route) {
return errors.New("plugin proxy route access denied")
}
if !proxy.hasAccessToRoute(route) {
return errors.New("plugin proxy route access denied")
}
proxy.matchedRoute = route
@@ -340,8 +332,7 @@ func (proxy *DataSourceProxy) validateRequest() error {
func (proxy *DataSourceProxy) hasAccessToRoute(route *plugins.Route) bool {
ctxLogger := logger.FromContext(proxy.ctx.Req.Context())
useRBAC := proxy.features.IsEnabled(proxy.ctx.Req.Context(), featuremgmt.FlagAccessControlOnCall) && route.ReqAction != ""
if useRBAC {
if route.ReqAction != "" {
routeEval := pluginac.GetDataSourceRouteEvaluator(proxy.ds.UID, route.ReqAction)
hasAccess := routeEval.Evaluate(proxy.ctx.GetPermissions())
if !hasAccess {
+1 -1
View File
@@ -1094,7 +1094,7 @@ func setupDSProxyTest(t *testing.T, ctx *contextmodel.ReqContext, ds *datasource
cfg := setting.NewCfg()
secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore())
secretsStore := secretskvs.NewSQLSecretsKVStore(dbtest.NewFakeDB(), secretsService, log.NewNopLogger())
features := featuremgmt.WithFeatures(featuremgmt.FlagAccessControlOnCall)
features := featuremgmt.WithFeatures()
dsService, err := datasourceservice.ProvideService(nil, secretsService, secretsStore, cfg, features, acimpl.ProvideAccessControl(features),
&actest.FakePermissionsService{}, quotatest.New(false, nil), &pluginstore.FakePluginStore{}, &pluginfakes.FakePluginClient{},
plugincontext.ProvideBaseService(cfg, pluginconfig.NewFakePluginRequestConfigProvider()))
+1 -2
View File
@@ -129,8 +129,7 @@ func (proxy *PluginProxy) HandleRequest() {
}
func (proxy *PluginProxy) hasAccessToRoute(route *plugins.Route) bool {
useRBAC := proxy.features.IsEnabled(proxy.ctx.Req.Context(), featuremgmt.FlagAccessControlOnCall) && route.ReqAction != ""
if useRBAC {
if route.ReqAction != "" {
routeEval := pluginac.GetPluginRouteEvaluator(proxy.ps.PluginID, route.ReqAction)
hasAccess := ac.HasAccess(proxy.accessControl, proxy.ctx)(routeEval)
if !hasAccess {
+1 -1
View File
@@ -557,7 +557,7 @@ func TestPluginProxyRoutesAccessControl(t *testing.T) {
SecureJSONData: map[string][]byte{},
}
cfg := &setting.Cfg{}
proxy, err := NewPluginProxy(ps, testRoutes, ctx, tc.proxyPath, cfg, secretsService, tracing.InitializeTracerForTest(), &http.Transport{}, acimpl.ProvideAccessControl(featuremgmt.WithFeatures()), featuremgmt.WithFeatures(featuremgmt.FlagAccessControlOnCall))
proxy, err := NewPluginProxy(ps, testRoutes, ctx, tc.proxyPath, cfg, secretsService, tracing.InitializeTracerForTest(), &http.Transport{}, acimpl.ProvideAccessControl(featuremgmt.WithFeatures()), featuremgmt.WithFeatures())
require.NoError(t, err)
proxy.HandleRequest()
+4 -3
View File
@@ -3,8 +3,8 @@ module github.com/grafana/grafana/pkg/apimachinery
go 1.23.1
require (
github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7 // @grafana/identity-access-team
github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31 // @grafana/identity-access-team
github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 // @grafana/identity-access-team
github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 // @grafana/identity-access-team
github.com/stretchr/testify v1.10.0
k8s.io/apimachinery v0.32.1
k8s.io/apiserver v0.32.1
@@ -23,6 +23,7 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
@@ -43,7 +44,7 @@ require (
golang.org/x/text v0.22.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.70.0 // indirect
google.golang.org/protobuf v1.36.4 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
+8 -8
View File
@@ -25,17 +25,17 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7 h1:NTMmow+74I3Jb033xhbRgWQS7A//5TDhiM4tl7bsVP4=
github.com/grafana/authlib v0.0.0-20250219100139-6a3b1bbb50e7/go.mod h1:T3X4z0ejGfJOiOmZLFeKCRT/yxWJq/RtclAc/PHj/w4=
github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31 h1:EokLC5grHwLPs4tXW8T6E8187H1e5G9AP0QQ5B60HbA=
github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 h1:FTuDRy/Shw8yOdG+v1DnkeuaCAl8fvwgcfaG9Wccuhg=
github.com/grafana/authlib v0.0.0-20250225105729-99e678595501/go.mod h1:XVpdLhaeYqz414FmGnW00/0vTe1x8c0GRH3KaeRtyg0=
github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 h1:DnRUYiAotHXnrfYJCvhH1NkiyWVcPm5Pd+P7Ugqt/d8=
github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -151,8 +151,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+3 -3
View File
@@ -5,8 +5,8 @@ go 1.23.4
toolchain go1.23.6
require (
github.com/google/go-cmp v0.6.0
github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31
github.com/google/go-cmp v0.7.0
github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82
github.com/grafana/grafana-app-sdk/logging v0.30.0
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240701135906-559738ce6ae1
github.com/prometheus/client_golang v1.20.5
@@ -93,7 +93,7 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.70.0 // indirect
google.golang.org/protobuf v1.36.4 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+6 -6
View File
@@ -68,8 +68,8 @@ github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvR
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -79,8 +79,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.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31 h1:EokLC5grHwLPs4tXW8T6E8187H1e5G9AP0QQ5B60HbA=
github.com/grafana/authlib/types v0.0.0-20250219092154-21ce22b49f31/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 h1:DnRUYiAotHXnrfYJCvhH1NkiyWVcPm5Pd+P7Ugqt/d8=
github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
github.com/grafana/grafana-app-sdk/logging v0.30.0 h1:K/P/bm7Cp7Di4tqIJ3EQz2+842JozQGRaz62r95ApME=
github.com/grafana/grafana-app-sdk/logging v0.30.0/go.mod h1:xy6ZyVXl50Z3DBDLybvBPphbykPhuVNed/VNmen9DQM=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240701135906-559738ce6ae1 h1:ItDcDxUjVLPKja+hogpqgW/kj8LxUL2qscelXIsN1Bs=
@@ -312,8 +312,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+18 -23
View File
@@ -26,8 +26,18 @@ var (
_ rest.SingularNameProvider = (DualWriter)(nil)
)
type dualWriteContextKey struct{}
func IsDualWriteUpdate(ctx context.Context) bool {
return ctx.Value(dualWriteContextKey{}) == true
}
func WithDualWriteUpdate(ctx context.Context) context.Context {
return context.WithValue(ctx, dualWriteContextKey{}, true)
}
// Function that will create a dual writer
type DualWriteBuilder func(gr schema.GroupResource, legacy LegacyStorage, storage Storage) (Storage, error)
type DualWriteBuilder func(gr schema.GroupResource, legacy Storage, unified Storage) (Storage, error)
// Storage is a storage implementation that satisfies the same interfaces as genericregistry.Store.
type Storage interface {
@@ -36,26 +46,12 @@ type Storage interface {
rest.TableConvertor
rest.SingularNameProvider
rest.Getter
// TODO: when watch is implemented, we can replace all the below with rest.StandardStorage
rest.Lister
rest.CreaterUpdater
rest.GracefulDeleter
rest.CollectionDeleter
}
// LegacyStorage is a storage implementation that writes to the Grafana SQL database.
type LegacyStorage interface {
rest.Storage
rest.Scoper
rest.SingularNameProvider
rest.CreaterUpdater
rest.Lister
rest.GracefulDeleter
rest.CollectionDeleter
rest.TableConvertor
rest.Getter
}
// DualWriter is a storage implementation that writes first to LegacyStorage and then to Storage.
// If writing to LegacyStorage fails, the write to Storage is skipped and the error is returned.
// Storage is used for all read operations. This is useful as a migration step from SQL based
@@ -79,7 +75,6 @@ type LegacyStorage interface {
type DualWriter interface {
Storage
LegacyStorage
Mode() DualWriterMode
}
@@ -110,8 +105,8 @@ const (
// NewDualWriter returns a new DualWriter.
func NewDualWriter(
mode DualWriterMode,
legacy LegacyStorage,
storage Storage,
legacy Storage,
unified Storage,
reg prometheus.Registerer,
resource string,
) Storage {
@@ -122,17 +117,17 @@ func NewDualWriter(
return legacy
case Mode1:
// read and write only from legacy storage
return newDualWriterMode1(legacy, storage, metrics, resource)
return newDualWriterMode1(legacy, unified, metrics, resource)
case Mode2:
// write to both, read from storage but use legacy as backup
return newDualWriterMode2(legacy, storage, metrics, resource)
return newDualWriterMode2(legacy, unified, metrics, resource)
case Mode3:
// write to both, read from storage only
return newDualWriterMode3(legacy, storage, metrics, resource)
return newDualWriterMode3(legacy, unified, metrics, resource)
case Mode4, Mode5:
return storage
return unified
default:
return newDualWriterMode1(legacy, storage, metrics, resource)
return newDualWriterMode1(legacy, unified, metrics, resource)
}
}
+2 -2
View File
@@ -15,7 +15,7 @@ import (
)
type DualWriterMode1 struct {
Legacy LegacyStorage
Legacy Storage
Storage Storage
*dualWriterMetrics
resource string
@@ -26,7 +26,7 @@ const mode1Str = "1"
// NewDualWriterMode1 returns a new DualWriter in mode 1.
// Mode 1 represents writing to and reading from LegacyStorage.
func newDualWriterMode1(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics, resource string) *DualWriterMode1 {
func newDualWriterMode1(legacy Storage, storage Storage, dwm *dualWriterMetrics, resource string) *DualWriterMode1 {
return &DualWriterMode1{
Legacy: legacy,
Storage: storage,
+24 -24
View File
@@ -60,10 +60,10 @@ func TestMode1_Create(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -122,10 +122,10 @@ func TestMode1_CreateOnUnifiedStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -190,10 +190,10 @@ func TestMode1_Get(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -251,10 +251,10 @@ func TestMode1_GetFromUnifiedStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -308,10 +308,10 @@ func TestMode1_List(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -365,10 +365,10 @@ func TestMode1_ListFromUnifiedStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -434,10 +434,10 @@ func TestMode1_Delete(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -494,10 +494,10 @@ func TestMode1_DeleteFromUnifiedStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -565,10 +565,10 @@ func TestMode1_DeleteCollection(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -626,10 +626,10 @@ func TestMode1_DeleteCollectionFromUnifiedStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -695,10 +695,10 @@ func TestMode1_Update(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -761,10 +761,10 @@ func TestMode1_UpdateOnUnifiedStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
+2 -8
View File
@@ -16,15 +16,9 @@ import (
"github.com/grafana/grafana/pkg/apimachinery/utils"
)
type dualWriteContextKey struct{}
func IsDualWriteUpdate(ctx context.Context) bool {
return ctx.Value(dualWriteContextKey{}) == true
}
type DualWriterMode2 struct {
Storage Storage
Legacy LegacyStorage
Legacy Storage
*dualWriterMetrics
resource string
Log klog.Logger
@@ -35,7 +29,7 @@ const mode2Str = "2"
// newDualWriterMode2 returns a new DualWriter in mode 2.
// Mode 2 represents writing to LegacyStorage first, then to Storage.
// When reading, values from LegacyStorage will be returned.
func newDualWriterMode2(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics, resource string) *DualWriterMode2 {
func newDualWriterMode2(legacy Storage, storage Storage, dwm *dualWriterMetrics, resource string) *DualWriterMode2 {
return &DualWriterMode2{
Legacy: legacy,
Storage: storage,
+12 -12
View File
@@ -54,10 +54,10 @@ func TestMode2_Create(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -138,10 +138,10 @@ func TestMode2_Get(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -212,10 +212,10 @@ func TestMode2_List(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -313,10 +313,10 @@ func TestMode2_Delete(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -382,10 +382,10 @@ func TestMode2_DeleteCollection(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -451,10 +451,10 @@ func TestMode2_Update(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
+2 -2
View File
@@ -17,7 +17,7 @@ import (
)
type DualWriterMode3 struct {
Legacy LegacyStorage
Legacy Storage
Storage Storage
watchImp rest.Watcher // watch is only available in mode 3 and 4
*dualWriterMetrics
@@ -27,7 +27,7 @@ type DualWriterMode3 struct {
// newDualWriterMode3 returns a new DualWriter in mode 3.
// Mode 3 represents writing to LegacyStorage and Storage and reading from Storage.
func newDualWriterMode3(legacy LegacyStorage, storage Storage, dwm *dualWriterMetrics, resource string) *DualWriterMode3 {
func newDualWriterMode3(legacy Storage, storage Storage, dwm *dualWriterMetrics, resource string) *DualWriterMode3 {
return &DualWriterMode3{
Legacy: legacy,
Storage: storage,
+14 -14
View File
@@ -61,10 +61,10 @@ func TestMode3_Create(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -128,10 +128,10 @@ func TestMode3_Get(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -187,10 +187,10 @@ func TestMode1_GetFromLegacyStorage(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -234,10 +234,10 @@ func TestMode3_List(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupStorageFn != nil {
@@ -311,10 +311,10 @@ func TestMode3_Delete(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -380,10 +380,10 @@ func TestMode3_DeleteCollection(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
@@ -449,10 +449,10 @@ func TestMode3_Update(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
ls := legacyStoreMock{&mock.Mock{}, l}
ls := storageMock{&mock.Mock{}, l}
us := storageMock{&mock.Mock{}, s}
if tt.setupLegacyFn != nil {
+1 -1
View File
@@ -33,7 +33,7 @@ type SyncerConfig struct {
RequestInfo *request.RequestInfo
Mode DualWriterMode
LegacyStorage LegacyStorage
LegacyStorage Storage
Storage Storage
ServerLockService ServerLockService
+4 -4
View File
@@ -181,12 +181,12 @@ func TestLegacyToUnifiedStorage_DataSyncer(t *testing.T) {
// mode 1
for _, tt := range tests {
t.Run("Mode-1-"+tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
lm := &mock.Mock{}
um := &mock.Mock{}
ls := legacyStoreMock{lm, l}
ls := storageMock{lm, l}
us := storageMock{um, s}
if tt.setupLegacyFn != nil {
@@ -221,12 +221,12 @@ func TestLegacyToUnifiedStorage_DataSyncer(t *testing.T) {
// mode 2
for _, tt := range tests {
t.Run("Mode-2-"+tt.name, func(t *testing.T) {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
lm := &mock.Mock{}
um := &mock.Mock{}
ls := legacyStoreMock{lm, l}
ls := storageMock{lm, l}
us := storageMock{um, s}
if tt.setupLegacyFn != nil {
+2 -2
View File
@@ -64,7 +64,7 @@ func TestSetDualWritingMode(t *testing.T) {
}
for _, tt := range tests {
l := (LegacyStorage)(nil)
l := (Storage)(nil)
s := (Storage)(nil)
sm := &mock.Mock{}
@@ -75,7 +75,7 @@ func TestSetDualWritingMode(t *testing.T) {
lm := &mock.Mock{}
lm.On("List", mock.Anything, mock.Anything).Return(exampleList, nil)
ls := legacyStoreMock{lm, l}
ls := storageMock{lm, l}
serverLockSvc := &fakeServerLock{
err: tt.serverLockError,
-91
View File
@@ -11,102 +11,11 @@ import (
"k8s.io/apiserver/pkg/registry/rest"
)
type legacyStoreMock struct {
*mock.Mock
LegacyStorage
}
type storageMock struct {
*mock.Mock
Storage
}
func (m legacyStoreMock) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
select {
case <-ctx.Done():
return nil, errors.New("context canceled")
default:
}
args := m.Called(ctx, name, options)
if err := args.Get(1); err != nil {
return nil, err.(error)
}
return args.Get(0).(runtime.Object), args.Error(1)
}
func (m legacyStoreMock) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
select {
case <-ctx.Done():
return nil, errors.New("context canceled")
default:
}
args := m.Called(ctx, obj, createValidation, options)
if err := args.Get(1); err != nil {
return nil, err.(error)
}
return args.Get(0).(runtime.Object), args.Error(1)
}
func (m legacyStoreMock) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
select {
case <-ctx.Done():
return nil, errors.New("context canceled")
default:
}
args := m.Called(ctx, options)
if err := args.Get(1); err != nil {
return nil, err.(error)
}
return args.Get(0).(runtime.Object), args.Error(1)
}
func (m legacyStoreMock) NewList() runtime.Object {
return nil
}
func (m legacyStoreMock) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
select {
case <-ctx.Done():
return nil, false, errors.New("context canceled")
default:
}
args := m.Called(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options)
if err := args.Get(2); err != nil {
return nil, false, err.(error)
}
return args.Get(0).(runtime.Object), args.Bool(1), args.Error(2)
}
func (m legacyStoreMock) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
select {
case <-ctx.Done():
return nil, false, errors.New("context canceled")
default:
}
args := m.Called(ctx, name, deleteValidation, options)
if err := args.Get(2); err != nil {
return nil, false, err.(error)
}
return args.Get(0).(runtime.Object), args.Bool(1), args.Error(2)
}
func (m legacyStoreMock) DeleteCollection(ctx context.Context, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) {
select {
case <-ctx.Done():
return nil, errors.New("context canceled")
default:
}
args := m.Called(ctx, deleteValidation, options, listOptions)
if err := args.Get(1); err != nil {
return nil, err.(error)
}
return args.Get(0).(runtime.Object), args.Error(1)
}
// Unified Store
func (m storageMock) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
select {
+2 -2
View File
@@ -14,7 +14,7 @@ require (
github.com/docker/docker v27.4.1+incompatible // @grafana/grafana-developer-enablement-squad
github.com/drone/drone-cli v1.8.0 // @grafana/grafana-developer-enablement-squad
github.com/gogo/protobuf v1.3.2 // indirect; @grafana/alerting-backend
github.com/google/go-cmp v0.6.0 // @grafana/grafana-backend-group
github.com/google/go-cmp v0.7.0 // @grafana/grafana-backend-group
github.com/google/go-github/v69 v69.2.0 // @grafana/grafana-developer-enablement-squad
github.com/google/uuid v1.6.0 // indirect; @grafana/grafana-backend-group
github.com/googleapis/gax-go/v2 v2.14.1 // indirect; @grafana/grafana-backend-group
@@ -35,7 +35,7 @@ require (
golang.org/x/time v0.9.0 // indirect; @grafana/grafana-backend-group
google.golang.org/api v0.216.0 // @grafana/grafana-backend-group
google.golang.org/grpc v1.70.0 // indirect; @grafana/plugins-platform-backend
google.golang.org/protobuf v1.36.4 // indirect; @grafana/plugins-platform-backend
google.golang.org/protobuf v1.36.5 // indirect; @grafana/plugins-platform-backend
gopkg.in/yaml.v3 v3.0.1 // @grafana/alerting-backend
)
+4 -4
View File
@@ -126,8 +126,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-github/v69 v69.2.0 h1:wR+Wi/fN2zdUx9YxSmYE0ktiX9IAR/BeePzeaUUbEHE=
github.com/google/go-github/v69 v69.2.0/go.mod h1:xne4jymxLR6Uj9b7J7PyTpkMYstEMMwGZa0Aehh1azM=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
@@ -362,8 +362,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+1 -1
View File
@@ -3,7 +3,7 @@ module github.com/grafana/grafana/pkg/build/wire
go 1.23.1
require (
github.com/google/go-cmp v0.6.0
github.com/google/go-cmp v0.7.0
github.com/google/subcommands v1.2.0
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
golang.org/x/tools v0.29.0
+2 -2
View File
@@ -1,5 +1,5 @@
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+1 -1
View File
@@ -21,7 +21,7 @@ require (
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/golang/glog v1.2.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
+2 -2
View File
@@ -25,8 +25,8 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc=
github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/codejen v0.0.4-0.20230321061741-77f656893a3d h1:hrXbGJ5jgp6yNITzs5o+zXq0V5yT3siNJ+uM8LGwWKk=
+40
View File
@@ -0,0 +1,40 @@
//go:build enterprise
// +build enterprise
package extensions
import (
_ "cloud.google.com/go/kms/apiv1"
_ "cloud.google.com/go/kms/apiv1/kmspb"
_ "cloud.google.com/go/spanner"
_ "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
_ "github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys"
_ "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault"
_ "github.com/Azure/go-autorest/autorest"
_ "github.com/Azure/go-autorest/autorest/adal"
_ "github.com/beevik/etree"
_ "github.com/blugelabs/bluge"
_ "github.com/blugelabs/bluge_segment_api"
_ "github.com/crewjam/saml"
_ "github.com/go-jose/go-jose/v3"
_ "github.com/gobwas/glob"
_ "github.com/googleapis/gax-go/v2"
_ "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus"
_ "github.com/grpc-ecosystem/go-grpc-middleware/v2"
_ "github.com/hashicorp/go-multierror"
_ "github.com/hashicorp/golang-lru/v2"
_ "github.com/m3db/prometheus_remote_client_golang/promremote"
_ "github.com/phpdave11/gofpdi"
_ "github.com/robfig/cron/v3"
_ "github.com/russellhaering/goxmldsig"
_ "github.com/spf13/cobra" // used by the standalone apiserver cli
_ "github.com/stretchr/testify/require"
_ "golang.org/x/time/rate"
_ "xorm.io/builder"
_ "github.com/grafana/dskit/backoff"
_ "github.com/grafana/dskit/flagext"
_ "github.com/grafana/e2e"
_ "github.com/grafana/gofpdf"
_ "github.com/grafana/gomemcache/memcache"
)
+1 -34
View File
@@ -1,38 +1,5 @@
package extensions
import (
_ "cloud.google.com/go/kms/apiv1"
_ "cloud.google.com/go/kms/apiv1/kmspb"
_ "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
_ "github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys"
_ "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault"
_ "github.com/Azure/go-autorest/autorest"
_ "github.com/Azure/go-autorest/autorest/adal"
_ "github.com/beevik/etree"
_ "github.com/blugelabs/bluge"
_ "github.com/blugelabs/bluge_segment_api"
_ "github.com/crewjam/saml"
_ "github.com/go-jose/go-jose/v3"
_ "github.com/gobwas/glob"
_ "github.com/googleapis/gax-go/v2"
_ "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus"
_ "github.com/grpc-ecosystem/go-grpc-middleware/v2"
_ "github.com/hashicorp/go-multierror"
_ "github.com/hashicorp/golang-lru/v2"
_ "github.com/m3db/prometheus_remote_client_golang/promremote"
_ "github.com/phpdave11/gofpdi"
_ "github.com/robfig/cron/v3"
_ "github.com/russellhaering/goxmldsig"
_ "github.com/spf13/cobra" // used by the standalone apiserver cli
_ "github.com/stretchr/testify/require"
_ "golang.org/x/time/rate"
_ "xorm.io/builder"
_ "github.com/grafana/dskit/backoff"
_ "github.com/grafana/dskit/flagext"
_ "github.com/grafana/e2e"
_ "github.com/grafana/gofpdf"
_ "github.com/grafana/gomemcache/memcache"
)
// Imports used by Grafana enterprise are in enterprise_imports.go (behind a build tag).
var IsEnterprise bool = false
+3 -7
View File
@@ -16,7 +16,6 @@ import (
"github.com/grafana/grafana/pkg/services/authn"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
@@ -138,9 +137,7 @@ func CanAdminPlugins(cfg *setting.Cfg, accessControl ac.AccessControl) func(c *c
}
}
func RoleAppPluginAuth(accessControl ac.AccessControl, ps pluginstore.Store, features featuremgmt.FeatureToggles,
logger log.Logger,
) func(c *contextmodel.ReqContext) {
func RoleAppPluginAuth(accessControl ac.AccessControl, ps pluginstore.Store, logger log.Logger) func(c *contextmodel.ReqContext) {
return func(c *contextmodel.ReqContext) {
pluginID := web.Params(c.Req)[":id"]
p, exists := ps.Plugin(c.Req.Context(), pluginID)
@@ -164,12 +161,11 @@ func RoleAppPluginAuth(accessControl ac.AccessControl, ps pluginstore.Store, fea
}
if normalizeIncludePath(u.Path) == path {
useRBAC := features.IsEnabledGlobally(featuremgmt.FlagAccessControlOnCall) && i.RequiresRBACAction()
if useRBAC && !hasAccess(pluginaccesscontrol.GetPluginRouteEvaluator(pluginID, i.Action)) {
if i.RequiresRBACAction() && !hasAccess(pluginaccesscontrol.GetPluginRouteEvaluator(pluginID, i.Action)) {
logger.Debug("Plugin include is covered by RBAC, user doesn't have access", "plugin", pluginID, "include", i.Name)
permitted = false
break
} else if !useRBAC && !c.HasUserRole(i.Role) {
} else if !i.RequiresRBACAction() && !c.HasUserRole(i.Role) {
permitted = false
break
}
+4 -8
View File
@@ -204,11 +204,10 @@ func TestRoleAppPluginAuth(t *testing.T) {
0: tc.role,
},
})
features := featuremgmt.WithFeatures()
logger := &logtest.Fake{}
ac := &actest.FakeAccessControl{}
sc.m.Get("/a/:id/*", RoleAppPluginAuth(ac, ps, features, logger), func(c *contextmodel.ReqContext) {
sc.m.Get("/a/:id/*", RoleAppPluginAuth(ac, ps, logger), func(c *contextmodel.ReqContext) {
c.JSON(http.StatusOK, map[string]interface{}{})
})
sc.fakeReq("GET", path).exec()
@@ -227,10 +226,9 @@ func TestRoleAppPluginAuth(t *testing.T) {
0: org.RoleViewer,
},
})
features := featuremgmt.WithFeatures()
logger := &logtest.Fake{}
ac := &actest.FakeAccessControl{}
sc.m.Get("/a/:id/*", RoleAppPluginAuth(ac, &pluginstore.FakePluginStore{}, features, logger), func(c *contextmodel.ReqContext) {
sc.m.Get("/a/:id/*", RoleAppPluginAuth(ac, &pluginstore.FakePluginStore{}, logger), func(c *contextmodel.ReqContext) {
c.JSON(http.StatusOK, map[string]interface{}{})
})
sc.fakeReq("GET", "/a/test-app/test").exec()
@@ -245,7 +243,6 @@ func TestRoleAppPluginAuth(t *testing.T) {
0: org.RoleViewer,
},
})
features := featuremgmt.WithFeatures()
logger := &logtest.Fake{}
ac := &actest.FakeAccessControl{}
sc.m.Get("/a/:id/*", RoleAppPluginAuth(ac, pluginstore.NewFakePluginStore(pluginstore.Plugin{
@@ -259,7 +256,7 @@ func TestRoleAppPluginAuth(t *testing.T) {
},
},
},
}), features, logger), func(c *contextmodel.ReqContext) {
}), logger), func(c *contextmodel.ReqContext) {
c.JSON(http.StatusOK, map[string]interface{}{})
})
sc.fakeReq("GET", "/a/test-app/notExistingPath").exec()
@@ -307,7 +304,6 @@ func TestRoleAppPluginAuth(t *testing.T) {
},
})
logger := &logtest.Fake{}
features := featuremgmt.WithFeatures(featuremgmt.FlagAccessControlOnCall)
ac := &actest.FakeAccessControl{
ExpectedEvaluate: tc.evalResult,
ExpectedErr: tc.evalErr,
@@ -327,7 +323,7 @@ func TestRoleAppPluginAuth(t *testing.T) {
},
})
sc.m.Get("/a/:id/*", RoleAppPluginAuth(ac, ps, features, logger), func(c *contextmodel.ReqContext) {
sc.m.Get("/a/:id/*", RoleAppPluginAuth(ac, ps, logger), func(c *contextmodel.ReqContext) {
c.JSON(http.StatusOK, map[string]interface{}{})
})
sc.fakeReq("GET", path).exec()

Some files were not shown because too many files have changed in this diff Show More