From 598cc585bdb4dbb928199a89449094c2006421ce Mon Sep 17 00:00:00 2001 From: Kevin Minehart <5140827+kminehart@users.noreply.github.com> Date: Thu, 31 Jul 2025 14:25:59 -0500 Subject: [PATCH 01/89] CI: Push dev images from PRs and remove Drone from PRs (#109004) * Push docker images in PRs and remove Drone * fix actionlint errors * grep for docker doesn't need another grep --- .drone.star | 2 - .drone.yml | 497 ----------------------------- .github/workflows/pr-e2e-tests.yml | 89 +++++- 3 files changed, 77 insertions(+), 511 deletions(-) diff --git a/.drone.star b/.drone.star index a430359e27d..a563ee0682a 100644 --- a/.drone.star +++ b/.drone.star @@ -8,7 +8,6 @@ This module returns a Drone configuration including pipelines and secrets. """ load("scripts/drone/events/main.star", "main_pipelines") -load("scripts/drone/events/pr.star", "pr_pipelines") load( "scripts/drone/events/release.star", "publish_artifacts_pipelines", @@ -28,7 +27,6 @@ load("scripts/drone/vault.star", "secrets") def main(_ctx): return ( - pr_pipelines() + main_pipelines() + rrc_patch_pipelines() + publish_image_pipelines_public() + diff --git a/.drone.yml b/.drone.yml index 2ca377f28a9..52bdd9dc125 100644 --- a/.drone.yml +++ b/.drone.yml @@ -8,498 +8,6 @@ image_pull_secrets: - gcr - gar kind: pipeline -name: pr-verify-drone -node: - type: no-parallel -platform: - arch: amd64 - os: linux -services: [] -steps: -- commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.21.3 - name: identify-runner -- commands: - - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd - depends_on: [] - environment: - CGO_ENABLED: 0 - image: golang:1.24.5-alpine - name: compile-build-cmd -- commands: - - ./bin/build verify-drone - depends_on: - - compile-build-cmd - image: byrnedo/alpine-curl:0.1.8 - name: lint-drone -trigger: - event: - - pull_request - paths: - exclude: - - docs/** - - '*.md' - include: - - scripts/drone/** - - .drone.yml - - .drone.star -type: docker -volumes: -- host: - path: /var/run/docker.sock - name: docker ---- -clone: - retries: 3 -depends_on: [] -environment: - EDITION: oss -image_pull_secrets: -- gcr -- gar -kind: pipeline -name: pr-verify-starlark -node: - type: no-parallel -platform: - arch: amd64 - os: linux -services: [] -steps: -- commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.21.3 - name: identify-runner -- commands: - - go install github.com/bazelbuild/buildtools/buildifier@latest - - buildifier --lint=warn -mode=check -r . - depends_on: [] - image: golang:1.24.5-alpine - name: lint-starlark -trigger: - event: - - pull_request - paths: - exclude: - - docs/** - - '*.md' - include: - - scripts/drone/** - - .drone.star -type: docker -volumes: -- host: - path: /var/run/docker.sock - name: docker ---- -clone: - retries: 3 -depends_on: [] -environment: - EDITION: oss -image_pull_secrets: -- gcr -- gar -kind: pipeline -name: pr-build-e2e -node: - type: no-parallel -platform: - arch: amd64 - os: linux -services: [] -steps: -- commands: - - echo $(/usr/bin/github-app-external-token) > /github-app/token - environment: - GITHUB_APP_ID: - from_secret: github-app-app-id - GITHUB_APP_INSTALLATION_ID: - from_secret: github-app-installation-id - GITHUB_APP_PRIVATE_KEY: - from_secret: github-app-private-key - failure: ignore - image: us-docker.pkg.dev/grafanalabs-global/docker-deployment-tools-prod/github-app-secret-writer:2024-11-05-v11688112090.1-83920c59 - name: github-app-generate-token - volumes: - - name: github-app - path: /github-app -- commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.21.3 - name: identify-runner -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl -- commands: - - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd - depends_on: [] - environment: - CGO_ENABLED: 0 - image: golang:1.24.5-alpine - name: compile-build-cmd -- commands: - - '# It is required that code generated from Thema/CUE be committed and in sync - with its inputs.' - - '# The following command will fail if running code generators produces any diff - in output.' - - apk add --update make - - CODEGEN_VERIFY=1 make gen-cue - depends_on: [] - image: golang:1.24.5-alpine - name: verify-gen-cue -- commands: - - '# It is required that generated jsonnet is committed and in sync with its inputs.' - - '# The following command will fail if running code generators produces any diff - in output.' - - apk add --update make - - CODEGEN_VERIFY=1 make gen-jsonnet - depends_on: [] - image: golang:1.24.5-alpine - name: verify-gen-jsonnet -- commands: - - yarn install --immutable || yarn install --immutable - depends_on: [] - image: node:22.16.0-alpine - name: yarn-install -- commands: - - apk add --update jq bash - - yarn packages:build - - yarn packages:pack - - ./scripts/validate-npm-packages.sh - depends_on: - - yarn-install - environment: - NODE_OPTIONS: --max_old_space_size=8192 - image: node:22.16.0-alpine - name: build-frontend-packages -- failure: ignore - image: grafana/drone-downstream - name: trigger-enterprise-downstream - settings: - params: - - SOURCE_BUILD_NUMBER=${DRONE_COMMIT} - - SOURCE_COMMIT=${DRONE_COMMIT} - - OSS_PULL_REQUEST=${DRONE_PULL_REQUEST} - repositories: - - grafana/grafana-enterprise@${DRONE_SOURCE_BRANCH} - server: https://drone.grafana.net - token: - from_secret: drone_token -- commands: - - wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz - | tar zx -C /bin - - apk add docker - - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version - - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*' - - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all - - go run ./pkg/build/cmd artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64 - -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 --yarn-cache=$$YARN_CACHE_FOLDER --build-id=$$DRONE_BUILD_NUMBER - --ubuntu-base=ubuntu-base --alpine-base=alpine-base --tag-format='{{ .version_base - }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{ .version_base }}-{{ .buildID - }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD > packages.txt - - find ./dist -name '*docker*.tar.gz' -type f | xargs -n1 docker load -i - depends_on: - - yarn-install - environment: - _EXPERIMENTAL_DAGGER_CLOUD_TOKEN: - from_secret: dagger_token - image: golang:1.24.5-alpine - name: rgm-package - pull: always - volumes: - - name: docker - path: /var/run/docker.sock -- commands: - - ./bin/grabpl artifacts docker publish --dockerhub-repo grafana/grafana - depends_on: - - rgm-package - environment: - DOCKER_PASSWORD: - from_secret: docker_password - DOCKER_USER: - from_secret: docker_username - GITHUB_APP_ID: "329617" - GITHUB_APP_INSTALLATION_ID: "37346161" - GITHUB_APP_PRIVATE_KEY: - from_secret: delivery-bot-app-private-key - failure: ignore - image: google/cloud-sdk:431.0.0 - name: publish-images-grafana - volumes: - - name: docker - path: /var/run/docker.sock -- commands: - - yarn e2e:plugin:build - depends_on: - - yarn-install - environment: - NODE_OPTIONS: --max_old_space_size=8192 - image: node:22.16.0-alpine - name: build-test-plugins -- commands: - - apk add --update tar bash - - mkdir grafana - - tar --strip-components=1 -xvf ./dist/*amd64.tar.gz -C grafana - - cp -r devenv scripts tools grafana && cd grafana && ./scripts/grafana-server/start-server - depends_on: - - rgm-package - detach: true - environment: - GF_APP_MODE: development - GF_SERVER_HTTP_PORT: "3001" - GF_SERVER_ROUTER_LOGGING: "1" - image: alpine:3.21.3 - name: grafana-server -- commands: - - GITHUB_TOKEN=$(cat /github-app/token) - - cd / - - ./cpp-e2e/scripts/ci-run.sh azure ${DRONE_SOURCE_BRANCH} - depends_on: - - grafana-server - - github-app-generate-token - environment: - AZURE_SP_APP_ID: - from_secret: azure_sp_app_id - AZURE_SP_PASSWORD: - from_secret: azure_sp_app_pw - AZURE_TENANT: - from_secret: azure_tenant - CYPRESS_CI: "true" - HOST: grafana-server - image: us-docker.pkg.dev/grafanalabs-dev/docker-oss-plugin-partnerships-dev/e2e-14.3.2:1.0.0 - name: end-to-end-tests-cloud-plugins-suite-azure - volumes: - - name: github-app - path: /github-app - when: - paths: - include: - - pkg/tsdb/azuremonitor/** - - public/app/plugins/datasource/azuremonitor/** - - e2e/cloud-plugins-suite/azure-monitor.spec.ts - repo: - - grafana/grafana -- commands: - - npx wait-on@7.0.1 http://$HOST:$PORT - - yarn playwright install --with-deps chromium - - GRAFANA_URL=http://$HOST:$PORT yarn e2e:playwright --grep @plugins - depends_on: - - grafana-server - - build-test-plugins - environment: - HOST: grafana-server - PORT: "3001" - PROV_DIR: /grafana/scripts/grafana-server/tmp/conf/provisioning - image: node:22-bookworm - name: playwright-plugin-e2e -- commands: - - apt-get update - - apt-get install -yq zip - - printenv GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY > /tmp/gcpkey_upload_artifacts.json - - gcloud auth activate-service-account --key-file=/tmp/gcpkey_upload_artifacts.json - - gsutil cp -r ./playwright-report/. gs://releng-pipeline-artifacts-dev/${DRONE_BUILD_NUMBER}/playwright-report - - export E2E_PLAYWRIGHT_REPORT_URL=https://storage.googleapis.com/releng-pipeline-artifacts-dev/${DRONE_BUILD_NUMBER}/playwright-report/index.html - - "echo \"E2E Playwright report uploaded to: \n $${E2E_PLAYWRIGHT_REPORT_URL}\"" - depends_on: - - playwright-plugin-e2e - environment: - GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY: - from_secret: gcp_upload_artifacts_key - failure: ignore - image: google/cloud-sdk:431.0.0 - name: playwright-e2e-report-upload - when: - status: - - success - - failure -- commands: - - GITHUB_TOKEN=$(cat /github-app/token) - - if [ ! -d ./playwright-report/trace ]; then echo 'all tests passed'; exit 0; fi - - export E2E_PLAYWRIGHT_REPORT_URL=https://storage.googleapis.com/releng-pipeline-artifacts-dev/${DRONE_BUILD_NUMBER}/playwright-report/index.html - - 'curl -L -X POST https://api.github.com/repos/grafana/grafana/issues/${DRONE_PULL_REQUEST}/comments - -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $${GITHUB_TOKEN}" - -H "X-GitHub-Api-Version: 2022-11-28" -d "{\"body\":\"❌ Failed to run Playwright - plugin e2e tests.

Click [here]($${E2E_PLAYWRIGHT_REPORT_URL}) to - browse the Playwright report and trace viewer.
For information on how to - run Playwright tests locally, refer to the [Developer guide](https://github.com/grafana/grafana/blob/main/contribute/developer-guide.md#to-run-the-playwright-tests). - \"}"' - depends_on: - - playwright-e2e-report-upload - - github-app-generate-token - failure: ignore - image: byrnedo/alpine-curl:0.1.8 - name: playwright-e2e-report-post-link - volumes: - - name: github-app - path: /github-app - when: - status: - - success - - failure -- commands: - - export GITHUB_TOKEN=$(cat /github-app/token) - - if [ -z `find ./e2e -type f -name *spec.ts.mp4` ]; then echo 'no e2e videos found - from remaining tests'; exit 0; fi - - apt-get update - - apt-get install -yq zip - - printenv GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY > /tmp/gcpkey_upload_artifacts.json - - gcloud auth activate-service-account --key-file=/tmp/gcpkey_upload_artifacts.json - - find ./e2e -type f -name "*spec.ts.mp4" | zip e2e/videos.zip -@ - - gsutil cp e2e/videos.zip gs://$${E2E_TEST_ARTIFACTS_BUCKET}/${DRONE_BUILD_NUMBER}/artifacts/videos/videos.zip - - export E2E_ARTIFACTS_VIDEO_ZIP=https://storage.googleapis.com/$${E2E_TEST_ARTIFACTS_BUCKET}/${DRONE_BUILD_NUMBER}/artifacts/videos/videos.zip - - 'echo "E2E Test artifacts uploaded to: $${E2E_ARTIFACTS_VIDEO_ZIP}"' - - 'curl -X POST https://api.github.com/repos/${DRONE_REPO}/statuses/${DRONE_COMMIT_SHA} - -H "Authorization: token $${GITHUB_TOKEN}" -d "{\"state\":\"success\",\"target_url\":\"$${E2E_ARTIFACTS_VIDEO_ZIP}\", - \"description\": \"Click on the details to download e2e recording videos\", \"context\": - \"e2e_artifacts\"}"' - depends_on: - - end-to-end-tests-cloud-plugins-suite-azure - - playwright-plugin-e2e - - github-app-generate-token - environment: - E2E_TEST_ARTIFACTS_BUCKET: releng-pipeline-artifacts-dev - GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY: - from_secret: gcp_upload_artifacts_key - failure: ignore - image: google/cloud-sdk:431.0.0 - name: e2e-tests-artifacts-upload - volumes: - - name: github-app - path: /github-app - when: - status: - - success - - failure -- commands: - - yarn storybook:build - - ./bin/build verify-storybook - depends_on: - - rgm-package - - build-frontend-packages - environment: - NODE_OPTIONS: --max_old_space_size=4096 - image: node:22.16.0-alpine - name: build-storybook - when: - paths: - include: - - packages/grafana-ui/** -- commands: - - npx wait-on@7.0.1 http://$HOST:$PORT - - pa11y-ci --config e2e/pa11yci.conf.js - depends_on: - - grafana-server - environment: - GRAFANA_MISC_STATS_API_KEY: - from_secret: grafana_misc_stats_api_key - HOST: grafana-server - NO_THRESHOLDS: "false" - PORT: 3001 - failure: always - image: grafana/docker-puppeteer:1.1.0 - name: test-a11y-frontend -trigger: - event: - - pull_request - paths: - exclude: - - '*.md' - - docs/** - - latest.json -type: docker -volumes: -- host: - path: /var/run/docker.sock - name: docker -- name: github-app - temp: {} ---- -clone: - retries: 3 -depends_on: [] -environment: - EDITION: oss -image_pull_secrets: -- gcr -- gar -kind: pipeline -name: pr-docs -node: - type: no-parallel -platform: - arch: amd64 - os: linux -services: [] -steps: -- commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.21.3 - name: identify-runner -- commands: - - yarn install --immutable || yarn install --immutable - depends_on: [] - image: node:22.16.0-alpine - name: yarn-install -- commands: - - yarn run prettier:checkDocs - depends_on: - - yarn-install - environment: - NODE_OPTIONS: --max_old_space_size=8192 - image: node:22.16.0-alpine - name: lint-docs -- commands: - - mkdir -p /hugo/content/docs/grafana/latest - - 'echo -e ''---\nredirectURL: /docs/grafana/latest/\ntype: redirect\nversioned: - true\n---\n'' > /hugo/content/docs/grafana/_index.md' - - cp -r docs/sources/* /hugo/content/docs/grafana/latest/ - - cd /hugo && make prod - image: grafana/docs-base:latest - name: build-docs-website - pull: always -- commands: - - '# It is required that code generated from Thema/CUE be committed and in sync - with its inputs.' - - '# The following command will fail if running code generators produces any diff - in output.' - - apk add --update make - - CODEGEN_VERIFY=1 make gen-cue - depends_on: [] - image: golang:1.24.5-alpine - name: verify-gen-cue -trigger: - event: - - pull_request - paths: - include: - - '*.md' - - docs/** - - packages/**/*.md - - latest.json - repo: - - grafana/grafana -type: docker -volumes: -- host: - path: /var/run/docker.sock - name: docker ---- -clone: - retries: 3 -depends_on: [] -environment: - EDITION: oss -image_pull_secrets: -- gcr -- gar -kind: pipeline name: main-docs node: type: no-parallel @@ -2365,8 +1873,3 @@ get: path: secret/data/common/gcr kind: secret name: gcr_credentials ---- -kind: signature -hmac: bfbdbe4aeedbcdc8778dd67abdfe94a75a20bdb314d1c53418cf2c2ea7a9f0c9 - -... diff --git a/.github/workflows/pr-e2e-tests.yml b/.github/workflows/pr-e2e-tests.yml index 6ceff2b9d45..5c9ad0e71d4 100644 --- a/.github/workflows/pr-e2e-tests.yml +++ b/.github/workflows/pr-e2e-tests.yml @@ -44,8 +44,6 @@ jobs: runs-on: ubuntu-latest-16-cores permissions: contents: read - outputs: - artifact: ${{ steps.artifact.outputs.artifact }} steps: - uses: actions/checkout@v4 with: @@ -57,7 +55,7 @@ jobs: - uses: actions/cache@v4 id: cache with: - key: "build-grafana-${{ runner.os }}-${{ hashFiles('yarn.lock', 'public/*', 'packages/*', 'pkg/**/*.go', '**/go.mod', '**/go.sum', '!**_test.go', '!**.test.ts', '!**.test.tsx') }}" + key: "build-grafana-${{ runner.os }}-${{ hashFiles('yarn.lock', 'public/*', 'packages/*', 'pkg/**/*.go', '**/go.mod', '**/go.sum', '!**_test.go', '!**.test.ts', '!**.test.tsx', 'Dockerfile') }}" path: | build-dir @@ -67,15 +65,16 @@ jobs: uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e with: verb: run - args: go run ./pkg/build/cmd artifacts -a targz:grafana:linux/amd64 --grafana-dir="${PWD}" > out.txt + args: go run ./pkg/build/cmd artifacts -a targz:grafana:linux/amd64 -a docker:grafana:linux/amd64 --grafana-dir="${PWD}" > out.txt - name: Cat built artifact if: steps.cache.outputs.cache-hit != 'true' run: cat out.txt - - name: Move built artifact + - name: Move built artifacts if: steps.cache.outputs.cache-hit != 'true' run: | mkdir -p build-dir - mv "$(cat out.txt)" build-dir/grafana.tar.gz + mv "$(grep 'grafana_.*tar.gz$' out.txt | grep -Fv -m1 'docker')" build-dir/grafana.tar.gz + mv "$(grep 'grafana_.*docker.tar.gz$' out.txt)" build-dir/grafana.docker.tar.gz # If cache hit, validate the artifact is present - name: Validate artifact @@ -90,14 +89,20 @@ jobs: run: echo "artifact=grafana-server-${{github.run_number}}" >> "$GITHUB_OUTPUT" id: artifact - - name: Upload artifact + - name: Upload grafana.tar.gz uses: actions/upload-artifact@v4 - id: upload with: retention-days: 1 - name: ${{ steps.artifact.outputs.artifact }} + name: grafana-tar-gz path: build-dir/grafana.tar.gz + - name: Upload grafana docker tarball + uses: actions/upload-artifact@v4 + with: + retention-days: 1 + name: grafana-docker-tar-gz + path: build-dir/grafana.docker.tar.gz + # TODO: we won't need this when we only have playwright build-e2e-runner: needs: detect-changes @@ -131,6 +136,66 @@ jobs: name: ${{ steps.artifact.outputs.artifact }} path: e2e-runner + push-docker-image: + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false + permissions: + contents: read + id-token: write + runs-on: ubuntu-latest + needs: + - build-grafana + steps: + - id: vault-secrets + uses: grafana/shared-workflows/actions/get-vault-secrets@main + with: + repo_secrets: | + GRAFANA_DELIVERY_BOT_APP_PEM=delivery-bot-app:PRIVATE_KEY + - name: Generate token + id: generate_token + uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a + with: + app_id: ${{ vars.DELIVERY_BOT_APP_ID }} + private_key: ${{ env.GRAFANA_DELIVERY_BOT_APP_PEM }} + repositories: '["grafana"]' + permissions: '{"checks": "write"}' + - uses: grafana/shared-workflows/actions/login-to-gar@main + id: login-to-gar + with: + registry: 'us-docker.pkg.dev' + environment: 'dev' + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 + with: + name: grafana-docker-tar-gz + path: . + - name: Load & Push Docker image + env: + BUILD_ID: ${{ github.run_id }} + run: | + set -euo pipefail + LOADED_IMAGE_NAME=$(docker load -i grafana.docker.tar.gz | sed 's/Loaded image: //g') + VERSION=$(echo "${LOADED_IMAGE_NAME}" | cut -d ':' -f 2 | cut -d '-' -f 1) + DOCKER_IMAGE="us-docker.pkg.dev/grafanalabs-dev/docker-grafana-dev/grafana:${VERSION}-${BUILD_ID}" + docker tag "${LOADED_IMAGE_NAME}" "${DOCKER_IMAGE}" + docker push "${DOCKER_IMAGE}" + echo "IMAGE=${DOCKER_IMAGE}" >> "$GITHUB_ENV" + - name: Add PR status check + env: + GH_TOKEN: ${{ steps.generate_token.outputs.token }} + SHA: ${{ github.event.pull_request.head.sha }} + run: | + gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/grafana/grafana/check-runs \ + -f "name=${IMAGE}" \ + -f "head_sha=${SHA}" \ + -f 'status=completed' \ + -f 'conclusion=neutral' \ + -f 'output[title]=Docker image' \ + -f "output[summary]=${IMAGE}" \ + -f "output[text]=${IMAGE}" + run-e2e-tests: needs: - build-grafana @@ -166,7 +231,7 @@ jobs: persist-credentials: false - uses: actions/download-artifact@v4 with: - name: ${{ needs.build-grafana.outputs.artifact }} + name: grafana-tar-gz - uses: actions/download-artifact@v4 with: name: ${{ needs.build-e2e-runner.outputs.artifact }} @@ -242,7 +307,7 @@ jobs: persist-credentials: false - uses: actions/download-artifact@v4 with: - name: ${{ needs.build-grafana.outputs.artifact }} + name: grafana-tar-gz - name: Run E2E tests uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e with: @@ -354,7 +419,7 @@ jobs: persist-credentials: false - uses: actions/download-artifact@v4 with: - name: ${{ needs.build-grafana.outputs.artifact }} + name: grafana-tar-gz - name: Run PR a11y test if: github.event_name == 'pull_request' uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e From 925e19acf278e479f2dd6368393b8bb04f447d20 Mon Sep 17 00:00:00 2001 From: Kevin Minehart <5140827+kminehart@users.noreply.github.com> Date: Thu, 31 Jul 2025 15:33:27 -0500 Subject: [PATCH 02/89] CI: set source-event in release-build dispatch (#109009) * set source-event in release-build dispatch * missing inputs key --- .github/workflows/release-build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 231bb0395c2..33288a4f971 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -1,6 +1,12 @@ name: Build Release Packages on: workflow_dispatch: + inputs: + source-event: + description: If this workflow was triggered by another workflow, this value should be set to the GITHUB_EVENT_NAME of that source workflow. + type: string + required: false + default: workflow_dispatch schedule: # Every weeknight at midnight # "Scheduled workflows will only run on the default branch." (docs.github.com) From 025d8527dd986216bb7be86b2f3d2df3bf4f7cb2 Mon Sep 17 00:00:00 2001 From: ismail simsek Date: Thu, 31 Jul 2025 23:32:43 +0200 Subject: [PATCH 03/89] Prometheus: Refactor metrics modal to handle high cardinality metrics (#108437) * remove redux from PromQueryBuilderContainer * remove export * housekeeping * introduce MetricsModalContext to replace redux * handle result pagination * add search related values in context * handle filtering * handle search * handle search and highlighting * cleaning up * better helpers * remove unused types * reorganize the code * update settings * improve search and fetch * remove unused styles * linting * fix tests * update * lint * i18n * import order * try to fix the test * remove start call from variable editor * fix highlighter * fix pagination alignment * make the entire row clickable and remove select button * review updates * remove settings * use ufuzzy search * fix tests * use case-insensitive search * review fixes * fix pagination * improve readability --- .../helpers/prometheus-helpers.ts | 6 +- .../various-suite/prometheus-editor.spec.ts | 7 +- .../components/VariableQueryEditor.test.tsx | 21 -- .../src/components/VariableQueryEditor.tsx | 5 - .../src/locales/en-US/grafana-prometheus.json | 14 - .../components/MetricCombobox.tsx | 21 +- .../querybuilder/components/NestedQuery.tsx | 2 +- .../components/PromQueryBuilder.tsx | 20 +- .../PromQueryBuilderContainer.test.tsx | 4 - .../components/PromQueryBuilderContainer.tsx | 80 +---- .../{shared => }/QueryBuilderContent.tsx | 43 ++- .../components/{shared => }/formatter.ts | 6 +- .../metrics-modal/AdditionalSettings.tsx | 87 ----- .../metrics-modal/MetricsModal.test.tsx | 95 +++-- .../components/metrics-modal/MetricsModal.tsx | 335 ++++-------------- .../MetricsModalContext.test.tsx | 329 +++++++++++++++++ .../metrics-modal/MetricsModalContext.tsx | 201 +++++++++++ .../components/metrics-modal/ResultsTable.tsx | 192 +++------- .../components/metrics-modal/helpers.test.ts | 313 ++++++++++++++++ .../components/metrics-modal/helpers.ts | 123 +++++++ .../components/metrics-modal/shared/types.ts | 30 -- .../components/metrics-modal/state/helpers.ts | 278 --------------- .../components/metrics-modal/state/state.ts | 212 ----------- .../components/metrics-modal/styles.ts | 85 +++-- .../metrics-modal/{shared => }/testIds.ts | 3 - .../components/metrics-modal/uFuzzy.ts | 54 ++- .../components/shared/BaseQueryBuilder.tsx | 27 -- .../querybuilder/components/shared/types.ts | 13 - .../src/querybuilder/types.ts | 5 - packages/grafana-prometheus/src/types.ts | 5 - 30 files changed, 1279 insertions(+), 1337 deletions(-) rename packages/grafana-prometheus/src/querybuilder/components/{shared => }/QueryBuilderContent.tsx (67%) rename packages/grafana-prometheus/src/querybuilder/components/{shared => }/formatter.ts (81%) delete mode 100644 packages/grafana-prometheus/src/querybuilder/components/metrics-modal/AdditionalSettings.tsx create mode 100644 packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModalContext.test.tsx create mode 100644 packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModalContext.tsx create mode 100644 packages/grafana-prometheus/src/querybuilder/components/metrics-modal/helpers.test.ts create mode 100644 packages/grafana-prometheus/src/querybuilder/components/metrics-modal/helpers.ts delete mode 100644 packages/grafana-prometheus/src/querybuilder/components/metrics-modal/shared/types.ts delete mode 100644 packages/grafana-prometheus/src/querybuilder/components/metrics-modal/state/helpers.ts delete mode 100644 packages/grafana-prometheus/src/querybuilder/components/metrics-modal/state/state.ts rename packages/grafana-prometheus/src/querybuilder/components/metrics-modal/{shared => }/testIds.ts (65%) delete mode 100644 packages/grafana-prometheus/src/querybuilder/components/shared/BaseQueryBuilder.tsx delete mode 100644 packages/grafana-prometheus/src/querybuilder/components/shared/types.ts diff --git a/e2e/old-arch/various-suite/helpers/prometheus-helpers.ts b/e2e/old-arch/various-suite/helpers/prometheus-helpers.ts index 265095ecd65..0102bcec3ab 100644 --- a/e2e/old-arch/various-suite/helpers/prometheus-helpers.ts +++ b/e2e/old-arch/various-suite/helpers/prometheus-helpers.ts @@ -24,11 +24,11 @@ export function createPromDS(dataSourceID: string, name: string): void { } export function getResources() { - cy.intercept(/__name__/g, metricResponse); + cy.intercept(/__name__/g, metricResponse).as('getMetricNames'); - cy.intercept(/metadata/g, metadataResponse); + cy.intercept(/metadata/g, metadataResponse).as('getMetadata'); - cy.intercept(/labels/g, labelsResponse); + cy.intercept(/labels/g, labelsResponse).as('getLabels'); } const metricResponse = { diff --git a/e2e/old-arch/various-suite/prometheus-editor.spec.ts b/e2e/old-arch/various-suite/prometheus-editor.spec.ts index 4a2b5aed7a3..7b3093f4f5d 100644 --- a/e2e/old-arch/various-suite/prometheus-editor.spec.ts +++ b/e2e/old-arch/various-suite/prometheus-editor.spec.ts @@ -138,12 +138,11 @@ describe('Prometheus query editor', () => { it('can select a metric and provide a hint', () => { navigateToEditor('Builder', 'prometheusBuilder'); - getResources(); - - e2e.components.DataSource.Prometheus.queryEditor.builder.metricSelect().should('exist').click().type('metric1'); + e2e.components.DataSource.Prometheus.queryEditor.builder.metricSelect().should('exist').click(); + cy.wait('@getMetadata'); + e2e.components.DataSource.Prometheus.queryEditor.builder.metricSelect().type('metric1'); selectOption('metric1'); - e2e.components.DataSource.Prometheus.queryEditor.builder.hints().contains('hint: add rate'); }); diff --git a/packages/grafana-prometheus/src/components/VariableQueryEditor.test.tsx b/packages/grafana-prometheus/src/components/VariableQueryEditor.test.tsx index 4e4c63352f3..1edbf5ba744 100644 --- a/packages/grafana-prometheus/src/components/VariableQueryEditor.test.tsx +++ b/packages/grafana-prometheus/src/components/VariableQueryEditor.test.tsx @@ -3,7 +3,6 @@ import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { select } from 'react-select-event'; -import { dateTime, TimeRange } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { PrometheusDatasource } from '../datasource'; @@ -376,24 +375,4 @@ describe('PromVariableQueryEditor', () => { qryType: 5, }); }); - - test('Calls language provider with the time range received in props', async () => { - const now = dateTime('2023-09-16T21:26:00Z'); - const range: TimeRange = { - from: dateTime(now).subtract(2, 'days'), - to: now, - raw: { - from: 'now-2d', - to: 'now', - }, - }; - props.range = range; - - const languageProviderStartMock = jest.fn(); - props.datasource.languageProvider.start = languageProviderStartMock; - - render(); - - expect(languageProviderStartMock).toHaveBeenCalledWith(range); - }); }); diff --git a/packages/grafana-prometheus/src/components/VariableQueryEditor.tsx b/packages/grafana-prometheus/src/components/VariableQueryEditor.tsx index d8f99a7bc48..2ec81339219 100644 --- a/packages/grafana-prometheus/src/components/VariableQueryEditor.tsx +++ b/packages/grafana-prometheus/src/components/VariableQueryEditor.tsx @@ -77,11 +77,6 @@ export const PromVariableQueryEditor = ({ onChange, query, datasource, range }: // label filters have been added as a filter for metrics in label values query type const [labelFilters, setLabelFilters] = useState([]); - useEffect(() => { - datasource.languageProvider.start(range); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - useEffect(() => { if (!query) { return; diff --git a/packages/grafana-prometheus/src/locales/en-US/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/en-US/grafana-prometheus.json index b94bb4cded3..f67ac0e3e9f 100644 --- a/packages/grafana-prometheus/src/locales/en-US/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/en-US/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "Filter metric names by regex search, using an additional call on the Prometheus API.", - "disable-text-wrap": "Disable text wrap" - }, "feedback-link": { "give-feedback": "Give feedback", "title-give-feedback": "The metrics explorer is new, please let us know how we can improve it" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "Search metrics by name", - "include-null-metadata": "Include results with no metadata", - "metadata-search-switch": "Include description in search", - "set-use-backend": "Enable regex search", "type": "Filter by type" }, "get-prom-types": { @@ -378,15 +371,9 @@ "tooltip-metric": "Optional: returns a list of label values for the label name in the specified metric." }, "metrics-modal": { - "additional-settings": "Additional Settings", - "aria-label-additional-settings": "Additional settings", "aria-label-browse-metrics": "Browse metrics", "currently-selected": "Currently selected: {{selected}}", "metrics-pre-filtered": "These metrics have been pre-filtered by labels chosen in the label filters.", - "placeholder-results-per-page": "results per page", - "results-amount_one": "Showing {{num}} of {{count}} results", - "results-amount_other": "Showing {{num}} of {{count}} results", - "results-per-page": "Results per page", "title-metrics-explorer": "Metrics explorer" }, "nested-query": { @@ -500,7 +487,6 @@ "message-expand-search": "There are no metrics found. Try to expand your search and filters.", "message-no-metrics-found": "There are no metrics found in the data source.", "name": "Name", - "select": "Select", "type": "Type" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/querybuilder/components/MetricCombobox.tsx b/packages/grafana-prometheus/src/querybuilder/components/MetricCombobox.tsx index 21a88427159..eaafcb1aa68 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/MetricCombobox.tsx +++ b/packages/grafana-prometheus/src/querybuilder/components/MetricCombobox.tsx @@ -11,9 +11,8 @@ import { PrometheusDatasource } from '../../datasource'; import { QueryBuilderLabelFilter } from '../shared/types'; import { PromVisualQuery } from '../types'; +import { formatKeyValueStrings } from './formatter'; import { MetricsModal } from './metrics-modal/MetricsModal'; -import { tracking } from './metrics-modal/state/helpers'; -import { formatKeyValueStrings } from './shared/formatter'; export interface MetricComboboxProps { metricLookupDisabled: boolean; @@ -76,18 +75,6 @@ export function MetricCombobox({ [getMetricLabels, onGetMetrics] ); - const loadMetricsExplorerMetrics = useCallback(async () => { - const allMetrics = await onGetMetrics(); - const metrics: string[] = []; - for (const metric of allMetrics) { - if (metric.value) { - metrics.push(metric.value); - } - } - - return metrics; - }, [onGetMetrics]); - const asyncSelect = () => { return ( @@ -115,10 +102,7 @@ export function MetricCombobox({ )} variant="secondary" icon="book-open" - onClick={() => { - tracking('grafana_prometheus_metric_encyclopedia_open', null, '', query); - setMetricsModalOpen(true); - }} + onClick={() => setMetricsModalOpen(true)} /> ); @@ -133,7 +117,6 @@ export function MetricCombobox({ onClose={() => setMetricsModalOpen(false)} query={query} onChange={onChange} - initialMetrics={loadMetricsExplorerMetrics} timeRange={timeRange} /> )} diff --git a/packages/grafana-prometheus/src/querybuilder/components/NestedQuery.tsx b/packages/grafana-prometheus/src/querybuilder/components/NestedQuery.tsx index 8ac17b1b854..daa84a83c62 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/NestedQuery.tsx +++ b/packages/grafana-prometheus/src/querybuilder/components/NestedQuery.tsx @@ -11,7 +11,7 @@ import { PrometheusDatasource } from '../../datasource'; import { binaryScalarDefs } from '../binaryScalarOperations'; import { PromVisualQueryBinary } from '../types'; -import { QueryBuilderContent } from './shared/QueryBuilderContent'; +import { QueryBuilderContent } from './QueryBuilderContent'; interface NestedQueryProps { nestedQuery: PromVisualQueryBinary; diff --git a/packages/grafana-prometheus/src/querybuilder/components/PromQueryBuilder.tsx b/packages/grafana-prometheus/src/querybuilder/components/PromQueryBuilder.tsx index 03bf97718bc..9504e50b5c0 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/PromQueryBuilder.tsx +++ b/packages/grafana-prometheus/src/querybuilder/components/PromQueryBuilder.tsx @@ -6,7 +6,8 @@ import { PanelData } from '@grafana/data'; import { PrometheusDatasource } from '../../datasource'; import { PromVisualQuery } from '../types'; -import { BaseQueryBuilder } from './shared/BaseQueryBuilder'; +import { NestedQueryList } from './NestedQueryList'; +import { QueryBuilderContent } from './QueryBuilderContent'; interface PromQueryBuilderProps { query: PromVisualQuery; @@ -18,7 +19,22 @@ interface PromQueryBuilderProps { } export const PromQueryBuilder = memo((props) => { - return ; + const { query, datasource, onChange, onRunQuery, showExplain } = props; + + return ( + <> + + {query.binaryQueries && query.binaryQueries.length > 0 && ( + + )} + + ); }); PromQueryBuilder.displayName = 'PromQueryBuilder'; diff --git a/packages/grafana-prometheus/src/querybuilder/components/PromQueryBuilderContainer.test.tsx b/packages/grafana-prometheus/src/querybuilder/components/PromQueryBuilderContainer.test.tsx index b325da19d45..3e400f13a50 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/PromQueryBuilderContainer.test.tsx +++ b/packages/grafana-prometheus/src/querybuilder/components/PromQueryBuilderContainer.test.tsx @@ -20,12 +20,8 @@ describe('PromQueryBuilderContainer', () => { await addOperationInQueryBuilder('Range functions', 'Rate'); // extra fields here are for storing metrics explorer settings. Future work: store these in local storage. expect(props.onChange).toHaveBeenCalledWith({ - disableTextWrap: false, expr: 'rate(metric_test{job="testjob"}[$__rate_interval])', - fullMetaSearch: false, - includeNullMetadata: true, refId: 'A', - useBackend: false, }); }); diff --git a/packages/grafana-prometheus/src/querybuilder/components/PromQueryBuilderContainer.tsx b/packages/grafana-prometheus/src/querybuilder/components/PromQueryBuilderContainer.tsx index 318d4a71213..31d3b6a6274 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/PromQueryBuilderContainer.tsx +++ b/packages/grafana-prometheus/src/querybuilder/components/PromQueryBuilderContainer.tsx @@ -1,6 +1,5 @@ // Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderContainer.tsx -import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { useEffect, useReducer } from 'react'; +import { useEffect, useState } from 'react'; import { PanelData } from '@grafana/data'; @@ -12,7 +11,6 @@ import { PromVisualQuery } from '../types'; import { PromQueryBuilder } from './PromQueryBuilder'; import { QueryPreview } from './QueryPreview'; -import { getSettings, MetricsModalSettings } from './metrics-modal/state/state'; interface PromQueryBuilderContainerProps { query: PromQuery; @@ -23,7 +21,7 @@ interface PromQueryBuilderContainerProps { showExplain: boolean; } -interface State { +interface RenderedQuery { visQuery?: PromVisualQuery; expr: string; } @@ -33,80 +31,38 @@ interface State { */ export function PromQueryBuilderContainer(props: PromQueryBuilderContainerProps) { const { query, onChange, onRunQuery, datasource, data, showExplain } = props; - const [state, dispatch] = useReducer(stateSlice.reducer, { expr: query.expr }); - // Only rebuild visual query if expr changes from outside - useEffect(() => { - dispatch(exprChanged(query.expr)); - dispatch( - setMetricsModalSettings({ - useBackend: query.useBackend ?? false, - disableTextWrap: query.disableTextWrap ?? false, - fullMetaSearch: query.fullMetaSearch ?? false, - includeNullMetadata: query.includeNullMetadata ?? true, - }) - ); - }, [query]); + const [rendered, setRendered] = useState({ expr: query.expr }); useEffect(() => { - datasource.languageProvider.start(data?.timeRange); - }, [data?.timeRange, datasource.languageProvider]); + // Only rebuild visual query if expr changes from outside + if (!rendered.visQuery || rendered.expr !== query.expr) { + const parseResult = buildVisualQueryFromString(query.expr ?? ''); + + setRendered({ expr: query.expr, visQuery: parseResult.query }); + } + }, [query, rendered]); const onVisQueryChange = (visQuery: PromVisualQuery) => { const expr = promQueryModeller.renderQuery(visQuery); - dispatch(visualQueryChange({ visQuery, expr })); - - const metricsModalSettings = getSettings(visQuery); - onChange({ ...props.query, expr: expr, ...metricsModalSettings }); + setRendered({ expr, visQuery }); + onChange({ ...props.query, expr }); }; - if (!state.visQuery) { + if (!rendered.visQuery) { return null; } return ( <> - {} + ); } - -const initialState: State = { - expr: '', -}; - -const stateSlice = createSlice({ - name: 'prom-builder-container', - initialState, - reducers: { - visualQueryChange: (state, action: PayloadAction<{ visQuery: PromVisualQuery; expr: string }>) => { - state.expr = action.payload.expr; - state.visQuery = action.payload.visQuery; - }, - exprChanged: (state, action: PayloadAction) => { - if (!state.visQuery || state.expr !== action.payload) { - state.expr = action.payload; - const parseResult = buildVisualQueryFromString(action.payload ?? ''); - - state.visQuery = parseResult.query; - } - }, - setMetricsModalSettings: (state, action: PayloadAction) => { - if (state.visQuery) { - state.visQuery.useBackend = action.payload.useBackend; - state.visQuery.disableTextWrap = action.payload.disableTextWrap; - state.visQuery.fullMetaSearch = action.payload.fullMetaSearch; - state.visQuery.includeNullMetadata = action.payload.includeNullMetadata; - } - }, - }, -}); - -const { visualQueryChange, exprChanged, setMetricsModalSettings } = stateSlice.actions; diff --git a/packages/grafana-prometheus/src/querybuilder/components/shared/QueryBuilderContent.tsx b/packages/grafana-prometheus/src/querybuilder/components/QueryBuilderContent.tsx similarity index 67% rename from packages/grafana-prometheus/src/querybuilder/components/shared/QueryBuilderContent.tsx rename to packages/grafana-prometheus/src/querybuilder/components/QueryBuilderContent.tsx index ce00f36cbb9..b04537da808 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/shared/QueryBuilderContent.tsx +++ b/packages/grafana-prometheus/src/querybuilder/components/QueryBuilderContent.tsx @@ -1,28 +1,37 @@ import { css } from '@emotion/css'; import { memo, useState } from 'react'; -import { DataSourceApi, getDefaultTimeRange } from '@grafana/data'; +import { DataSourceApi, getDefaultTimeRange, PanelData } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { EditorRow } from '@grafana/plugin-ui'; -import { promqlGrammar } from '../../../promql'; -import { getInitHints } from '../../../query_hints'; -import { buildVisualQueryFromString } from '../../parsing'; -import { OperationExplainedBox } from '../../shared/OperationExplainedBox'; -import { OperationList } from '../../shared/OperationList'; -import { OperationListExplained } from '../../shared/OperationListExplained'; -import { OperationsEditorRow } from '../../shared/OperationsEditorRow'; -import { QueryBuilderHints } from '../../shared/QueryBuilderHints'; -import { RawQuery } from '../../shared/RawQuery'; -import { promQueryModeller } from '../../shared/modeller_instance'; -import { QueryBuilderOperation } from '../../shared/types'; -import { PromVisualQuery } from '../../types'; -import { MetricsLabelsSection } from '../MetricsLabelsSection'; -import { EXPLAIN_LABEL_FILTER_CONTENT } from '../PromQueryBuilderExplained'; +import { PrometheusDatasource } from '../../datasource'; +import { promqlGrammar } from '../../promql'; +import { getInitHints } from '../../query_hints'; +import { buildVisualQueryFromString } from '../parsing'; +import { OperationExplainedBox } from '../shared/OperationExplainedBox'; +import { OperationList } from '../shared/OperationList'; +import { OperationListExplained } from '../shared/OperationListExplained'; +import { OperationsEditorRow } from '../shared/OperationsEditorRow'; +import { QueryBuilderHints } from '../shared/QueryBuilderHints'; +import { RawQuery } from '../shared/RawQuery'; +import { promQueryModeller } from '../shared/modeller_instance'; +import { QueryBuilderOperation } from '../shared/types'; +import { PromVisualQuery } from '../types'; -import { BaseQueryBuilderProps } from './types'; +import { MetricsLabelsSection } from './MetricsLabelsSection'; +import { EXPLAIN_LABEL_FILTER_CONTENT } from './PromQueryBuilderExplained'; -export const QueryBuilderContent = memo((props) => { +interface QueryBuilderContentProps { + query: PromVisualQuery; + datasource: PrometheusDatasource; + onChange: (update: PromVisualQuery) => void; + onRunQuery: () => void; + data?: PanelData; + showExplain: boolean; +} + +export const QueryBuilderContent = memo((props) => { const { datasource, query, onChange, onRunQuery, data, showExplain } = props; const [highlightedOp, setHighlightedOp] = useState(); diff --git a/packages/grafana-prometheus/src/querybuilder/components/shared/formatter.ts b/packages/grafana-prometheus/src/querybuilder/components/formatter.ts similarity index 81% rename from packages/grafana-prometheus/src/querybuilder/components/shared/formatter.ts rename to packages/grafana-prometheus/src/querybuilder/components/formatter.ts index baf8228c573..bb795745816 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/shared/formatter.ts +++ b/packages/grafana-prometheus/src/querybuilder/components/formatter.ts @@ -1,7 +1,7 @@ -import { regexifyLabelValuesQueryString } from '../../parsingUtils'; -import { QueryBuilderLabelFilter } from '../../shared/types'; +import { regexifyLabelValuesQueryString } from '../parsingUtils'; +import { QueryBuilderLabelFilter } from '../shared/types'; -export const formatPrometheusLabelFiltersToString = ( +const formatPrometheusLabelFiltersToString = ( queryString: string, labelsFilters: QueryBuilderLabelFilter[] | undefined ): string => { diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/AdditionalSettings.tsx b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/AdditionalSettings.tsx deleted file mode 100644 index 4ce04117dd9..00000000000 --- a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/AdditionalSettings.tsx +++ /dev/null @@ -1,87 +0,0 @@ -// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/components/metrics-modal/AdditionalSettings.tsx -import { css } from '@emotion/css'; - -import { GrafanaTheme2 } from '@grafana/data'; -import { Trans, t } from '@grafana/i18n'; -import { Icon, Switch, Tooltip, useTheme2 } from '@grafana/ui'; - -import { metricsModaltestIds } from './shared/testIds'; -import { AdditionalSettingsProps } from './shared/types'; -import { getPlaceholders } from './state/helpers'; - -export function AdditionalSettings(props: AdditionalSettingsProps) { - const { state, onChangeFullMetaSearch, onChangeIncludeNullMetadata, onChangeDisableTextWrap, onChangeUseBackend } = - props; - - const theme = useTheme2(); - const styles = getStyles(theme); - - const placeholders = getPlaceholders(); - - return ( - <> -
- onChangeFullMetaSearch()} - /> -
{placeholders.metadataSearchSwitch}
-
-
- onChangeIncludeNullMetadata()} - /> -
{placeholders.includeNullMetadata}
-
-
- onChangeDisableTextWrap()} /> -
- - Disable text wrap - -
-
-
- onChangeUseBackend()} - /> -
{placeholders.setUseBackend} 
- - - -
- - ); -} - -function getStyles(theme: GrafanaTheme2) { - return { - settingsIcon: css({ - color: theme.colors.text.secondary, - }), - selectItem: css({ - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - padding: '4px 0', - }), - selectItemLabel: css({ - margin: `0 0 0 ${theme.spacing(1)}`, - alignSelf: 'center', - color: theme.colors.text.secondary, - fontSize: '12px', - }), - }; -} diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModal.test.tsx b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModal.test.tsx index c85089657cb..f57fbb59bd6 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModal.test.tsx +++ b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModal.test.tsx @@ -12,7 +12,7 @@ import { PromOptions } from '../../../types'; import { PromVisualQuery } from '../../types'; import { MetricsModal } from './MetricsModal'; -import { metricsModaltestIds } from './shared/testIds'; +import { metricsModaltestIds } from './testIds'; // don't care about interaction tracking in our unit tests jest.mock('@grafana/runtime', () => ({ @@ -117,28 +117,6 @@ describe('MetricsModal', () => { }); }); - it('shows results metrics per page chosen by the user', async () => { - setup(defaultQuery, listOfMetrics); - const resultsPerPageInput = screen.getByTestId(metricsModaltestIds.resultsPerPage); - await userEvent.type(resultsPerPageInput, '12'); - const metricInsideRange = screen.getByText('j'); - expect(metricInsideRange).toBeInTheDocument(); - }); - - it('paginates lots of metrics and does not run out of memory', async () => { - const lotsOfMetrics: string[] = [...Array(100000).keys()].map((i) => '' + i); - setup(defaultQuery, lotsOfMetrics); - await waitFor(() => { - // doesn't break on loading - expect(screen.getByText('0')).toBeInTheDocument(); - }); - const resultsPerPageInput = screen.getByTestId(metricsModaltestIds.resultsPerPage); - // doesn't break on changing results per page - await userEvent.type(resultsPerPageInput, '11'); - const metricInsideRange = screen.getByText('9'); - expect(metricInsideRange).toBeInTheDocument(); - }); - // Fuzzy search it('searches and filter by metric name with a fuzzy search', async () => { // search for a_bucket by name @@ -171,14 +149,6 @@ describe('MetricsModal', () => { expect(metricABucket).toBeInTheDocument(); }); - const showSettingsButton = screen.getByTestId(metricsModaltestIds.showAdditionalSettings); - expect(showSettingsButton).toBeInTheDocument(); - await userEvent.click(showSettingsButton); - - const metadataSwitch = screen.getByTestId(metricsModaltestIds.searchWithMetadata); - expect(metadataSwitch).toBeInTheDocument(); - await userEvent.click(metadataSwitch); - const searchMetric = screen.getByTestId(metricsModaltestIds.searchMetric); expect(searchMetric).toBeInTheDocument(); await userEvent.type(searchMetric, 'functions'); @@ -248,6 +218,34 @@ function createDatasource(withLabels?: boolean) { const languageProvider = new EmptyLanguageProviderMock() as unknown as PrometheusLanguageProviderInterface; // display different results if their labels are selected in the PromVisualQuery + if (withLabels) { + languageProvider.queryMetricsMetadata = jest.fn().mockResolvedValue({ + 'with-labels': { + type: 'with-labels-type', + help: 'with-labels-help', + }, + }); + } else { + // all metrics - create metadata for all metrics in listOfMetrics + const mockMetadata: Record = {}; + listOfMetrics.forEach((metric) => { + if (metric === 'all-metrics') { + mockMetadata[metric] = { type: 'all-metrics-type', help: 'all-metrics-help' }; + } else if (metric === 'a_bucket') { + mockMetadata[metric] = { type: 'histogram', help: 'for functions' }; + } else if (metric === 'new_histogram') { + mockMetadata[metric] = { type: 'histogram', help: 'a native histogram' }; + } else if (metric === 'a') { + mockMetadata[metric] = { type: 'counter', help: 'a-metric-help' }; + } else { + mockMetadata[metric] = { type: 'counter', help: `${metric} metric help` }; + } + }); + + languageProvider.queryMetricsMetadata = jest.fn().mockResolvedValue(mockMetadata); + } + + // Also mock the retrieveMetricsMetadata method that might be used elsewhere if (withLabels) { languageProvider.retrieveMetricsMetadata = jest.fn().mockReturnValue({ 'with-labels': { @@ -256,26 +254,23 @@ function createDatasource(withLabels?: boolean) { }, }); } else { - // all metrics - languageProvider.retrieveMetricsMetadata = jest.fn().mockReturnValue({ - 'all-metrics': { - type: 'all-metrics-type', - help: 'all-metrics-help', - }, - a: { - type: 'counter', - help: 'a-metric-help', - }, - a_bucket: { - type: 'histogram', - help: 'for functions', - }, - new_histogram: { - type: 'histogram', - help: 'a native histogram', - }, - // missing metadata for other metrics is tested for, see below + // Create the same metadata structure for retrieveMetricsMetadata + const mockMetadata: Record = {}; + listOfMetrics.forEach((metric) => { + if (metric === 'all-metrics') { + mockMetadata[metric] = { type: 'all-metrics-type', help: 'all-metrics-help' }; + } else if (metric === 'a_bucket') { + mockMetadata[metric] = { type: 'histogram', help: 'for functions' }; + } else if (metric === 'new_histogram') { + mockMetadata[metric] = { type: 'histogram', help: 'a native histogram' }; + } else if (metric === 'a') { + mockMetadata[metric] = { type: 'counter', help: 'a-metric-help' }; + } else { + mockMetadata[metric] = { type: 'counter', help: `${metric} metric help` }; + } }); + + languageProvider.retrieveMetricsMetadata = jest.fn().mockReturnValue(mockMetadata); } const datasource = new PrometheusDatasource( diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModal.tsx b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModal.tsx index 0722489b771..59c4c703ccf 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModal.tsx +++ b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModal.tsx @@ -1,107 +1,49 @@ // Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/components/metrics-modal/MetricsModal.tsx import { cx } from '@emotion/css'; -import debounce from 'debounce-promise'; -import { useCallback, useEffect, useMemo, useReducer } from 'react'; -import { SelectableValue } from '@grafana/data'; +import { SelectableValue, TimeRange } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { t, Trans } from '@grafana/i18n'; -import { - Button, - ButtonGroup, - Icon, - Input, - Modal, - MultiSelect, - Pagination, - Spinner, - Toggletip, - useTheme2, -} from '@grafana/ui'; +import { Icon, Input, Modal, MultiSelect, Pagination, Spinner, useStyles2 } from '@grafana/ui'; -import { getDebounceTimeInMilliseconds } from '../../../caching'; -import { METRIC_LABEL } from '../../../constants'; -import { regexifyLabelValuesQueryString } from '../../parsingUtils'; -import { formatPrometheusLabelFilters } from '../shared/formatter'; +import { PrometheusDatasource } from '../../../datasource'; +import { PromVisualQuery } from '../../types'; -import { AdditionalSettings } from './AdditionalSettings'; import { FeedbackLink } from './FeedbackLink'; +import { MetricsModalContextProvider, useMetricsModal } from './MetricsModalContext'; import { ResultsTable } from './ResultsTable'; -import { metricsModaltestIds } from './shared/testIds'; -import { MetricsModalProps } from './shared/types'; -import { - calculatePageList, - calculateResultsPerPage, - displayedMetrics, - getPlaceholders, - getPromTypes, - setMetrics, - tracking, -} from './state/helpers'; -import { - buildMetrics, - DEFAULT_RESULTS_PER_PAGE, - filterMetricsBackend, - initialState, - MAXIMUM_RESULTS_PER_PAGE, - MetricsModalMetadata, - setDisableTextWrap, - setFullMetaSearch, - setFuzzySearchQuery, - setIncludeNullMetadata, - setIsLoading, - setMetaHaystack, - setNameHaystack, - setPageNum, - setResultsPerPage, - setSelectedTypes, - setUseBackend, - showAdditionalSettings, - stateSlice, -} from './state/state'; -import { getStyles } from './styles'; +import { getPlaceholders, getPromTypes } from './helpers'; +import { getMetricsModalStyles } from './styles'; +import { metricsModaltestIds } from './testIds'; import { PromFilterOption } from './types'; -import { debouncedFuzzySearch } from './uFuzzy'; -export const MetricsModal = (props: MetricsModalProps) => { - const { datasource, isOpen, onClose, onChange, query, initialMetrics, timeRange } = props; +interface MetricsModalProps { + datasource: PrometheusDatasource; + timeRange: TimeRange; + isOpen: boolean; + query: PromVisualQuery; + onClose: () => void; + onChange: (query: PromVisualQuery) => void; +} - const [state, dispatch] = useReducer(stateSlice.reducer, initialState(query)); +const MetricsModalContent = (props: MetricsModalProps) => { + const { isOpen, onClose, onChange, query, timeRange } = props; - const theme = useTheme2(); - const styles = getStyles(theme, state.disableTextWrap); + const { + isLoading, + filteredMetricsData, + debouncedBackendSearch, + pagination, + setPagination, + selectedTypes, + setSelectedTypes, + searchedText, + setSearchedText, + } = useMetricsModal(); + const styles = useStyles2(getMetricsModalStyles); const placeholders = getPlaceholders(); const promTypes = getPromTypes(); - /** - * loads metrics and metadata on opening modal and switching off useBackend - */ - const updateMetricsMetadata = useCallback(async () => { - // *** Loading Gif - dispatch(setIsLoading(true)); - - // Because Combobox in MetricsCombobox doesn't use the same lifecycle as Select to open the Metrics Explorer - // it might not have loaded any metrics yet, so it instead passes in an async function to get the metrics - const metrics = typeof initialMetrics === 'function' ? await initialMetrics() : initialMetrics; - - const data: MetricsModalMetadata = await setMetrics(datasource, query, metrics); - dispatch( - buildMetrics({ - isLoading: false, - hasMetadata: data.hasMetadata, - metrics: data.metrics, - metaHaystackDictionary: data.metaHaystackDictionary, - nameHaystackDictionary: data.nameHaystackDictionary, - totalMetricCount: data.metrics.length, - filteredMetricCount: data.metrics.length, - }) - ); - }, [query, datasource, initialMetrics]); - - useEffect(() => { - updateMetricsMetadata(); - }, [updateMetricsMetadata]); - const typeOptions: SelectableValue[] = promTypes.map((t: PromFilterOption) => { return { value: t.value, @@ -110,96 +52,10 @@ export const MetricsModal = (props: MetricsModalProps) => { }; }); - /** - * The backend debounced search - */ - const debouncedBackendSearch = useMemo( - () => - debounce(async (metricText: string) => { - dispatch(setIsLoading(true)); - - const queryString = regexifyLabelValuesQueryString(metricText); - const filterArray = query.labels ? formatPrometheusLabelFilters(query.labels) : []; - const match = `{__name__=~".*${queryString}"${filterArray ? filterArray.join('') : ''}}`; - - const results = await datasource.languageProvider.queryLabelValues(timeRange, METRIC_LABEL, match); - - const resultsOptions = results.map((result) => ({ - value: result, - })); - - dispatch( - filterMetricsBackend({ - metrics: resultsOptions, - filteredMetricCount: resultsOptions.length, - isLoading: false, - }) - ); - }, getDebounceTimeInMilliseconds(datasource.cacheLevel)), - [datasource.cacheLevel, datasource.languageProvider, query.labels, timeRange] - ); - - function fuzzyNameDispatch(haystackData: string[][]) { - dispatch(setNameHaystack(haystackData)); - } - - function fuzzyMetaDispatch(haystackData: string[][]) { - dispatch(setMetaHaystack(haystackData)); - } - - function searchCallback(query: string, fullMetaSearchVal: boolean) { - if (state.useBackend && query === '') { - // get all metrics data if a user erases everything in the input - updateMetricsMetadata(); - } else if (state.useBackend) { - debouncedBackendSearch(query); - } else { - // search either the names or all metadata - // fuzzy search go! - if (fullMetaSearchVal) { - debouncedFuzzySearch(Object.keys(state.metaHaystackDictionary), query, fuzzyMetaDispatch); - } else { - debouncedFuzzySearch(Object.keys(state.nameHaystackDictionary), query, fuzzyNameDispatch); - } - } - } - - /* Settings switches */ - const additionalSettings = ( - { - const newVal = !state.fullMetaSearch; - dispatch(setFullMetaSearch(newVal)); - onChange({ ...query, fullMetaSearch: newVal }); - searchCallback(state.fuzzySearchQuery, newVal); - }} - onChangeIncludeNullMetadata={() => { - dispatch(setIncludeNullMetadata(!state.includeNullMetadata)); - onChange({ ...query, includeNullMetadata: !state.includeNullMetadata }); - }} - onChangeDisableTextWrap={() => { - dispatch(setDisableTextWrap()); - onChange({ ...query, disableTextWrap: !state.disableTextWrap }); - tracking('grafana_prom_metric_encycopedia_disable_text_wrap_interaction', state, ''); - }} - onChangeUseBackend={() => { - const newVal = !state.useBackend; - dispatch(setUseBackend(newVal)); - onChange({ ...query, useBackend: newVal }); - if (newVal === false) { - // rebuild the metrics metadata if we turn off useBackend - updateMetricsMetadata(); - } else { - // check if there is text in the browse search and update - if (state.fuzzySearchQuery !== '') { - debouncedBackendSearch(state.fuzzySearchQuery); - } - // otherwise wait for user typing - } - }} - /> - ); + const searchCallback = (query: string, fullMetaSearchVal?: boolean) => { + setSearchedText(query); + debouncedBackendSearch(timeRange, query); + }; return ( { autoFocus={true} data-testid={metricsModaltestIds.searchMetric} placeholder={placeholders.browse} - value={state.fuzzySearchQuery} + value={searchedText} onInput={(e) => { const value = e.currentTarget.value ?? ''; - dispatch(setFuzzySearchQuery(value)); - searchCallback(value, state.fullMetaSearch); + setSearchedText(value); + setPagination({ ...pagination, pageNum: 1 }); + searchCallback(value); }} /> - {state.hasMetadata && ( -
- dispatch(setSelectedTypes(v))} - /> -
- )} -
- -
- - - -
+
+
@@ -298,61 +123,23 @@ export const MetricsModal = (props: MetricsModalProps) => { )}
- {state.metrics && ( - - )} + {filteredMetricsData && }
-
- - Showing {'{{num}}'} of {'{{count}}'} results - -
{ - const page = val ?? 1; - dispatch(setPageNum(page)); - }} + currentPage={pagination.pageNum > pagination.totalPageNum ? 1 : pagination.pageNum} + numberOfPages={pagination.totalPageNum} + onNavigate={(val: number) => setPagination({ ...pagination, pageNum: val ?? 1 })} /> -
-

- Results per page -

- { - const value = +e.currentTarget.value; - - if (isNaN(value) || value >= MAXIMUM_RESULTS_PER_PAGE) { - return; - } - - dispatch(setResultsPerPage(value)); - }} - /> -
); }; + +export const MetricsModal = (props: MetricsModalProps) => { + return ( + + + + ); +}; diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModalContext.test.tsx b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModalContext.test.tsx new file mode 100644 index 00000000000..955b2c1b585 --- /dev/null +++ b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModalContext.test.tsx @@ -0,0 +1,329 @@ +import { act, render, renderHook, waitFor } from '@testing-library/react'; +import { ReactNode } from 'react'; + +import { TimeRange } from '@grafana/data'; + +import { PrometheusLanguageProviderInterface } from '../../../language_provider'; + +import { DEFAULT_RESULTS_PER_PAGE, MetricsModalContextProvider, useMetricsModal } from './MetricsModalContext'; +import { generateMetricData } from './helpers'; + +// Mock dependencies +jest.mock('./helpers', () => ({ + generateMetricData: jest.fn(), +})); + +const mockGenerateMetricData = generateMetricData as jest.MockedFunction; + +// Mock language provider +const mockLanguageProvider: PrometheusLanguageProviderInterface = { + queryMetricsMetadata: jest.fn(), + queryLabelValues: jest.fn(), + retrieveMetricsMetadata: jest.fn(), +} as unknown as PrometheusLanguageProviderInterface; + +// Helper to create wrapper component +const createWrapper = (languageProvider = mockLanguageProvider) => { + return ({ children }: { children: ReactNode }) => ( + {children} + ); +}; + +// Sample time range for tests +const defaultTimeRange: TimeRange = { + from: 'now-1h' as unknown as TimeRange['from'], + to: 'now' as unknown as TimeRange['to'], + raw: { + from: 'now-1h', + to: 'now', + }, +}; + +describe('MetricsModalContext', () => { + let consoleSpy: jest.SpyInstance; + + beforeEach(() => { + jest.clearAllMocks(); + // Mock console.error to suppress React act() warnings + consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + + // Default mock implementations + mockGenerateMetricData.mockImplementation((metric) => ({ + value: metric, + type: 'counter', + description: 'Test metric', + })); + (mockLanguageProvider.queryMetricsMetadata as jest.Mock).mockResolvedValue({ + test_metric: { type: 'counter', help: 'Test metric' }, + }); + }); + + afterEach(() => { + consoleSpy.mockRestore(); + }); + + describe('useMetricsModal hook', () => { + it('should throw error when used outside provider', () => { + expect(() => { + renderHook(() => useMetricsModal()); + }).toThrow('useMetricsModal must be used within a MetricsModalContextProvider'); + }); + + it('should provide context value when used within provider', () => { + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + expect(result.current).toBeDefined(); + expect(result.current.isLoading).toBe(true); // Initially loading + expect(result.current.filteredMetricsData).toEqual([]); + expect(result.current.pagination).toEqual({ + pageNum: 1, + totalPageNum: 1, + resultsPerPage: DEFAULT_RESULTS_PER_PAGE, + }); + expect(result.current.selectedTypes).toEqual([]); + expect(result.current.searchedText).toBe(''); + }); + }); + + describe('State management', () => { + it('should update pagination', () => { + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + const expectedPagination = { pageNum: 1, resultsPerPage: 50, totalPageNum: 1 }; + + act(() => { + result.current.setPagination({ pageNum: 2, resultsPerPage: 50, totalPageNum: 3 }); + }); + + expect(result.current.pagination).toEqual(expectedPagination); + }); + + it('should update selected types', () => { + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + const newTypes = [{ value: 'counter', label: 'Counter' }]; + + act(() => { + result.current.setSelectedTypes(newTypes); + }); + + expect(result.current.selectedTypes).toEqual(newTypes); + }); + + it('should update searched text', () => { + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + act(() => { + result.current.setSearchedText('test_metric'); + }); + + expect(result.current.searchedText).toBe('test_metric'); + }); + + it('should update loading state', () => { + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + act(() => { + result.current.setIsLoading(false); + }); + + expect(result.current.isLoading).toBe(false); + }); + }); + + describe('Metadata fetching', () => { + it('should load initial metadata on mount', async () => { + const mockMetadata = { + cpu_usage: { type: 'gauge', help: 'CPU usage percentage' }, + memory_usage: { type: 'gauge', help: 'Memory usage bytes' }, + }; + + (mockLanguageProvider.queryMetricsMetadata as jest.Mock).mockResolvedValue(mockMetadata); + + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + // Wait for metadata to load + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + expect(mockLanguageProvider.queryMetricsMetadata).toHaveBeenCalledWith(1000); + expect(mockGenerateMetricData).toHaveBeenCalledWith('cpu_usage', mockLanguageProvider); + expect(mockGenerateMetricData).toHaveBeenCalledWith('memory_usage', mockLanguageProvider); + expect(result.current.filteredMetricsData).toHaveLength(2); + }); + + it('should handle empty metadata response', async () => { + (mockLanguageProvider.queryMetricsMetadata as jest.Mock).mockResolvedValue({}); + + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + expect(result.current.filteredMetricsData).toEqual([]); + }); + + it('should handle metadata fetch error', async () => { + (mockLanguageProvider.queryMetricsMetadata as jest.Mock).mockRejectedValue(new Error('Network error')); + + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + expect(result.current.filteredMetricsData).toEqual([]); + }); + }); + + describe('Backend search', () => { + it('should perform backend search with results', async () => { + (mockLanguageProvider.queryLabelValues as jest.Mock).mockResolvedValue(['test_metric', 'other_metric']); + + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + await act(async () => { + await result.current.debouncedBackendSearch(defaultTimeRange, 'test'); + }); + + expect(mockLanguageProvider.queryLabelValues).toHaveBeenCalledWith( + defaultTimeRange, + '__name__', + '{__name__=~"(?i).*test.*"}' + ); + expect(result.current.filteredMetricsData).toHaveLength(1); + }); + + it('should handle backend search error', async () => { + (mockLanguageProvider.queryLabelValues as jest.Mock).mockRejectedValue(new Error('Search failed')); + + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + await act(async () => { + await result.current.debouncedBackendSearch(defaultTimeRange, 'test'); + }); + + expect(result.current.filteredMetricsData).toEqual([]); + expect(result.current.isLoading).toBe(false); + }); + }); + + describe('Filtering logic', () => { + it('should return all metrics when no types are selected', async () => { + mockGenerateMetricData.mockImplementation((metric) => ({ + value: metric, + type: 'counter', + description: 'Test metric', + })); + + (mockLanguageProvider.queryMetricsMetadata as jest.Mock).mockResolvedValue({ + test_metric: { type: 'counter', help: 'Test metric' }, + }); + + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + expect(result.current.filteredMetricsData).toHaveLength(1); + expect(result.current.selectedTypes).toEqual([]); + }); + + it('should filter metrics by selected type', async () => { + mockGenerateMetricData.mockImplementation((metric) => ({ + value: metric, + type: metric === 'counter_metric' ? 'counter' : 'gauge', + description: 'Test metric', + })); + + (mockLanguageProvider.queryMetricsMetadata as jest.Mock).mockResolvedValue({ + counter_metric: { type: 'counter', help: 'Counter metric' }, + gauge_metric: { type: 'gauge', help: 'Gauge metric' }, + }); + + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + act(() => { + result.current.setSelectedTypes([{ value: 'counter', label: 'Counter' }]); + }); + + expect(result.current.filteredMetricsData).toHaveLength(1); + expect(result.current.filteredMetricsData[0].value).toBe('counter_metric'); + }); + + it('should handle metrics without type when "no type" is selected', async () => { + mockGenerateMetricData.mockImplementation((metric) => ({ + value: metric, + type: metric === 'no_type_metric' ? undefined : 'counter', + description: 'Test metric', + })); + + (mockLanguageProvider.queryMetricsMetadata as jest.Mock).mockResolvedValue({ + counter_metric: { type: 'counter', help: 'Counter metric' }, + no_type_metric: { help: 'Metric without type' }, + }); + + const { result } = renderHook(() => useMetricsModal(), { + wrapper: createWrapper(), + }); + + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + }); + + act(() => { + result.current.setSelectedTypes([{ value: 'no type', label: 'No Type' }]); + }); + + expect(result.current.filteredMetricsData).toHaveLength(1); + expect(result.current.filteredMetricsData[0].value).toBe('no_type_metric'); + }); + }); + + describe('Component integration', () => { + it('should render provider without errors', () => { + const TestComponent = () => { + return
frontend
; + }; + + const { getByTestId } = render( + + + + ); + + expect(getByTestId('test')).toHaveTextContent('frontend'); + }); + }); +}); diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModalContext.tsx b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModalContext.tsx new file mode 100644 index 00000000000..3361b448547 --- /dev/null +++ b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/MetricsModalContext.tsx @@ -0,0 +1,201 @@ +import debounce from 'debounce-promise'; +import { + createContext, + FC, + PropsWithChildren, + useCallback, + useContext, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; + +import { SelectableValue, TimeRange } from '@grafana/data'; + +import { METRIC_LABEL, PROMETHEUS_QUERY_BUILDER_MAX_RESULTS } from '../../../constants'; +import { PrometheusLanguageProviderInterface } from '../../../language_provider'; +import { regexifyLabelValuesQueryString } from '../../parsingUtils'; +import { QueryBuilderLabelFilter } from '../../shared/types'; +import { formatPrometheusLabelFilters } from '../formatter'; + +import { generateMetricData } from './helpers'; +import { MetricData, MetricsData } from './types'; +import { fuzzySearch } from './uFuzzy'; + +export const DEFAULT_RESULTS_PER_PAGE = 25; + +type Pagination = { + pageNum: number; + resultsPerPage: number; + totalPageNum: number; +}; + +type MetricsModalContextValue = { + isLoading: boolean; + setIsLoading: (val: boolean) => void; + filteredMetricsData: MetricData[]; + debouncedBackendSearch: ( + timeRange: TimeRange, + metricText: string, + queryLabels?: QueryBuilderLabelFilter[] + ) => Promise; + pagination: Pagination; + setPagination: (val: Pagination) => void; + selectedTypes: Array>; + setSelectedTypes: (val: Array>) => void; + searchedText: string; + setSearchedText: (val: string) => void; +}; + +const MetricsModalContext = createContext(undefined); + +type MetricsModalContextProviderProps = { + languageProvider: PrometheusLanguageProviderInterface; +}; + +export const MetricsModalContextProvider: FC> = ({ + children, + languageProvider, +}) => { + const [isLoading, setIsLoading] = useState(true); + const [metricsData, setMetricsData] = useState([]); + const [pagination, setPagination] = useState({ + pageNum: 1, + totalPageNum: 1, + resultsPerPage: DEFAULT_RESULTS_PER_PAGE, + }); + const [selectedTypes, setSelectedTypes] = useState>>([]); + const [searchedText, setSearchedText] = useState(''); + + const filteredMetricsData = useMemo(() => { + if (selectedTypes.length === 0) { + return metricsData; + } + + // Filter metrics based on selected types + return metricsData.filter((metric: MetricData) => { + return selectedTypes.some((selectedType) => { + // Handle metrics with defined types + if (metric.type && selectedType.value) { + return metric.type.includes(selectedType.value); + } + + // Handle metrics without type when "no type" is selected + if (!metric.type && selectedType.value === 'no type') { + return true; + } + + return false; + }); + }); + }, [metricsData, selectedTypes]); + + useEffect(() => { + const totalPageNum = + filteredMetricsData.length === 0 ? 1 : Math.ceil(filteredMetricsData.length / pagination.resultsPerPage); + const pageNum = pagination.pageNum > totalPageNum ? 1 : pagination.pageNum; + + setPagination((prevPagination) => ({ + ...prevPagination, + totalPageNum, + pageNum, + })); + }, [filteredMetricsData.length, pagination.resultsPerPage, pagination.pageNum]); + + // Track the latest search ID to handle race conditions + const latestSearchIdRef = useRef(0); + + const fetchMetadata = useCallback(async () => { + try { + setIsLoading(true); + const metadata = await languageProvider.queryMetricsMetadata(PROMETHEUS_QUERY_BUILDER_MAX_RESULTS); + + if (Object.keys(metadata).length === 0) { + setMetricsData([]); + } else { + const processedData = Object.keys(metadata).map((m) => generateMetricData(m, languageProvider)); + setMetricsData(processedData); + } + } catch (error) { + setMetricsData([]); + } finally { + setIsLoading(false); + } + }, [languageProvider]); + + const debouncedBackendSearch = useMemo( + () => + debounce(async (timeRange: TimeRange, metricText: string, queryLabels?: QueryBuilderLabelFilter[]) => { + // Generate unique search ID to handle race conditions + const searchId = ++latestSearchIdRef.current; + + try { + if (metricText === '') { + await fetchMetadata(); + return; + } + + setIsLoading(true); + + const queryString = regexifyLabelValuesQueryString(metricText); + const filterArray = queryLabels ? formatPrometheusLabelFilters(queryLabels) : []; + const match = `{__name__=~"(?i).*${queryString}"${filterArray ? filterArray.join('') : ''}}`; + + const results = await languageProvider.queryLabelValues(timeRange, METRIC_LABEL, match); + + // Check if this is still the most recent search + if (searchId !== latestSearchIdRef.current) { + return; // Ignore outdated results + } + + const [fuzzyOrderedMetrics] = fuzzySearch(results, queryString); + const resultsOptions: MetricsData = fuzzyOrderedMetrics.map((m) => generateMetricData(m, languageProvider)); + + setMetricsData(resultsOptions); + setIsLoading(false); + } catch (error) { + // Only update state if this is still the latest search + if (searchId === latestSearchIdRef.current) { + console.error('Backend search failed:', error); + setMetricsData([]); // Clear results on error + setIsLoading(false); + } + } + }, 300), + [fetchMetadata, languageProvider] + ); + + useEffect(() => { + fetchMetadata(); + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( + + {children} + + ); +}; + +export function useMetricsModal() { + const context = useContext(MetricsModalContext); + if (context === undefined) { + throw new Error('useMetricsModal must be used within a MetricsModalContextProvider'); + } + return context; +} diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/ResultsTable.tsx b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/ResultsTable.tsx index 1e179d336ee..3f3a1bf5afc 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/ResultsTable.tsx +++ b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/ResultsTable.tsx @@ -1,65 +1,62 @@ // Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/components/metrics-modal/ResultsTable.tsx -import { css } from '@emotion/css'; -import { ReactElement } from 'react'; +import { ReactElement, useMemo } from 'react'; import Highlighter from 'react-highlight-words'; -import { GrafanaTheme2 } from '@grafana/data'; import { t, Trans } from '@grafana/i18n'; -import { Button, Icon, Tooltip, useTheme2 } from '@grafana/ui'; +import { Icon, Tooltip, useStyles2 } from '@grafana/ui'; import { docsTip } from '../../../configuration/shared/utils'; import { PromVisualQuery } from '../../types'; -import { tracking } from './state/helpers'; -import { MetricsModalState } from './state/state'; -import { MetricData, MetricsData } from './types'; +import { useMetricsModal } from './MetricsModalContext'; +import { getResultsTableStyles } from './styles'; +import { MetricData } from './types'; type ResultsTableProps = { - metrics: MetricsData; onChange: (query: PromVisualQuery) => void; onClose: () => void; query: PromVisualQuery; - state: MetricsModalState; - disableTextWrap: boolean; }; export function ResultsTable(props: ResultsTableProps) { - const { metrics, onChange, onClose, query, state, disableTextWrap } = props; + const { onChange, onClose, query } = props; + const { + isLoading, + filteredMetricsData, + pagination: { pageNum, resultsPerPage }, + selectedTypes, + searchedText, + } = useMetricsModal(); - const theme = useTheme2(); - const styles = getStyles(theme, disableTextWrap); + const slicedMetrics = useMemo(() => { + const startIndex = (pageNum - 1) * resultsPerPage; + const endIndex = startIndex + resultsPerPage; + return filteredMetricsData.slice(startIndex, endIndex); + }, [filteredMetricsData, pageNum, resultsPerPage]); + + const styles = useStyles2(getResultsTableStyles); function selectMetric(metric: MetricData) { if (metric.value) { onChange({ ...query, metric: metric.value }); - tracking('grafana_prom_metric_encycopedia_tracking', state, metric.value); onClose(); } } function metaRows(metric: MetricData) { - if (state.fullMetaSearch && metric) { - return ( - <> - {displayType(metric.type ?? '')} - - - - - ); - } else { - return ( - <> - {displayType(metric.type ?? '')} - {metric.description ?? ''} - - ); - } + return ( + <> + {displayType(metric.type ?? '')} + + + + + ); } function addHelpIcon(fullType: string, descriptiveType: string, link: string) { @@ -105,7 +102,7 @@ export function ResultsTable(props: ResultsTableProps) { function noMetricsMessages(): ReactElement { let message; - if (!state.fuzzySearchQuery) { + if (!searchedText) { message = t( 'grafana-prometheus.querybuilder.results-table.message-no-metrics-found', 'There are no metrics found in the data source.' @@ -119,7 +116,7 @@ export function ResultsTable(props: ResultsTableProps) { ); } - if (state.fuzzySearchQuery || state.selectedTypes.length > 0) { + if (searchedText || selectedTypes.length > 0) { message = t( 'grafana-prometheus.querybuilder.results-table.message-expand-search', 'There are no metrics found. Try to expand your search and filters.' @@ -133,21 +130,6 @@ export function ResultsTable(props: ResultsTableProps) { ); } - function textHighlight(state: MetricsModalState) { - if (state.useBackend) { - // highlight the input only for the backend search - // this highlight is equivalent to how the metric select highlights - // look into matching on regex input - return [state.fuzzySearchQuery]; - } else if (state.fullMetaSearch) { - // highlight the matches in the ufuzzy metaHaystack - return state.metaHaystackMatches; - } else { - // highlight the ufuzzy name matches - return state.nameHaystackMatches; - } - } - return ( @@ -155,115 +137,35 @@ export function ResultsTable(props: ResultsTableProps) { - {state.hasMetadata && ( - <> - - - - )} - + + <> - {metrics.length > 0 && - metrics.map((metric: MetricData, idx: number) => { + {slicedMetrics.length > 0 && + slicedMetrics.map((metric: MetricData, idx: number) => { return ( - + selectMetric(metric)}> - {state.hasMetadata && metaRows(metric)} - + {metaRows(metric)} ); })} - {metrics.length === 0 && !state.isLoading && noMetricsMessages()} + {slicedMetrics.length === 0 && !isLoading && noMetricsMessages()}
Name - Type - - Description - + Type + + Description +
- -
); } - -const getStyles = (theme: GrafanaTheme2, disableTextWrap: boolean) => { - return { - table: css({ - tableLayout: disableTextWrap ? undefined : 'fixed', - borderRadius: theme.shape.radius.default, - width: '100%', - whiteSpace: disableTextWrap ? 'nowrap' : 'normal', - td: { - padding: theme.spacing(1), - }, - 'td,th': { - minWidth: theme.spacing(3), - borderBottom: `1px solid ${theme.colors.border.weak}`, - }, - }), - row: css({ - label: 'row', - borderBottom: `1px solid ${theme.colors.border.weak}`, - '&:last-child': { - borderBottom: 0, - }, - }), - tableHeaderPadding: css({ - padding: '8px', - }), - matchHighLight: css({ - background: 'inherit', - color: theme.components.textHighlight.text, - backgroundColor: theme.components.textHighlight.background, - }), - nameWidth: css({ - width: disableTextWrap ? undefined : '37.5%', - }), - nameOverflow: css({ - overflowWrap: disableTextWrap ? undefined : 'anywhere', - }), - typeWidth: css({ - width: disableTextWrap ? undefined : '15%', - }), - descriptionWidth: css({ - width: disableTextWrap ? undefined : '35%', - }), - selectButtonWidth: css({ - width: disableTextWrap ? undefined : '12.5%', - }), - stickyHeader: css({ - position: 'sticky', - top: 0, - backgroundColor: theme.colors.background.primary, - }), - noResults: css({ - textAlign: 'center', - color: theme.colors.text.secondary, - }), - tooltipSpace: css({ - marginLeft: '4px', - }), - centerButton: css({ - display: 'block', - margin: 'auto', - border: 'none', - }), - }; -}; diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/helpers.test.ts b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/helpers.test.ts new file mode 100644 index 00000000000..d3998e46de0 --- /dev/null +++ b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/helpers.test.ts @@ -0,0 +1,313 @@ +import { PrometheusLanguageProviderInterface } from '../../../language_provider'; +import { PromMetricsMetadata } from '../../../types'; + +import { calculatePageList, generateMetricData, getPlaceholders, getPromTypes } from './helpers'; +import { MetricsData } from './types'; + +// Mock the language provider +const createMockLanguageProvider = (metadata: PromMetricsMetadata = {}): PrometheusLanguageProviderInterface => + ({ + retrieveMetricsMetadata: jest.fn().mockReturnValue(metadata), + }) as unknown as PrometheusLanguageProviderInterface; + +describe('helpers.ts', () => { + describe('generateMetricData', () => { + it('should generate basic metric data', () => { + const mockProvider = createMockLanguageProvider({ + test_metric: { + type: 'counter', + help: 'Test counter metric', + }, + }); + + const result = generateMetricData('test_metric', mockProvider); + + expect(result).toEqual({ + value: 'test_metric', + type: 'counter', + description: 'Test counter metric', + }); + }); + + it('should handle metric with no metadata', () => { + const mockProvider = createMockLanguageProvider({}); + + const result = generateMetricData('unknown_metric', mockProvider); + + expect(result).toEqual({ + value: 'unknown_metric', + type: undefined, + description: undefined, + }); + }); + + it('should enhance type based on description for histogram', () => { + const mockProvider = createMockLanguageProvider({ + test_metric: { + type: 'gauge', + help: 'This is a histogram metric for testing', + }, + }); + + const result = generateMetricData('test_metric', mockProvider); + + expect(result.type).toBe('gauge (histogram)'); + }); + + it('should enhance type based on description for summary', () => { + const mockProvider = createMockLanguageProvider({ + test_metric: { + type: 'counter', + help: 'This is a summary metric for testing', + }, + }); + + const result = generateMetricData('test_metric', mockProvider); + + expect(result.type).toBe('counter (summary)'); + }); + + it('should not enhance type if already matches description', () => { + const mockProvider = createMockLanguageProvider({ + test_metric: { + type: 'histogram', + help: 'This is a histogram metric for testing', + }, + }); + + const result = generateMetricData('test_metric', mockProvider); + + expect(result.type).toBe('native histogram'); // Should be native histogram, not enhanced + }); + + it('should detect native histogram vs classic histogram', () => { + const mockProvider = createMockLanguageProvider({ + native_histogram: { + type: 'histogram', + help: 'Native histogram', + }, + classic_bucket: { + type: 'histogram', + help: 'Classic histogram', + }, + classic_bucket_with_labels: { + type: 'histogram', + help: 'Classic histogram with labels', + }, + }); + + // Native histogram (no _bucket suffix) + const nativeResult = generateMetricData('native_histogram', mockProvider); + expect(nativeResult.type).toBe('native histogram'); + + // Classic histogram (with _bucket suffix) + const classicResult = generateMetricData('classic_bucket', mockProvider); + expect(classicResult.type).toBe('histogram'); + + // Classic histogram with labels + const classicWithLabelsResult = generateMetricData('classic_bucket_with_labels', mockProvider); + expect(classicWithLabelsResult.type).toBe('native histogram'); // No _bucket pattern match + }); + + it('should handle old histogram pattern matching', () => { + const mockProvider = createMockLanguageProvider({ + test_bucket: { type: 'histogram', help: 'Test bucket metric' }, + 'test_bucket{le="0.1"}': { type: 'histogram', help: 'Test bucket with labels' }, + test_histogram: { type: 'histogram', help: 'Test histogram metric' }, + }); + + // Should be classic histogram (matches pattern) + expect(generateMetricData('test_bucket', mockProvider).type).toBe('histogram'); + expect(generateMetricData('test_bucket{le="0.1"}', mockProvider).type).toBe('histogram'); + + // Should be native histogram (doesn't match pattern) + expect(generateMetricData('test_histogram', mockProvider).type).toBe('native histogram'); + }); + + it('should handle case-insensitive description matching', () => { + const mockProvider = createMockLanguageProvider({ + test_metric: { + type: 'gauge', + help: 'This is a HISTOGRAM metric for testing', + }, + }); + + const result = generateMetricData('test_metric', mockProvider); + expect(result.type).toBe('gauge (histogram)'); + }); + + it('should handle empty type with description enhancement', () => { + const mockProvider = createMockLanguageProvider({ + test_metric: { + type: '', + help: 'This is a histogram metric for testing', + }, + }); + + const result = generateMetricData('test_metric', mockProvider); + expect(result.type).toBe('native histogram'); + }); + + it('should handle empty description', () => { + const mockProvider = createMockLanguageProvider({ + test_metric: { + type: 'gauge', + help: '', + }, + }); + + const result = generateMetricData('test_metric', mockProvider); + expect(result.type).toBe('gauge'); + }); + }); + + describe('calculatePageList', () => { + const createMetricsData = (length: number): MetricsData => + Array.from({ length }, (_, i) => ({ value: `metric_${i}` })); + + it('should return empty array for empty metrics data', () => { + expect(calculatePageList([], 10)).toEqual([]); + }); + + it('should return [1] for zero or negative results per page', () => { + const metricsData = createMetricsData(5); + expect(calculatePageList(metricsData, 0)).toEqual([1]); + expect(calculatePageList(metricsData, -5)).toEqual([1]); + }); + + it('should calculate correct page list for exact division', () => { + const metricsData = createMetricsData(20); + const result = calculatePageList(metricsData, 10); + expect(result).toEqual([1, 2]); + }); + + it('should calculate correct page list for non-exact division', () => { + const metricsData = createMetricsData(23); + const result = calculatePageList(metricsData, 10); + expect(result).toEqual([1, 2, 3]); + }); + + it('should handle single page scenario', () => { + const metricsData = createMetricsData(5); + const result = calculatePageList(metricsData, 10); + expect(result).toEqual([1]); + }); + + it('should handle very large datasets', () => { + const metricsData = createMetricsData(1000); + const result = calculatePageList(metricsData, 25); + expect(result).toHaveLength(40); + expect(result[0]).toBe(1); + expect(result[result.length - 1]).toBe(40); + }); + + it('should handle single item per page', () => { + const metricsData = createMetricsData(3); + const result = calculatePageList(metricsData, 1); + expect(result).toEqual([1, 2, 3]); + }); + + it('should handle fractional results per page', () => { + const metricsData = createMetricsData(10); + expect(calculatePageList(metricsData, 3.5)).toEqual([1, 2, 3]); + }); + }); + + describe('getPromTypes', () => { + it('should return array of Prometheus types', () => { + const types = getPromTypes(); + + expect(Array.isArray(types)).toBe(true); + expect(types.length).toBe(7); + + const expectedValues = ['counter', 'gauge', 'histogram', 'native histogram', 'summary', 'unknown', 'no type']; + const actualValues = types.map((type) => type.value); + + expect(actualValues).toEqual(expectedValues); + }); + + it('should have correct structure for each type', () => { + const types = getPromTypes(); + + types.forEach((type) => { + expect(type).toHaveProperty('value'); + expect(type).toHaveProperty('label'); + expect(type).toHaveProperty('description'); + + expect(typeof type.value).toBe('string'); + expect(typeof type.label).toBe('string'); + expect(typeof type.description).toBe('string'); + + expect(type.value.length).toBeGreaterThan(0); + expect(type.label.length).toBeGreaterThan(0); + expect(type.description.length).toBeGreaterThan(0); + }); + }); + + it('should return consistent results on multiple calls', () => { + const types1 = getPromTypes(); + const types2 = getPromTypes(); + + expect(types1).toEqual(types2); + }); + + it('should have unique values', () => { + const types = getPromTypes(); + const values = types.map((type) => type.value); + const uniqueValues = [...new Set(values)]; + + expect(values.length).toBe(uniqueValues.length); + }); + + it('should have descriptive labels', () => { + const types = getPromTypes(); + + types.forEach((type) => { + expect(type.label).not.toBe(type.value); + expect(type.label.length).toBeGreaterThanOrEqual(type.value.length); + }); + }); + }); + + describe('getPlaceholders', () => { + it('should return object with all required placeholders', () => { + const placeholders = getPlaceholders(); + + const expectedKeys = ['browse', 'filterType']; + + expect(Object.keys(placeholders)).toEqual(expectedKeys); + }); + + it('should have string values for all placeholders', () => { + const placeholders = getPlaceholders(); + + Object.values(placeholders).forEach((placeholder) => { + expect(typeof placeholder).toBe('string'); + expect(placeholder.length).toBeGreaterThan(0); + }); + }); + + it('should return consistent results on multiple calls', () => { + const placeholders1 = getPlaceholders(); + const placeholders2 = getPlaceholders(); + + expect(placeholders1).toEqual(placeholders2); + }); + + it('should contain expected placeholder content', () => { + const placeholders = getPlaceholders(); + + expect(placeholders.browse).toMatch(/search/i); + expect(placeholders.filterType).toMatch(/type/i); + }); + + it('should have descriptive placeholder text', () => { + const placeholders = getPlaceholders(); + + Object.values(placeholders).forEach((placeholder) => { + expect(placeholder.length).toBeGreaterThan(5); + expect(placeholder).toMatch(/[a-zA-Z]/); + }); + }); + }); +}); diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/helpers.ts b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/helpers.ts new file mode 100644 index 00000000000..9377a22e5e0 --- /dev/null +++ b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/helpers.ts @@ -0,0 +1,123 @@ +// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/components/metrics-modal/state/helpers.ts +import { t } from '@grafana/i18n'; + +import { PrometheusLanguageProviderInterface } from '../../../language_provider'; + +import { MetricData, MetricsData, PromFilterOption } from './types'; + +// Constants +const HISTOGRAM_TYPES = ['histogram', 'summary'] as const; +const OLD_HISTOGRAM_PATTERN = /^\w+_bucket$|^\w+_bucket{.*}$/; +const HISTOGRAM_TYPE = 'histogram'; +const NATIVE_HISTOGRAM_TYPE = 'native histogram'; + +/** + * Builds the metric data object with type and description + * @param metric - The metric name + * @param languageProvider - The Prometheus language provider interface + * @returns MetricData object with value, type, and description + */ +export const generateMetricData = ( + metric: string, + languageProvider: PrometheusLanguageProviderInterface +): MetricData => { + const metadata = languageProvider.retrieveMetricsMetadata(); + + let type = metadata[metric]?.type; + const description = metadata[metric]?.help; + + HISTOGRAM_TYPES.forEach((t) => { + if (description?.toLowerCase().includes(t) && type !== t) { + type = type ? `${type} (${t})` : t; + } + }); + + const oldHistogramMatch = metric.match(OLD_HISTOGRAM_PATTERN); + + if (type === HISTOGRAM_TYPE && !oldHistogramMatch) { + type = NATIVE_HISTOGRAM_TYPE; + } + + return { + value: metric, + type: type, + description: description, + }; +}; + +export function calculatePageList(metricsData: MetricsData, resultsPerPage: number): number[] { + if (!Array.isArray(metricsData) || metricsData.length === 0) { + return []; + } + + if (resultsPerPage <= 0) { + return [1]; + } + + const totalPages = Math.ceil(metricsData.length / resultsPerPage); + return Array.from({ length: totalPages }, (_, i) => i + 1); +} + +export const getPromTypes: () => PromFilterOption[] = () => [ + { + value: 'counter', + label: t('grafana-prometheus.querybuilder.get-prom-types.label-counter', 'Counter'), + description: t( + 'grafana-prometheus.querybuilder.get-prom-types.description-counter', + 'A cumulative metric that represents a single monotonically increasing counter whose value can only increase or be reset to zero on restart.' + ), + }, + { + value: 'gauge', + label: t('grafana-prometheus.querybuilder.get-prom-types.label-gauge', 'Gauge'), + description: t( + 'grafana-prometheus.querybuilder.get-prom-types.description-gauge', + 'A metric that represents a single numerical value that can arbitrarily go up and down.' + ), + }, + { + value: 'histogram', + label: t('grafana-prometheus.querybuilder.get-prom-types.label-histogram', 'Histogram'), + description: t( + 'grafana-prometheus.querybuilder.get-prom-types.description-histogram', + 'A histogram samples observations (usually things like request durations or response sizes) and counts them in configurable buckets.' + ), + }, + { + value: 'native histogram', + label: t('grafana-prometheus.querybuilder.get-prom-types.label-native-histogram', 'Native histogram'), + description: t( + 'grafana-prometheus.querybuilder.get-prom-types.description-native-histogram', + 'Native histograms are different from classic Prometheus histograms in a number of ways: Native histogram bucket boundaries are calculated by a formula that depends on the scale (resolution) of the native histogram, and are not user defined.' + ), + }, + { + value: 'summary', + label: t('grafana-prometheus.querybuilder.get-prom-types.label-summary', 'Summary'), + description: t( + 'grafana-prometheus.querybuilder.get-prom-types.description-summary', + 'A summary samples observations (usually things like request durations and response sizes) and can calculate configurable quantiles over a sliding time window.' + ), + }, + { + value: 'unknown', + label: t('grafana-prometheus.querybuilder.get-prom-types.label-unknown', 'Unknown'), + description: t( + 'grafana-prometheus.querybuilder.get-prom-types.description-unknown', + 'These metrics have been given the type unknown in the metadata.' + ), + }, + { + value: 'no type', + label: t('grafana-prometheus.querybuilder.get-prom-types.label-no-type', 'No type'), + description: t( + 'grafana-prometheus.querybuilder.get-prom-types.description-no-type', + 'These metrics have no defined type in the metadata.' + ), + }, +]; + +export const getPlaceholders = () => ({ + browse: t('grafana-prometheus.querybuilder.get-placeholders.browse', 'Search metrics by name'), + filterType: t('grafana-prometheus.querybuilder.get-placeholders.type', 'Filter by type'), +}); diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/shared/types.ts b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/shared/types.ts deleted file mode 100644 index 76ee015c1e9..00000000000 --- a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/shared/types.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { TimeRange } from '@grafana/data'; - -import { PrometheusDatasource } from '../../../../datasource'; -import { PromVisualQuery } from '../../../types'; - -interface MetricsModalState { - useBackend: boolean; - disableTextWrap: boolean; - includeNullMetadata: boolean; - fullMetaSearch: boolean; - hasMetadata: boolean; -} - -export interface MetricsModalProps { - datasource: PrometheusDatasource; - isOpen: boolean; - query: PromVisualQuery; - onClose: () => void; - onChange: (query: PromVisualQuery) => void; - initialMetrics: string[] | (() => Promise); - timeRange: TimeRange; -} - -export interface AdditionalSettingsProps { - state: MetricsModalState; - onChangeFullMetaSearch: () => void; - onChangeIncludeNullMetadata: () => void; - onChangeDisableTextWrap: () => void; - onChangeUseBackend: () => void; -} diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/state/helpers.ts b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/state/helpers.ts deleted file mode 100644 index 79d41287197..00000000000 --- a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/state/helpers.ts +++ /dev/null @@ -1,278 +0,0 @@ -// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/components/metrics-modal/state/helpers.ts -import { AnyAction } from '@reduxjs/toolkit'; - -import { t } from '@grafana/i18n'; -import { reportInteraction } from '@grafana/runtime'; - -import { PrometheusDatasource } from '../../../../datasource'; -import { PromMetricsMetadata } from '../../../../types'; -import { PromVisualQuery } from '../../../types'; -import { HaystackDictionary, MetricData, MetricsData, PromFilterOption } from '../types'; - -import { MetricsModalMetadata, MetricsModalState, setFilteredMetricCount } from './state'; - -export async function setMetrics( - datasource: PrometheusDatasource, - query: PromVisualQuery, - initialMetrics?: string[] -): Promise { - // metadata is set in the metric select now - // use this to disable metadata search and display - let hasMetadata = true; - const metadata = datasource.languageProvider.retrieveMetricsMetadata(); - if (metadata && Object.keys(metadata).length === 0) { - hasMetadata = false; - } - - let nameHaystackDictionaryData: HaystackDictionary = {}; - let metaHaystackDictionaryData: HaystackDictionary = {}; - - // pass in metrics from getMetrics in the query builder, reduced in the metric select - let metricsData: MetricsData | undefined; - - metricsData = initialMetrics?.map((m: string) => { - const metricData = buildMetricData(m, datasource); - - const metaDataString = `${m}¦${metricData.description}`; - - nameHaystackDictionaryData[m] = metricData; - metaHaystackDictionaryData[metaDataString] = metricData; - - return metricData; - }); - - return { - isLoading: false, - hasMetadata: hasMetadata, - metrics: metricsData ?? [], - metaHaystackDictionary: metaHaystackDictionaryData, - nameHaystackDictionary: nameHaystackDictionaryData, - totalMetricCount: metricsData?.length ?? 0, - filteredMetricCount: metricsData?.length ?? 0, - }; -} - -/** - * Builds the metric data object with type and description - * - * @param metric The metric name - * @param datasource The Prometheus datasource for mapping metradata to the metric name - * @returns A MetricData object. - */ -function buildMetricData(metric: string, datasource: PrometheusDatasource): MetricData { - let type = getMetadataType(metric, datasource.languageProvider.retrieveMetricsMetadata()); - - const description = getMetadataHelp(metric, datasource.languageProvider.retrieveMetricsMetadata()); - - ['histogram', 'summary'].forEach((t) => { - if (description?.toLowerCase().includes(t) && type !== t) { - type += ` (${t})`; - } - }); - - const oldHistogramMatch = metric.match(/^\w+_bucket$|^\w+_bucket{.*}$/); - - if (type === 'histogram' && !oldHistogramMatch) { - type = 'native histogram'; - } - - const metricData: MetricData = { - value: metric, - type: type, - description: description, - }; - - return metricData; -} - -function getMetadataHelp(metric: string, metadata: PromMetricsMetadata): string | undefined { - return metadata[metric]?.help; -} - -function getMetadataType(metric: string, metadata: PromMetricsMetadata): string | undefined { - return metadata[metric]?.type; -} - -/** - * The filtered and paginated metrics displayed in the modal - * */ -export function displayedMetrics(state: MetricsModalState, dispatch: React.Dispatch) { - const filteredSorted: MetricsData = filterMetrics(state); - - if (!state.isLoading && state.filteredMetricCount !== filteredSorted.length) { - dispatch(setFilteredMetricCount(filteredSorted.length)); - } - - return sliceMetrics(filteredSorted, state.pageNum, state.resultsPerPage); -} - -/** - * Filter the metrics with all the options, fuzzy, type, null metadata - */ -function filterMetrics(state: MetricsModalState): MetricsData { - let filteredMetrics: MetricsData = state.metrics; - - if (state.fuzzySearchQuery && !state.useBackend) { - if (state.fullMetaSearch) { - filteredMetrics = state.metaHaystackOrder.map((needle: string) => state.metaHaystackDictionary[needle]); - } else { - filteredMetrics = state.nameHaystackOrder.map((needle: string) => state.nameHaystackDictionary[needle]); - } - } - - if (state.selectedTypes.length > 0) { - filteredMetrics = filteredMetrics.filter((m: MetricData, idx) => { - // Matches type - const matchesSelectedType = state.selectedTypes.some((t) => { - if (m.type && t.value) { - return m.type.includes(t.value); - } - - if (!m.type && t.value === 'no type') { - return true; - } - - return false; - }); - - // when a user filters for type, only return metrics with defined types - return matchesSelectedType; - }); - } - - if (!state.includeNullMetadata) { - filteredMetrics = filteredMetrics.filter((m: MetricData) => { - return m.type !== undefined && m.description !== undefined; - }); - } - - return filteredMetrics; -} - -export function calculatePageList(state: MetricsModalState) { - if (!state.metrics.length) { - return []; - } - - const calcResultsPerPage: number = state.resultsPerPage === 0 ? 1 : state.resultsPerPage; - - const pages = Math.floor(filterMetrics(state).length / calcResultsPerPage) + 1; - - return [...Array(pages).keys()].map((i) => i + 1); -} - -function sliceMetrics(metrics: MetricsData, pageNum: number, resultsPerPage: number) { - const calcResultsPerPage: number = resultsPerPage === 0 ? 1 : resultsPerPage; - const start: number = pageNum === 1 ? 0 : (pageNum - 1) * calcResultsPerPage; - const end: number = start + calcResultsPerPage; - return metrics.slice(start, end); -} - -export const calculateResultsPerPage = (results: number, defaultResults: number, max: number) => { - if (results < 1) { - return 1; - } - - if (results > max) { - return max; - } - - return results ?? defaultResults; -}; - -export function tracking(event: string, state?: MetricsModalState | null, metric?: string, query?: PromVisualQuery) { - switch (event) { - case 'grafana_prom_metric_encycopedia_tracking': - reportInteraction(event, { - metric: metric, - hasMetadata: state?.hasMetadata, - totalMetricCount: state?.totalMetricCount, - fuzzySearchQuery: state?.fuzzySearchQuery, - fullMetaSearch: state?.fullMetaSearch, - selectedTypes: state?.selectedTypes, - useRegexSearch: state?.useBackend, - includeResultsWithoutMetadata: state?.includeNullMetadata, - }); - case 'grafana_prom_metric_encycopedia_disable_text_wrap_interaction': - reportInteraction(event, { - disableTextWrap: state?.disableTextWrap, - }); - case 'grafana_prometheus_metric_encyclopedia_open': - reportInteraction(event, { - query: query, - }); - } -} - -export const getPromTypes: () => PromFilterOption[] = () => [ - { - value: 'counter', - label: t('grafana-prometheus.querybuilder.get-prom-types.label-counter', 'Counter'), - description: t( - 'grafana-prometheus.querybuilder.get-prom-types.description-counter', - 'A cumulative metric that represents a single monotonically increasing counter whose value can only increase or be reset to zero on restart.' - ), - }, - { - value: 'gauge', - label: t('grafana-prometheus.querybuilder.get-prom-types.label-gauge', 'Gauge'), - description: t( - 'grafana-prometheus.querybuilder.get-prom-types.description-gauge', - 'A metric that represents a single numerical value that can arbitrarily go up and down.' - ), - }, - { - value: 'histogram', - label: t('grafana-prometheus.querybuilder.get-prom-types.label-histogram', 'Histogram'), - description: t( - 'grafana-prometheus.querybuilder.get-prom-types.description-histogram', - 'A histogram samples observations (usually things like request durations or response sizes) and counts them in configurable buckets.' - ), - }, - { - value: 'native histogram', - label: t('grafana-prometheus.querybuilder.get-prom-types.label-native-histogram', 'Native histogram'), - description: t( - 'grafana-prometheus.querybuilder.get-prom-types.description-native-histogram', - 'Native histograms are different from classic Prometheus histograms in a number of ways: Native histogram bucket boundaries are calculated by a formula that depends on the scale (resolution) of the native histogram, and are not user defined.' - ), - }, - { - value: 'summary', - label: t('grafana-prometheus.querybuilder.get-prom-types.label-summary', 'Summary'), - description: t( - 'grafana-prometheus.querybuilder.get-prom-types.description-summary', - 'A summary samples observations (usually things like request durations and response sizes) and can calculate configurable quantiles over a sliding time window.' - ), - }, - { - value: 'unknown', - label: t('grafana-prometheus.querybuilder.get-prom-types.label-unknown', 'Unknown'), - description: t( - 'grafana-prometheus.querybuilder.get-prom-types.description-unknown', - 'These metrics have been given the type unknown in the metadata.' - ), - }, - { - value: 'no type', - label: t('grafana-prometheus.querybuilder.get-prom-types.label-no-type', 'No type'), - description: t( - 'grafana-prometheus.querybuilder.get-prom-types.description-no-type', - 'These metrics have no defined type in the metadata.' - ), - }, -]; - -export const getPlaceholders = () => ({ - browse: t('grafana-prometheus.querybuilder.get-placeholders.browse', 'Search metrics by name'), - metadataSearchSwitch: t( - 'grafana-prometheus.querybuilder.get-placeholders.metadata-search-switch', - 'Include description in search' - ), - type: t('grafana-prometheus.querybuilder.get-placeholders.type', 'Filter by type'), - includeNullMetadata: t( - 'grafana-prometheus.querybuilder.get-placeholders.include-null-metadata', - 'Include results with no metadata' - ), - setUseBackend: t('grafana-prometheus.querybuilder.get-placeholders.set-use-backend', 'Enable regex search'), -}); diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/state/state.ts b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/state/state.ts deleted file mode 100644 index 05031eee4db..00000000000 --- a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/state/state.ts +++ /dev/null @@ -1,212 +0,0 @@ -// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/components/metrics-modal/state/state.ts -import { PayloadAction, createSlice } from '@reduxjs/toolkit'; - -import { SelectableValue } from '@grafana/data'; - -import { PromVisualQuery } from '../../../types'; -import { HaystackDictionary, MetricsData } from '../types'; - -export const DEFAULT_RESULTS_PER_PAGE = 100; -export const MAXIMUM_RESULTS_PER_PAGE = 1000; - -/** - * Initial state for the metrics explorer - * @returns - */ -export function initialState(query?: PromVisualQuery): MetricsModalState { - return { - isLoading: true, - metrics: [], - hasMetadata: true, - metaHaystackDictionary: {}, - metaHaystackMatches: [], - metaHaystackOrder: [], - nameHaystackDictionary: {}, - nameHaystackOrder: [], - nameHaystackMatches: [], - totalMetricCount: 0, - filteredMetricCount: null, - resultsPerPage: DEFAULT_RESULTS_PER_PAGE, - pageNum: 1, - fuzzySearchQuery: '', - fullMetaSearch: query?.fullMetaSearch ?? false, - includeNullMetadata: query?.includeNullMetadata ?? true, - selectedTypes: [], - useBackend: query?.useBackend ?? false, - disableTextWrap: query?.disableTextWrap ?? false, - showAdditionalSettings: false, - }; -} - -/** - * The metrics explorer state object - */ -export interface MetricsModalState { - /** Used for the loading spinner */ - isLoading: boolean; - /** - * Initial collection of metrics. - * The frontend filters do not impact this, but - * it is reduced by the backend search. - */ - metrics: MetricsData; - /** Field for disabling type select and switches that rely on metadata */ - hasMetadata: boolean; - /** Used to display metrics and help with fuzzy order */ - nameHaystackDictionary: HaystackDictionary; - /** Used to sort name fuzzy search by relevance */ - nameHaystackOrder: string[]; - /** Used to highlight text in fuzzy matches */ - nameHaystackMatches: string[]; - /** Used to display metrics and help with fuzzy order for search across all metadata */ - metaHaystackDictionary: HaystackDictionary; - /** Used to sort meta fuzzy search by relevance */ - metaHaystackOrder: string[]; - /** Used to highlight text in fuzzy matches */ - metaHaystackMatches: string[]; - /** Total results computed on initialization */ - totalMetricCount: number; - /** Set after filtering metrics */ - filteredMetricCount: number | null; - /** Pagination field for showing results in table */ - resultsPerPage: number; - /** Pagination field */ - pageNum: number; - /** The text query used to match metrics */ - fuzzySearchQuery: string; - /** Enables the fuzzy meatadata search */ - fullMetaSearch: boolean; - /** Includes results that are missing type and description */ - includeNullMetadata: boolean; - /** Filter by prometheus type */ - selectedTypes: Array>; - /** Filter by the series match endpoint instead of the fuzzy search */ - useBackend: boolean; - /** Disable text wrap for descriptions in the results table */ - disableTextWrap: boolean; - /** Display toggle switches for settings */ - showAdditionalSettings: boolean; -} - -/** - * Type for the useEffect get metadata function - */ -export type MetricsModalMetadata = { - isLoading: boolean; - metrics: MetricsData; - hasMetadata: boolean; - metaHaystackDictionary: HaystackDictionary; - nameHaystackDictionary: HaystackDictionary; - totalMetricCount: number; - filteredMetricCount: number | null; -}; - -// for updating the settings in the PromQuery model -export function getSettings(visQuery: PromVisualQuery): MetricsModalSettings { - return { - useBackend: visQuery?.useBackend ?? false, - disableTextWrap: visQuery?.disableTextWrap ?? false, - fullMetaSearch: visQuery?.fullMetaSearch ?? false, - includeNullMetadata: visQuery.includeNullMetadata ?? false, - }; -} - -export type MetricsModalSettings = { - useBackend?: boolean; - disableTextWrap?: boolean; - fullMetaSearch?: boolean; - includeNullMetadata?: boolean; -}; - -export const stateSlice = createSlice({ - name: 'metrics-modal-state', - initialState: initialState(), - reducers: { - filterMetricsBackend: ( - state, - action: PayloadAction<{ - metrics: MetricsData; - filteredMetricCount: number; - isLoading: boolean; - }> - ) => { - state.metrics = action.payload.metrics; - state.filteredMetricCount = action.payload.filteredMetricCount; - state.isLoading = action.payload.isLoading; - }, - buildMetrics: (state, action: PayloadAction) => { - state.isLoading = action.payload.isLoading; - state.metrics = action.payload.metrics; - state.hasMetadata = action.payload.hasMetadata; - state.metaHaystackDictionary = action.payload.metaHaystackDictionary; - state.nameHaystackDictionary = action.payload.nameHaystackDictionary; - state.totalMetricCount = action.payload.totalMetricCount; - state.filteredMetricCount = action.payload.filteredMetricCount; - }, - setIsLoading: (state, action: PayloadAction) => { - state.isLoading = action.payload; - }, - setFilteredMetricCount: (state, action: PayloadAction) => { - state.filteredMetricCount = action.payload; - }, - setResultsPerPage: (state, action: PayloadAction) => { - state.resultsPerPage = action.payload; - }, - setPageNum: (state, action: PayloadAction) => { - state.pageNum = action.payload; - }, - setFuzzySearchQuery: (state, action: PayloadAction) => { - state.fuzzySearchQuery = action.payload; - state.pageNum = 1; - }, - setNameHaystack: (state, action: PayloadAction) => { - state.nameHaystackOrder = action.payload[0]; - state.nameHaystackMatches = action.payload[1]; - }, - setMetaHaystack: (state, action: PayloadAction) => { - state.metaHaystackOrder = action.payload[0]; - state.metaHaystackMatches = action.payload[1]; - }, - setFullMetaSearch: (state, action: PayloadAction) => { - state.fullMetaSearch = action.payload; - state.pageNum = 1; - }, - setIncludeNullMetadata: (state, action: PayloadAction) => { - state.includeNullMetadata = action.payload; - state.pageNum = 1; - }, - setSelectedTypes: (state, action: PayloadAction>>) => { - state.selectedTypes = action.payload; - state.pageNum = 1; - }, - setUseBackend: (state, action: PayloadAction) => { - state.useBackend = action.payload; - state.fullMetaSearch = false; - state.pageNum = 1; - }, - setDisableTextWrap: (state) => { - state.disableTextWrap = !state.disableTextWrap; - }, - showAdditionalSettings: (state) => { - state.showAdditionalSettings = !state.showAdditionalSettings; - }, - }, -}); - -export const { - setIsLoading, - buildMetrics, - filterMetricsBackend, - setResultsPerPage, - setPageNum, - setFuzzySearchQuery, - setNameHaystack, - setMetaHaystack, - setFullMetaSearch, - setIncludeNullMetadata, - setSelectedTypes, - setUseBackend, - setDisableTextWrap, - showAdditionalSettings, - setFilteredMetricCount, -} = stateSlice.actions; diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/styles.ts b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/styles.ts index bcc6fa425c7..64e52600055 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/styles.ts +++ b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/styles.ts @@ -3,7 +3,7 @@ import { css } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; -export const getStyles = (theme: GrafanaTheme2, disableTextWrap: boolean) => { +export const getMetricsModalStyles = (theme: GrafanaTheme2) => { return { modal: css({ width: '85vw', @@ -34,20 +34,9 @@ export const getStyles = (theme: GrafanaTheme2, disableTextWrap: boolean) => { minWidth: '100%', }, }), - selectWrapper: css({ - marginBottom: theme.spacing(1), - }), - resultsAmount: css({ - color: theme.colors.text.secondary, - fontSize: '0.85rem', - padding: '0 0 4px 0', - }), resultsData: css({ margin: `4px 0 ${theme.spacing(2)} 0`, }), - resultsDataCount: css({ - margin: 0, - }), resultsDataFiltered: css({ color: theme.colors.text.secondary, textAlign: 'center', @@ -67,9 +56,9 @@ export const getStyles = (theme: GrafanaTheme2, disableTextWrap: boolean) => { display: 'flex', flexDirection: 'row', flexWrap: 'wrap', - justifyContent: 'space-between', alignItems: 'center', position: 'sticky', + justifyContent: 'center', }), currentlySelected: css({ color: 'grey', @@ -82,21 +71,69 @@ export const getStyles = (theme: GrafanaTheme2, disableTextWrap: boolean) => { visible: css({ visibility: 'visible', }), - settingsBtn: css({ - float: 'right', - }), noBorder: css({ border: 'none', }), - resultsPerPageLabel: css({ - color: theme.colors.text.secondary, - opacity: '75%', - paddingTop: '5px', - fontSize: '0.85rem', - marginRight: '8px', + }; +}; + +export const getResultsTableStyles = (theme: GrafanaTheme2) => { + return { + table: css({ + tableLayout: 'fixed', + borderRadius: theme.shape.radius.default, + width: '100%', + whiteSpace: 'normal', + td: { + padding: theme.spacing(1), + }, + 'td,th': { + minWidth: theme.spacing(3), + borderBottom: `1px solid ${theme.colors.border.weak}`, + }, }), - resultsPerPageWrapper: css({ - display: 'flex', + row: css({ + label: 'row', + borderBottom: `1px solid ${theme.colors.border.weak}`, + cursor: 'pointer', + '&:last-child': { + borderBottom: 0, + }, + '&:hover': { + backgroundColor: theme.colors.background.secondary, + }, + }), + tableHeaderPadding: css({ + padding: '8px', + }), + matchHighLight: css({ + background: 'inherit', + color: theme.components.textHighlight.text, + backgroundColor: theme.components.textHighlight.background, + }), + nameWidth: css({ + width: '37.5%', + }), + nameOverflow: css({ + overflowWrap: 'anywhere', + }), + typeWidth: css({ + width: '15%', + }), + descriptionWidth: css({ + width: '35%', + }), + stickyHeader: css({ + position: 'sticky', + top: 0, + backgroundColor: theme.colors.background.primary, + }), + noResults: css({ + textAlign: 'center', + color: theme.colors.text.secondary, + }), + tooltipSpace: css({ + marginLeft: '4px', }), }; }; diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/shared/testIds.ts b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/testIds.ts similarity index 65% rename from packages/grafana-prometheus/src/querybuilder/components/metrics-modal/shared/testIds.ts rename to packages/grafana-prometheus/src/querybuilder/components/metrics-modal/testIds.ts index 275394dd348..f1e5c7709e8 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/shared/testIds.ts +++ b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/testIds.ts @@ -1,12 +1,9 @@ export const metricsModaltestIds = { metricModal: 'metric-modal', searchMetric: 'search-metric', - searchWithMetadata: 'search-with-metadata', selectType: 'select-type', metricCard: 'metric-card', useMetric: 'use-metric', searchPage: 'search-page', resultsPerPage: 'results-per-page', - setUseBackend: 'set-use-backend', - showAdditionalSettings: 'show-additional-settings', }; diff --git a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/uFuzzy.ts b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/uFuzzy.ts index 297e216b560..3de9b6f1828 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/uFuzzy.ts +++ b/packages/grafana-prometheus/src/querybuilder/components/metrics-modal/uFuzzy.ts @@ -1,6 +1,5 @@ // Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/components/metrics-modal/uFuzzy.ts import uFuzzy from '@leeoniya/ufuzzy'; -import { debounce as debounceLodash } from 'lodash'; const uf = new uFuzzy({ intraMode: 1, @@ -10,37 +9,34 @@ const uf = new uFuzzy({ intraDel: 1, }); -function fuzzySearch(haystack: string[], query: string, dispatcher: (data: string[][]) => void) { +export const fuzzySearch = (haystack: string[], query: string) => { const [idxs, info, order] = uf.search(haystack, query, 0, 1e5); let haystackOrder: string[] = []; let matchesSet: Set = new Set(); - if (idxs && order) { - /** - * get the fuzzy matches for hilighting - * @param part - * @param matched - */ - const mark = (part: string, matched: boolean) => { - if (matched) { - matchesSet.add(part); - } - }; - - // Iterate to create the order of needles(queries) and the matches - for (let i = 0; i < order.length; i++) { - let infoIdx = order[i]; - - /** Evaluate the match, get the matches for highlighting */ - uFuzzy.highlight(haystack[info.idx[infoIdx]], info.ranges[infoIdx], mark); - /** Get the order */ - haystackOrder.push(haystack[info.idx[infoIdx]]); - } - - dispatcher([haystackOrder, [...matchesSet]]); - } else if (!query) { - dispatcher([[], []]); + if (!(idxs && order)) { + return [[], []]; } -} + /** + * get the fuzzy matches for highlighting + * @param part + * @param matched + */ + const mark = (part: string, matched: boolean) => { + if (matched) { + matchesSet.add(part); + } + }; -export const debouncedFuzzySearch = debounceLodash(fuzzySearch, 300); + // Iterate to create the order of needles(queries) and the matches + for (let i = 0; i < order.length; i++) { + let infoIdx = order[i]; + + /** Evaluate the match, get the matches for highlighting */ + uFuzzy.highlight(haystack[info.idx[infoIdx]], info.ranges[infoIdx], mark); + /** Get the order */ + haystackOrder.push(haystack[info.idx[infoIdx]]); + } + + return [haystackOrder, [...matchesSet]]; +}; diff --git a/packages/grafana-prometheus/src/querybuilder/components/shared/BaseQueryBuilder.tsx b/packages/grafana-prometheus/src/querybuilder/components/shared/BaseQueryBuilder.tsx deleted file mode 100644 index 03787aad88a..00000000000 --- a/packages/grafana-prometheus/src/querybuilder/components/shared/BaseQueryBuilder.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { memo } from 'react'; - -import { NestedQueryList } from '../NestedQueryList'; - -import { QueryBuilderContent } from './QueryBuilderContent'; -import { BaseQueryBuilderProps } from './types'; - -export const BaseQueryBuilder = memo((props) => { - const { query, datasource, onChange, onRunQuery, showExplain } = props; - - return ( - <> - - {query.binaryQueries && query.binaryQueries.length > 0 && ( - - )} - - ); -}); - -BaseQueryBuilder.displayName = 'BaseQueryBuilder'; diff --git a/packages/grafana-prometheus/src/querybuilder/components/shared/types.ts b/packages/grafana-prometheus/src/querybuilder/components/shared/types.ts deleted file mode 100644 index 626e6606259..00000000000 --- a/packages/grafana-prometheus/src/querybuilder/components/shared/types.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { PanelData } from '@grafana/data'; - -import { PrometheusDatasource } from '../../../datasource'; -import { PromVisualQuery } from '../../types'; - -export interface BaseQueryBuilderProps { - query: PromVisualQuery; - datasource: PrometheusDatasource; - onChange: (update: PromVisualQuery) => void; - onRunQuery: () => void; - data?: PanelData; - showExplain: boolean; -} diff --git a/packages/grafana-prometheus/src/querybuilder/types.ts b/packages/grafana-prometheus/src/querybuilder/types.ts index 991cfec8969..c2bc18bc2e5 100644 --- a/packages/grafana-prometheus/src/querybuilder/types.ts +++ b/packages/grafana-prometheus/src/querybuilder/types.ts @@ -14,11 +14,6 @@ export interface PromVisualQuery { labels: QueryBuilderLabelFilter[]; operations: QueryBuilderOperation[]; binaryQueries?: PromVisualQueryBinary[]; - // metrics explorer additional settings - useBackend?: boolean; - disableTextWrap?: boolean; - includeNullMetadata?: boolean; - fullMetaSearch?: boolean; } export interface PromQueryModellerInterface { diff --git a/packages/grafana-prometheus/src/types.ts b/packages/grafana-prometheus/src/types.ts index acd5b803ee2..98730018bf3 100644 --- a/packages/grafana-prometheus/src/types.ts +++ b/packages/grafana-prometheus/src/types.ts @@ -15,11 +15,6 @@ export interface PromQuery extends GenPromQuery, DataQuery { showingTable?: boolean; hinting?: boolean; interval?: string; - // store the metrics explorer additional settings - useBackend?: boolean; - disableTextWrap?: boolean; - fullMetaSearch?: boolean; - includeNullMetadata?: boolean; fromExploreMetrics?: boolean; } From ef0d6381b08d03e190018d22293b89a93227adaa Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Thu, 31 Jul 2025 17:12:17 -0500 Subject: [PATCH 04/89] Dashboards: Remove incorrect information in docs (#109014) --- docs/sources/developers/http_api/dashboard.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/sources/developers/http_api/dashboard.md b/docs/sources/developers/http_api/dashboard.md index b862fb7c4a6..f5456a22e77 100644 --- a/docs/sources/developers/http_api/dashboard.md +++ b/docs/sources/developers/http_api/dashboard.md @@ -568,8 +568,6 @@ Gets a dashboard via the dashboard uid. - namespace: to read more about the namespace to use, see the [API overview](https://grafana.com/docs/grafana//developers/http_api/apis/). - uid: the unique identifier of the dashboard to update. this will be the _name_ in the dashboard response -Note: For large dashboards, add `/dto` to the end of the URL to get the full dashboard body. - **Required permissions** See note in the [introduction]({{< ref "#dashboard-api" >}}) for an explanation. From ae2614f1a8402c4aa280af245589061374ea27c4 Mon Sep 17 00:00:00 2001 From: "grafana-pr-automation[bot]" <140550294+grafana-pr-automation[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 00:44:23 +0000 Subject: [PATCH 05/89] I18n: Download translations from Crowdin (#109016) New Crowdin translations by GitHub Action Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../src/locales/cs-CZ/grafana-prometheus.json | 18 +---------- .../src/locales/de-DE/grafana-prometheus.json | 16 +--------- .../src/locales/es-ES/grafana-prometheus.json | 16 +--------- .../src/locales/fr-FR/grafana-prometheus.json | 16 +--------- .../src/locales/hu-HU/grafana-prometheus.json | 16 +--------- .../src/locales/id-ID/grafana-prometheus.json | 15 +--------- .../src/locales/it-IT/grafana-prometheus.json | 16 +--------- .../src/locales/ja-JP/grafana-prometheus.json | 15 +--------- .../src/locales/ko-KR/grafana-prometheus.json | 15 +--------- .../src/locales/nl-NL/grafana-prometheus.json | 16 +--------- .../src/locales/pl-PL/grafana-prometheus.json | 18 +---------- .../src/locales/pt-BR/grafana-prometheus.json | 16 +--------- .../src/locales/pt-PT/grafana-prometheus.json | 16 +--------- .../src/locales/ru-RU/grafana-prometheus.json | 18 +---------- .../src/locales/sv-SE/grafana-prometheus.json | 16 +--------- .../src/locales/tr-TR/grafana-prometheus.json | 16 +--------- .../locales/zh-Hans/grafana-prometheus.json | 15 +--------- .../locales/zh-Hant/grafana-prometheus.json | 15 +--------- public/locales/cs-CZ/grafana.json | 30 +++++++++++++------ public/locales/de-DE/grafana.json | 30 +++++++++++++------ public/locales/es-ES/grafana.json | 30 +++++++++++++------ public/locales/fr-FR/grafana.json | 30 +++++++++++++------ public/locales/hu-HU/grafana.json | 30 +++++++++++++------ public/locales/id-ID/grafana.json | 30 +++++++++++++------ public/locales/it-IT/grafana.json | 30 +++++++++++++------ public/locales/ja-JP/grafana.json | 30 +++++++++++++------ public/locales/ko-KR/grafana.json | 30 +++++++++++++------ public/locales/nl-NL/grafana.json | 30 +++++++++++++------ public/locales/pl-PL/grafana.json | 30 +++++++++++++------ public/locales/pt-BR/grafana.json | 30 +++++++++++++------ public/locales/pt-PT/grafana.json | 30 +++++++++++++------ public/locales/ru-RU/grafana.json | 30 +++++++++++++------ public/locales/sv-SE/grafana.json | 30 +++++++++++++------ public/locales/tr-TR/grafana.json | 30 +++++++++++++------ public/locales/zh-Hans/grafana.json | 30 +++++++++++++------ public/locales/zh-Hant/grafana.json | 30 +++++++++++++------ 36 files changed, 396 insertions(+), 433 deletions(-) diff --git a/packages/grafana-prometheus/src/locales/cs-CZ/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/cs-CZ/grafana-prometheus.json index 3b17ab6a5a8..44a8acbc7a2 100644 --- a/packages/grafana-prometheus/src/locales/cs-CZ/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/cs-CZ/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "Filtrovat názvy metrik podle vyhledávání regulárních výrazů pomocí dalšího volání rozhraní Prometheus API.", - "disable-text-wrap": "Zakázat obtékání textu" - }, "feedback-link": { "give-feedback": "Poskytnout zpětnou vazbu", "title-give-feedback": "Průzkumník metrik je nový. Dejte nám prosím vědět, jak ho můžeme vylepšit" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,18 +371,10 @@ "tooltip-metric": "Volitelné: vrátí seznam hodnot štítků pro název štítku v zadané metrice." }, "metrics-modal": { - "additional-settings": "Dodatečná nastavení", - "aria-label-additional-settings": "Další nastavení", "aria-label-browse-metrics": "Procházet metriky", "currently-selected": "Aktuálně vybráno: {{selected}}", "metrics-pre-filtered": "Tyto metriky byly předem filtrovány štítky vybranými ve filtrech štítků.", - "placeholder-results-per-page": "výsledků na stránku", - "results-per-page": "Výsledky na stránku", - "title-metrics-explorer": "Průzkumník metrik", - "results-amount_one": "Zobrazuje se {{num}} z {{count}} výsledků", - "results-amount_few": "Zobrazuje se {{num}} z {{count}} výsledků", - "results-amount_many": "Zobrazuje se {{num}} z {{count}} výsledků", - "results-amount_other": "Zobrazuje se {{num}} z {{count}} výsledků" + "title-metrics-explorer": "Průzkumník metrik" }, "nested-query": { "label": { @@ -502,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Název", - "select": "Vybrat", "type": "Typ" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/de-DE/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/de-DE/grafana-prometheus.json index 7b2db63bb8b..c391ba11f3d 100644 --- a/packages/grafana-prometheus/src/locales/de-DE/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/de-DE/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "Filtern Sie Metriknamen per Regex-Suche und nutzen Sie dabei einen zusätzlichen Aufruf der Prometheus-API.", - "disable-text-wrap": "Textumbruch deaktivieren" - }, "feedback-link": { "give-feedback": "Feedback geben", "title-give-feedback": "Der Metrik-Explorer ist neu. Bitte teilen Sie uns mit, wie wir ihn verbessern können." @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,16 +371,10 @@ "tooltip-metric": "Optional: gibt eine Liste von Label-Werten für den Label-Namen in der angegebenen Metrik zurück." }, "metrics-modal": { - "additional-settings": "Zusätzliche Einstellungen", - "aria-label-additional-settings": "Zusätzliche Einstellungen", "aria-label-browse-metrics": "Metriken durchsuchen", "currently-selected": "Aktuell ausgewählt: {{selected}}", "metrics-pre-filtered": "Diese Metriken wurden anhand der Labels, die in den Label-Filtern ausgewählt wurden, vorgefiltert.", - "placeholder-results-per-page": "Ergebnisse pro Seite", - "results-per-page": "Ergebnisse pro Seite", - "title-metrics-explorer": "Metrik-Explorer", - "results-amount_one": "{{num}} von {{count}} Ergebnissen werden angezeigt", - "results-amount_other": "{{num}} von {{count}} Ergebnissen werden angezeigt" + "title-metrics-explorer": "Metrik-Explorer" }, "nested-query": { "label": { @@ -500,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Name", - "select": "Auswählen", "type": "Typ" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/es-ES/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/es-ES/grafana-prometheus.json index 8feaf63282c..c0016de4b4a 100644 --- a/packages/grafana-prometheus/src/locales/es-ES/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/es-ES/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "", - "disable-text-wrap": "" - }, "feedback-link": { "give-feedback": "Enviar comentarios", "title-give-feedback": "" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,16 +371,10 @@ "tooltip-metric": "" }, "metrics-modal": { - "additional-settings": "", - "aria-label-additional-settings": "Configuraciones adicionales", "aria-label-browse-metrics": "", "currently-selected": "", "metrics-pre-filtered": "", - "placeholder-results-per-page": "", - "results-per-page": "", - "title-metrics-explorer": "", - "results-amount_one": "", - "results-amount_other": "" + "title-metrics-explorer": "" }, "nested-query": { "label": { @@ -500,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Nombre", - "select": "Seleccionar", "type": "Tipo" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/fr-FR/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/fr-FR/grafana-prometheus.json index 1b48f0ac903..75fffbffa7e 100644 --- a/packages/grafana-prometheus/src/locales/fr-FR/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/fr-FR/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "Filtrez les noms de métriques par recherche d’expression régulière, en utilisant un appel supplémentaire sur l’API Prometheus.", - "disable-text-wrap": "Désactiver le retour à la ligne automatique" - }, "feedback-link": { "give-feedback": "Publiez votre commentaire", "title-give-feedback": "L’explorateur de métriques est une nouvelle fonctionnalité ; faites-nous part de vos retours pour l’améliorer" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,16 +371,10 @@ "tooltip-metric": "Facultatif : renvoie une liste de valeurs d’étiquette pour le nom d’étiquette dans la métrique spécifiée." }, "metrics-modal": { - "additional-settings": "Paramètres additionnels", - "aria-label-additional-settings": "Paramètres supplémentaires", "aria-label-browse-metrics": "Parcourir les métriques", "currently-selected": "Sélection actuelle : {{selected}}", "metrics-pre-filtered": "Ces métriques ont été pré-filtrées par les étiquettes choisies dans les filtres d’étiquettes.", - "placeholder-results-per-page": "résultats par page", - "results-per-page": "Résultats par page", - "title-metrics-explorer": "Explorateur de métriques", - "results-amount_one": "Affichage de {{num}} résultats sur {{count}}", - "results-amount_other": "Affichage de {{num}} résultats sur {{count}}" + "title-metrics-explorer": "Explorateur de métriques" }, "nested-query": { "label": { @@ -500,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Nom", - "select": "Sélectionner", "type": "Type" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/hu-HU/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/hu-HU/grafana-prometheus.json index 2b4464c68f6..454e51f3684 100644 --- a/packages/grafana-prometheus/src/locales/hu-HU/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/hu-HU/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "A metrikanevek szűrése reguláris kifejezéses kereséssel, a Prometheus API további hívásával.", - "disable-text-wrap": "Sortörés letiltása" - }, "feedback-link": { "give-feedback": "Visszajelzés küldése", "title-give-feedback": "A metrikaböngésző új, és számítunk az építő jellegű visszajelzésére" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,16 +371,10 @@ "tooltip-metric": "Opcionális: a megadott metrikában a címke nevéhez tartozó címkeértékek listáját adja vissza." }, "metrics-modal": { - "additional-settings": "További beállítások", - "aria-label-additional-settings": "További beállítások", "aria-label-browse-metrics": "Metrikák böngészése", "currently-selected": "Jelenleg kiválasztott: {{selected}}", "metrics-pre-filtered": "Ezek a metrikák előszűrtek a címkeszűrőkben kiválasztott címkék alapján.", - "placeholder-results-per-page": "találat oldalanként", - "results-per-page": "Találatok száma oldalanként", - "title-metrics-explorer": "Metrikaböngésző", - "results-amount_one": "{{count}}/{{num}} találat megjelenítése", - "results-amount_other": "{{count}}/{{num}} találat megjelenítése" + "title-metrics-explorer": "Metrikaböngésző" }, "nested-query": { "label": { @@ -500,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Név", - "select": "Kijelölés", "type": "Típus" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/id-ID/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/id-ID/grafana-prometheus.json index bbcd6d32f7e..e674183019f 100644 --- a/packages/grafana-prometheus/src/locales/id-ID/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/id-ID/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "Filter nama metrik dengan pencarian regex, menggunakan panggilan tambahan pada API Prometheus.", - "disable-text-wrap": "Nonaktifkan pemenggalan teks otomatis" - }, "feedback-link": { "give-feedback": "Berikan umpan balik", "title-give-feedback": "Penjelajah metrik ini masih baru, beri tahu kami cara untuk meningkatkannya" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,15 +371,10 @@ "tooltip-metric": "Opsional: mengembalikan daftar nilai label untuk nama label dalam metrik yang ditentukan." }, "metrics-modal": { - "additional-settings": "Pengaturan Tambahan", - "aria-label-additional-settings": "Pengaturan tambahan", "aria-label-browse-metrics": "Telusuri metrik", "currently-selected": "Sedang dipilih: {{selected}}", "metrics-pre-filtered": "Metrik ini telah difilter sebelumnya berdasarkan label yang dipilih di filter label.", - "placeholder-results-per-page": "hasil per halaman", - "results-per-page": "Hasil per halaman", - "title-metrics-explorer": "Penjelajah metrik", - "results-amount_other": "Menampilkan {{num}} dari {{count}} hasil" + "title-metrics-explorer": "Penjelajah metrik" }, "nested-query": { "label": { @@ -499,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Nama", - "select": "Pilih", "type": "Jenis" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/it-IT/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/it-IT/grafana-prometheus.json index 9cfc70e6c88..2671478ca0f 100644 --- a/packages/grafana-prometheus/src/locales/it-IT/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/it-IT/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "", - "disable-text-wrap": "" - }, "feedback-link": { "give-feedback": "Lascia un feedback", "title-give-feedback": "" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,16 +371,10 @@ "tooltip-metric": "" }, "metrics-modal": { - "additional-settings": "", - "aria-label-additional-settings": "Impostazioni aggiuntive", "aria-label-browse-metrics": "", "currently-selected": "", "metrics-pre-filtered": "", - "placeholder-results-per-page": "", - "results-per-page": "", - "title-metrics-explorer": "", - "results-amount_one": "", - "results-amount_other": "" + "title-metrics-explorer": "" }, "nested-query": { "label": { @@ -500,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Nome", - "select": "Seleziona", "type": "Tipo" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/ja-JP/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/ja-JP/grafana-prometheus.json index c4f13c7d462..72b1785b222 100644 --- a/packages/grafana-prometheus/src/locales/ja-JP/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/ja-JP/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "Prometheus APIの追加呼び出しを使用して、正規表現検索でメトリック名をフィルタリングします。", - "disable-text-wrap": "テキストの折り返しを無効化" - }, "feedback-link": { "give-feedback": "フィードバックを送信", "title-give-feedback": "メトリックエクスプローラーは新機能です。改善点についてお聞かせください" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,15 +371,10 @@ "tooltip-metric": "オプション: 指定されたメトリックのラベル名に対するラベル値のリストを返します。" }, "metrics-modal": { - "additional-settings": "追加設定", - "aria-label-additional-settings": "追加設定", "aria-label-browse-metrics": "メトリックを参照", "currently-selected": "現在選択中: {{selected}}", "metrics-pre-filtered": "これらのメトリックは、ラベルフィルターで選択されたラベルによって事前にフィルタリングされています。", - "placeholder-results-per-page": "1ページあたりの結果数", - "results-per-page": "1ページあたりの結果数", - "title-metrics-explorer": "メトリックエクスプローラー", - "results-amount_other": "{{count}}件中{{num}}件の結果を表示" + "title-metrics-explorer": "メトリックエクスプローラー" }, "nested-query": { "label": { @@ -499,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "名前", - "select": "選択", "type": "種類" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/ko-KR/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/ko-KR/grafana-prometheus.json index f9824a261d9..975a9631f32 100644 --- a/packages/grafana-prometheus/src/locales/ko-KR/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/ko-KR/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "", - "disable-text-wrap": "" - }, "feedback-link": { "give-feedback": "피드백 제출하기", "title-give-feedback": "" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,15 +371,10 @@ "tooltip-metric": "" }, "metrics-modal": { - "additional-settings": "", - "aria-label-additional-settings": "추가 설정", "aria-label-browse-metrics": "", "currently-selected": "", "metrics-pre-filtered": "", - "placeholder-results-per-page": "", - "results-per-page": "", - "title-metrics-explorer": "", - "results-amount_other": "" + "title-metrics-explorer": "" }, "nested-query": { "label": { @@ -499,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "이름", - "select": "선택", "type": "유형" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/nl-NL/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/nl-NL/grafana-prometheus.json index 9a1280a547c..f20146043d3 100644 --- a/packages/grafana-prometheus/src/locales/nl-NL/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/nl-NL/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "Filter metrische namen op regex-zoekopdracht, met behulp van een extra oproep op de Prometheus-API.", - "disable-text-wrap": "Tekstterugloop uitschakelen" - }, "feedback-link": { "give-feedback": "Feedback geven", "title-give-feedback": "De metriekverkenner is nieuw, laat ons weten hoe we deze kunnen verbeteren" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,16 +371,10 @@ "tooltip-metric": "Optioneel: retourneert een lijst met labelwaarden voor de labelnaam in de opgegeven metriek." }, "metrics-modal": { - "additional-settings": "Extra instellingen", - "aria-label-additional-settings": "Aanvullende instellingen", "aria-label-browse-metrics": "Metriek bekijken", "currently-selected": "Momenteel geselecteerd: {{selected}}", "metrics-pre-filtered": "Deze metriek is vooraf gefilterd op labels die zijn gekozen in de labelfilters.", - "placeholder-results-per-page": "resultaten per pagina", - "results-per-page": "Resultaten per pagina", - "title-metrics-explorer": "Metriekverkenner", - "results-amount_one": "{{num}} resultaten van {{count}} weergeven", - "results-amount_other": "{{num}} resultaten van {{count}} weergeven" + "title-metrics-explorer": "Metriekverkenner" }, "nested-query": { "label": { @@ -500,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Naam", - "select": "Selecteren", "type": "Type" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/pl-PL/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/pl-PL/grafana-prometheus.json index a52ae2f32a7..fe3211ff5e4 100644 --- a/packages/grafana-prometheus/src/locales/pl-PL/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/pl-PL/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "", - "disable-text-wrap": "" - }, "feedback-link": { "give-feedback": "Przekaż opinię", "title-give-feedback": "" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,18 +371,10 @@ "tooltip-metric": "" }, "metrics-modal": { - "additional-settings": "", - "aria-label-additional-settings": "Ustawienia dodatkowe", "aria-label-browse-metrics": "", "currently-selected": "", "metrics-pre-filtered": "", - "placeholder-results-per-page": "", - "results-per-page": "", - "title-metrics-explorer": "", - "results-amount_one": "", - "results-amount_few": "", - "results-amount_many": "", - "results-amount_other": "" + "title-metrics-explorer": "" }, "nested-query": { "label": { @@ -502,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Imię", - "select": "Wybierz", "type": "Typ" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/pt-BR/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/pt-BR/grafana-prometheus.json index cf886e70733..507ddf3c792 100644 --- a/packages/grafana-prometheus/src/locales/pt-BR/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/pt-BR/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "", - "disable-text-wrap": "" - }, "feedback-link": { "give-feedback": "Dar feedback", "title-give-feedback": "" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,16 +371,10 @@ "tooltip-metric": "" }, "metrics-modal": { - "additional-settings": "", - "aria-label-additional-settings": "Configurações adicionais", "aria-label-browse-metrics": "", "currently-selected": "", "metrics-pre-filtered": "", - "placeholder-results-per-page": "", - "results-per-page": "", - "title-metrics-explorer": "", - "results-amount_one": "", - "results-amount_other": "" + "title-metrics-explorer": "" }, "nested-query": { "label": { @@ -500,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Nome", - "select": "Selecionar", "type": "Tipo" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/pt-PT/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/pt-PT/grafana-prometheus.json index b6d796a828c..3f80c60195a 100644 --- a/packages/grafana-prometheus/src/locales/pt-PT/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/pt-PT/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "", - "disable-text-wrap": "" - }, "feedback-link": { "give-feedback": "Dar feedback", "title-give-feedback": "" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,16 +371,10 @@ "tooltip-metric": "" }, "metrics-modal": { - "additional-settings": "", - "aria-label-additional-settings": "Definições adicionais", "aria-label-browse-metrics": "", "currently-selected": "", "metrics-pre-filtered": "", - "placeholder-results-per-page": "", - "results-per-page": "", - "title-metrics-explorer": "", - "results-amount_one": "", - "results-amount_other": "" + "title-metrics-explorer": "" }, "nested-query": { "label": { @@ -500,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Nome", - "select": "Selecionar", "type": "Tipo" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/ru-RU/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/ru-RU/grafana-prometheus.json index 473f1f146f7..896c67e458f 100644 --- a/packages/grafana-prometheus/src/locales/ru-RU/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/ru-RU/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "", - "disable-text-wrap": "" - }, "feedback-link": { "give-feedback": "Отправить отзыв", "title-give-feedback": "" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,18 +371,10 @@ "tooltip-metric": "" }, "metrics-modal": { - "additional-settings": "", - "aria-label-additional-settings": "Дополнительные параметры", "aria-label-browse-metrics": "", "currently-selected": "", "metrics-pre-filtered": "", - "placeholder-results-per-page": "", - "results-per-page": "", - "title-metrics-explorer": "", - "results-amount_one": "", - "results-amount_few": "", - "results-amount_many": "", - "results-amount_other": "" + "title-metrics-explorer": "" }, "nested-query": { "label": { @@ -502,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Имя", - "select": "Выбрать", "type": "Тип" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/sv-SE/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/sv-SE/grafana-prometheus.json index 017e25b5ae3..f51290dffe1 100644 --- a/packages/grafana-prometheus/src/locales/sv-SE/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/sv-SE/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "", - "disable-text-wrap": "" - }, "feedback-link": { "give-feedback": "Ge feedback", "title-give-feedback": "" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,16 +371,10 @@ "tooltip-metric": "" }, "metrics-modal": { - "additional-settings": "", - "aria-label-additional-settings": "Ytterligare inställningar", "aria-label-browse-metrics": "", "currently-selected": "", "metrics-pre-filtered": "", - "placeholder-results-per-page": "", - "results-per-page": "", - "title-metrics-explorer": "", - "results-amount_one": "", - "results-amount_other": "" + "title-metrics-explorer": "" }, "nested-query": { "label": { @@ -500,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Namn", - "select": "Välj", "type": "Typ" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/tr-TR/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/tr-TR/grafana-prometheus.json index 10e63ea4441..9aa271d54fe 100644 --- a/packages/grafana-prometheus/src/locales/tr-TR/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/tr-TR/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "", - "disable-text-wrap": "" - }, "feedback-link": { "give-feedback": "Geri bildirim gönder", "title-give-feedback": "" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,16 +371,10 @@ "tooltip-metric": "" }, "metrics-modal": { - "additional-settings": "", - "aria-label-additional-settings": "Ek ayarlar", "aria-label-browse-metrics": "", "currently-selected": "", "metrics-pre-filtered": "", - "placeholder-results-per-page": "", - "results-per-page": "", - "title-metrics-explorer": "", - "results-amount_one": "", - "results-amount_other": "" + "title-metrics-explorer": "" }, "nested-query": { "label": { @@ -500,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "Ad", - "select": "Seçin", "type": "Tür" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/zh-Hans/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/zh-Hans/grafana-prometheus.json index 4050d264fa2..f15a039030c 100644 --- a/packages/grafana-prometheus/src/locales/zh-Hans/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/zh-Hans/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "使用 Prometheus API 上的其他调用,通过正则表达式搜索筛选指标名称。", - "disable-text-wrap": "禁用文本换行" - }, "feedback-link": { "give-feedback": "提供反馈", "title-give-feedback": "指标浏览器是新功能,请告诉我们如何改进" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,15 +371,10 @@ "tooltip-metric": "可选:返回指定指标中标签名称的标签值列表。" }, "metrics-modal": { - "additional-settings": "其他设置", - "aria-label-additional-settings": "附加设置", "aria-label-browse-metrics": "浏览指标", "currently-selected": "当前选择:{{selected}}", "metrics-pre-filtered": "这些指标已通过标签筛选器中选择的标签进行预筛选。", - "placeholder-results-per-page": "每页显示结果数", - "results-per-page": "每页结果数", - "title-metrics-explorer": "指标浏览器", - "results-amount_other": "显示 {{num}} 个结果(共 {{count}} 个)" + "title-metrics-explorer": "指标浏览器" }, "nested-query": { "label": { @@ -499,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "名称", - "select": "选择", "type": "类型" }, "update-function-args": { diff --git a/packages/grafana-prometheus/src/locales/zh-Hant/grafana-prometheus.json b/packages/grafana-prometheus/src/locales/zh-Hant/grafana-prometheus.json index 33c4d871bb0..d6a441a81bf 100644 --- a/packages/grafana-prometheus/src/locales/zh-Hant/grafana-prometheus.json +++ b/packages/grafana-prometheus/src/locales/zh-Hant/grafana-prometheus.json @@ -311,10 +311,6 @@ } }, "querybuilder": { - "additional-settings": { - "content-filter-metric-names-regex-search-using": "透過正規表達式搜尋篩選指標名稱,並使用額外的 Prometheus API 呼叫。", - "disable-text-wrap": "停用文字換行" - }, "feedback-link": { "give-feedback": "提供意見回饋", "title-give-feedback": "指標瀏覽器為新功能,請告訴我們如何改善" @@ -328,9 +324,6 @@ }, "get-placeholders": { "browse": "", - "include-null-metadata": "", - "metadata-search-switch": "", - "set-use-backend": "", "type": "" }, "get-prom-types": { @@ -378,15 +371,10 @@ "tooltip-metric": "選擇性設定:回傳指定指標中該標籤名稱的標籤值清單。" }, "metrics-modal": { - "additional-settings": "附加設定", - "aria-label-additional-settings": "附加設定", "aria-label-browse-metrics": "瀏覽指標", "currently-selected": "目前已選取:{{selected}}", "metrics-pre-filtered": "這些指標已透過標籤篩選條件中選擇的標籤進行預先篩選。", - "placeholder-results-per-page": "每頁顯示結果", - "results-per-page": "每頁顯示的結果", - "title-metrics-explorer": "指標瀏覽器", - "results-amount_other": "結果共 {{count}} 項,顯示 {{num}} 項" + "title-metrics-explorer": "指標瀏覽器" }, "nested-query": { "label": { @@ -499,7 +487,6 @@ "message-expand-search": "", "message-no-metrics-found": "", "name": "名稱(名字)", - "select": "選取", "type": "類型" }, "update-function-args": { diff --git a/public/locales/cs-CZ/grafana.json b/public/locales/cs-CZ/grafana.json index 308c5ba4955..1643e92662c 100644 --- a/public/locales/cs-CZ/grafana.json +++ b/public/locales/cs-CZ/grafana.json @@ -3601,12 +3601,12 @@ "tags-column": "Tagy" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "Složka byla úspěšně odstraněna", "api-error": "Složku se nepodařilo odstranit", "button-cancel": "Zrušit", "button-delete": "Odstranit", "button-deleting": "Probíhá odstraňování…", - "delete-warning": "Tímto odstraníte tuto složku a všechny následné složky. Celkově to ovlivní:" + "delete-warning": "Tímto odstraníte tuto složku a všechny následné složky. Celkově to ovlivní:", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Nelze načíst informace o následovníkovi" @@ -3649,7 +3649,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Chyba při vytváření složky", - "alert-folder-created-successfully": "Složka úspěšně vytvořena", "button-create": "Vytvořit", "button-creating": "Vytváření…", "cancel": "Zrušit", @@ -3797,7 +3796,6 @@ } }, "description-experimental-types": "Povolit výběr experimentálních typů prvků", - "description-infinite-panning": "Povolit nekonečné posouvání – užitečné pro rozsáhlá plátna. Upozornění: Jedná se o experimentální funkci, která v současné době funguje pouze s prvky, které jsou omezeny nahoře/vlevo", "description-inline-editing": "Povolit přímé úpravy panelu", "description-pan-zoom": "Povolit posouvání a přiblížení", "direction-options": { @@ -3898,7 +3896,6 @@ "name-align-text": "Zarovnat text", "name-color": "Barva textu", "name-experimental-types": "Experimentální typy prvků", - "name-infinite-panning": "Nekonečné posouvání", "name-inline-editing": "Přímé upravování", "name-pan-zoom": "Posouvání a přiblížení", "name-text": "Text", @@ -5685,6 +5682,7 @@ "delete-read-only-file-message": "Tuto nástěnku nelze odstranit přímo z Grafany, protože úložiště je pouze pro čtení. Chcete-li tuto nástěnku odstranit, odeberte soubor z úložiště Git.", "deleting": "Probíhá odstranění…", "drawer-title": "Odstranit zajištěnou nástěnku", + "success-message": "", "title-this-repository-is-read-only": "Toto úložiště je jen pro čtení" }, "description-label": { @@ -5697,9 +5695,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "Změny na nástěnce úspěšně uloženy" - }, "email-list": { "aria-label-emailmenu": "Přepnout e-mailovou nabídku" }, @@ -5860,6 +5855,7 @@ "usage-count_other": "Použito na {{count}} nástěnkách" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5869,6 +5865,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11081,6 +11078,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Tato funkce je v současné době v aktivním vývoji. Pro nejlepší zážitek a nejnovější vylepšení doporučujeme použít <2>noční sestavení Grafany." @@ -11954,7 +11954,7 @@ "recommended": "Doporučeno", "results": "Výsledky" }, - "search": "Hledat" + "search": "" } }, "search": { @@ -12595,6 +12595,18 @@ "label-medium": "Střední", "label-small": "Malé" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "Pokud je vybrán, celý řádek bude barevný jako tato buňka.", "description-wrap-text": "Pokud bude vybraný text zabalen na šířku textu v nakonfigurovaném sloupci", diff --git a/public/locales/de-DE/grafana.json b/public/locales/de-DE/grafana.json index c583a7bc4f0..80e030a1058 100644 --- a/public/locales/de-DE/grafana.json +++ b/public/locales/de-DE/grafana.json @@ -3563,12 +3563,12 @@ "tags-column": "Tags" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "Ordner erfolgreich gelöscht", "api-error": "Ordner konnte nicht gelöscht werden", "button-cancel": "Abbrechen", "button-delete": "Löschen", "button-deleting": "Wird gelöscht …", - "delete-warning": "Dadurch werden dieser und alle untergeordneten Ordner gelöscht. Insgesamt betrifft dies:" + "delete-warning": "Dadurch werden dieser und alle untergeordneten Ordner gelöscht. Insgesamt betrifft dies:", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Nachfolgerinformationen können nicht abgerufen werden" @@ -3611,7 +3611,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Fehler beim Erstellen des Ordners", - "alert-folder-created-successfully": "Der Ordner wurde erfolgreich erstellt", "button-create": "Erstellen", "button-creating": "Wird erstellt ...", "cancel": "Abbrechen", @@ -3759,7 +3758,6 @@ } }, "description-experimental-types": "Auswahl experimenteller Elementtypen aktivieren", - "description-infinite-panning": "Unbegrenztes Schwenken aktivieren – nützlich für umfangreiche Leinwände. Warnung: Dies ist eine experimentelle Funktion und funktioniert momentan nur mit Elementen gut, die oben/links eingeschränkt sind", "description-inline-editing": "Direkte Bearbeitung des Panels aktivieren", "description-pan-zoom": "Schwenken und Zoomen aktivieren", "direction-options": { @@ -3860,7 +3858,6 @@ "name-align-text": "Text ausrichten", "name-color": "Textfarbe", "name-experimental-types": "Experimentelle Elementtypen", - "name-infinite-panning": "Unbegrenztes Schwenken", "name-inline-editing": "Inline-Bearbeitung", "name-pan-zoom": "Schwenken und Zoomen", "name-text": "Text", @@ -5645,6 +5642,7 @@ "delete-read-only-file-message": "Dieses Dashboard kann nicht direkt von Grafana aus gelöscht werden, da das Repository schreibgeschützt ist. Um dieses Dashboard zu löschen, entfernen Sie bitte die Datei aus Ihrem Git-Repository.", "deleting": "Löschen...", "drawer-title": "Bereitgestelltes Dashboard löschen", + "success-message": "", "title-this-repository-is-read-only": "Dieses Repository ist schreibgeschützt" }, "description-label": { @@ -5657,9 +5655,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "Dashboard-Änderungen erfolgreich gespeichert" - }, "email-list": { "aria-label-emailmenu": "E-Mail-Menü umschalten" }, @@ -5818,6 +5813,7 @@ "usage-count_other": "Verwendet bei {{count}} Dashboards" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5827,6 +5823,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11015,6 +11012,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Diese Funktion befindet sich momentan in der aktiven Entwicklung. Für die bestmögliche Nutzererfahrung und die neuesten Verbesserungen empfehlen wir die Nutzung von <2>Nightly Build von Grafana." @@ -11874,7 +11874,7 @@ "recommended": "Empfohlen", "results": "Ergebnisse" }, - "search": "Suche" + "search": "" } }, "search": { @@ -12511,6 +12511,18 @@ "label-medium": "Mittel", "label-small": "Klein" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "Wenn dies ausgewählt ist, wird die gesamte Zeile so eingefärbt, wie es diese Zelle wäre.", "description-wrap-text": "Wenn dies ausgewählt ist, wird der Text auf die Breite des Textes in der konfigurierten Spalte umgebrochen", diff --git a/public/locales/es-ES/grafana.json b/public/locales/es-ES/grafana.json index dacff308cb7..fed89a55f7e 100644 --- a/public/locales/es-ES/grafana.json +++ b/public/locales/es-ES/grafana.json @@ -3563,12 +3563,12 @@ "tags-column": "Etiquetas" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "", "api-error": "", "button-cancel": "", "button-delete": "", "button-deleting": "", - "delete-warning": "" + "delete-warning": "", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "No se puede recuperar la información descendiente" @@ -3611,7 +3611,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Error al crear la carpeta", - "alert-folder-created-successfully": "Carpeta creada correctamente", "button-create": "Crear", "button-creating": "Creando...", "cancel": "Cancelar", @@ -3759,7 +3758,6 @@ } }, "description-experimental-types": "", - "description-infinite-panning": "", "description-inline-editing": "", "description-pan-zoom": "", "direction-options": { @@ -3860,7 +3858,6 @@ "name-align-text": "", "name-color": "", "name-experimental-types": "", - "name-infinite-panning": "", "name-inline-editing": "", "name-pan-zoom": "", "name-text": "", @@ -5645,6 +5642,7 @@ "delete-read-only-file-message": "", "deleting": "Eliminando...", "drawer-title": "", + "success-message": "", "title-this-repository-is-read-only": "Este repositorio es de solo lectura" }, "description-label": { @@ -5657,9 +5655,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "" - }, "email-list": { "aria-label-emailmenu": "Alternar menú de correo electrónico" }, @@ -5818,6 +5813,7 @@ "usage-count_other": "Utilizado en {{count}} dashboards" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5827,6 +5823,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11015,6 +11012,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Esta función se encuentra actualmente en desarrollo activo. Para obtener la mejor experiencia y las últimas mejoras, recomendamos utilizar la <2>compilación nocturna de Grafana." @@ -11874,7 +11874,7 @@ "recommended": "Recomendado", "results": "Resultados" }, - "search": "Buscar" + "search": "" } }, "search": { @@ -12511,6 +12511,18 @@ "label-medium": "", "label-small": "" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "Si se selecciona, toda la fila se coloreará como esta celda.", "description-wrap-text": "Si se selecciona, el texto se ajustará al ancho del texto en la columna configurada", diff --git a/public/locales/fr-FR/grafana.json b/public/locales/fr-FR/grafana.json index 2485164635d..4b9634936a7 100644 --- a/public/locales/fr-FR/grafana.json +++ b/public/locales/fr-FR/grafana.json @@ -3563,12 +3563,12 @@ "tags-column": "Balises" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "Dossier supprimé avec succès", "api-error": "Échec de la suppression du dossier", "button-cancel": "Annuler", "button-delete": "Supprimer", "button-deleting": "Suppression en cours…", - "delete-warning": "Cette opération supprimera ce dossier ainsi que tous ses éléments enfants. Au total, cela concernera :" + "delete-warning": "Cette opération supprimera ce dossier ainsi que tous ses éléments enfants. Au total, cela concernera :", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Impossible de récupérer les informations descendantes" @@ -3611,7 +3611,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Erreur de création du dossier", - "alert-folder-created-successfully": "Le dossier a bien été créé", "button-create": "Créer", "button-creating": "Création...", "cancel": "Annuler", @@ -3759,7 +3758,6 @@ } }, "description-experimental-types": "Activer la sélection de types d’éléments expérimentaux", - "description-infinite-panning": "Activez le panoramique infini, utile pour les canvas étendus. Avertissement : il s’agit d’une fonctionnalité expérimentale qui ne fonctionne actuellement bien qu’avec des éléments contraints en haut/à gauche", "description-inline-editing": "Activer la modification directe du panneau", "description-pan-zoom": "Activer le zoom et le déplacement", "direction-options": { @@ -3860,7 +3858,6 @@ "name-align-text": "Alignement du texte", "name-color": "Couleur du texte", "name-experimental-types": "Types d’éléments expérimentaux", - "name-infinite-panning": "Panoramique infini", "name-inline-editing": "Édition en ligne", "name-pan-zoom": "Zoom et déplacement", "name-text": "Texte", @@ -5645,6 +5642,7 @@ "delete-read-only-file-message": "Ce tableau de bord ne peut pas être supprimé directement depuis Grafana, car le dépôt est en lecture seule. Pour le supprimer, veuillez retirer le fichier de votre dépôt Git.", "deleting": "Suppression…", "drawer-title": "Supprimer le tableau de bord provisionné", + "success-message": "", "title-this-repository-is-read-only": "Ce référentiel est en lecture seule" }, "description-label": { @@ -5657,9 +5655,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "Modifications du tableau de bord enregistrées avec succès" - }, "email-list": { "aria-label-emailmenu": "Basculer vers le menu des e-mails" }, @@ -5818,6 +5813,7 @@ "usage-count_other": "Utilisé sur {{count}} tableaux de bord" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5827,6 +5823,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11015,6 +11012,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Cette fonctionnalité est actuellement en cours de développement. Pour une expérience optimale et les dernières améliorations, nous vous recommandons d’utiliser la <2>compilation nocturne de Grafana." @@ -11874,7 +11874,7 @@ "recommended": "Recommandé", "results": "Résultats" }, - "search": "Rechercher" + "search": "" } }, "search": { @@ -12511,6 +12511,18 @@ "label-medium": "Moyen", "label-small": "Petit" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "Si cette option est sélectionnée, toute la ligne sera colorée comme cette cellule.", "description-wrap-text": "Si le texte sélectionné sera ajusté à la largeur du texte dans la colonne configurée", diff --git a/public/locales/hu-HU/grafana.json b/public/locales/hu-HU/grafana.json index 5e9f8acb6d0..cc206d4e880 100644 --- a/public/locales/hu-HU/grafana.json +++ b/public/locales/hu-HU/grafana.json @@ -3563,12 +3563,12 @@ "tags-column": "Címkék" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "A mappa törlése sikeres", "api-error": "A mappa törlése nem sikerült", "button-cancel": "Mégse", "button-delete": "Törlés", "button-deleting": "Törlés...", - "delete-warning": "Ez törli ezt a mappát és minden almappáját. Összességében ez a következőket érinti:" + "delete-warning": "Ez törli ezt a mappát és minden almappáját. Összességében ez a következőket érinti:", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Nem lehet lekérni a leszármazott adatokat" @@ -3611,7 +3611,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Hiba történt a mappa létrehozása közben", - "alert-folder-created-successfully": "A mappa létrehozása sikerült", "button-create": "Létrehozás", "button-creating": "Létrehozás…", "cancel": "Mégse", @@ -3759,7 +3758,6 @@ } }, "description-experimental-types": "Kísérleti elemtípusok kiválasztásának engedélyezése", - "description-infinite-panning": "Végtelen pásztázás engedélyezése – hasznos a tágas vásznakhoz. Figyelem: ez egy kísérleti funkció, és jelenleg csak a felül/bal oldalon korlátozott elemekkel működik jól", "description-inline-editing": "A panel közvetlen szerkesztésének engedélyezése", "description-pan-zoom": "Pásztázás és nagyítás engedélyezése", "direction-options": { @@ -3860,7 +3858,6 @@ "name-align-text": "Szöveg igazítása", "name-color": "Szöveg színe", "name-experimental-types": "Kísérleti elemtípusok", - "name-infinite-panning": "Végtelen pásztázás", "name-inline-editing": "Beágyazott szerkesztés", "name-pan-zoom": "Pásztázás és nagyítás", "name-text": "Szöveg", @@ -5645,6 +5642,7 @@ "delete-read-only-file-message": "Ez az irányítópult nem törölhető közvetlenül a Grafanából, mert az adattár csak olvasható. Az irányítópult törléséhez távolítsa el a fájlt a Git-tárból.", "deleting": "Törlés...", "drawer-title": "Kiépített irányítópult törlése", + "success-message": "", "title-this-repository-is-read-only": "Ez az adattár csak olvasható" }, "description-label": { @@ -5657,9 +5655,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "Irányítópult-módosítások mentése sikeres" - }, "email-list": { "aria-label-emailmenu": "E-mail-menü ki- és bekapcsolása" }, @@ -5818,6 +5813,7 @@ "usage-count_other": "{{count}} irányítópulton használatos" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5827,6 +5823,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11015,6 +11012,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Ez a funkció jelenleg aktív fejlesztés alatt áll. A legjobb élmény és a legújabb fejlesztések érdekében javasoljuk a Grafana <2>éjszakai buildjének használatát." @@ -11874,7 +11874,7 @@ "recommended": "Ajánlott", "results": "Eredmények" }, - "search": "Keresés" + "search": "" } }, "search": { @@ -12511,6 +12511,18 @@ "label-medium": "Közepes", "label-small": "Kicsi" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "Ha ki van választva, a teljes sor olyan színű lesz, mint ez a cella.", "description-wrap-text": "Ha ki van választva, a szöveg a konfigurált oszlop szövegének szélességéhez lesz tördelve", diff --git a/public/locales/id-ID/grafana.json b/public/locales/id-ID/grafana.json index ee7e3db48e3..6cc5262ca6c 100644 --- a/public/locales/id-ID/grafana.json +++ b/public/locales/id-ID/grafana.json @@ -3544,12 +3544,12 @@ "tags-column": "Tag" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "Folder berhasil dihapus", "api-error": "Gagal menghapus folder", "button-cancel": "Batalkan", "button-delete": "Hapus", "button-deleting": "Menghapus...", - "delete-warning": "Ini akan menghapus folder ini dan semua subfoldernya. Secara keseluruhan, ini akan memengaruhi:" + "delete-warning": "Ini akan menghapus folder ini dan semua subfoldernya. Secara keseluruhan, ini akan memengaruhi:", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Tidak dapat mengambil informasi turunan" @@ -3592,7 +3592,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Kesalahan saat membuat folder", - "alert-folder-created-successfully": "Folder berhasil dibuat", "button-create": "Buat", "button-creating": "Membuat...", "cancel": "Batalkan", @@ -3740,7 +3739,6 @@ } }, "description-experimental-types": "Aktifkan pemilihan jenis elemen eksperimental", - "description-infinite-panning": "Aktifkan fitur geser tak terbatas - berguna untuk kanvas yang luas. Peringatan: ini adalah fitur eksperimental dan saat ini hanya berfungsi dengan baik dengan elemen yang dibatasi terhadap sudut atas/kiri", "description-inline-editing": "Aktifkan pengeditan panel secara langsung", "description-pan-zoom": "Aktifkan geser dan zoom", "direction-options": { @@ -3841,7 +3839,6 @@ "name-align-text": "Ratakan teks", "name-color": "Warna teks", "name-experimental-types": "Jenis elemen eksperimental", - "name-infinite-panning": "Geser tak terbatas", "name-inline-editing": "Pengeditan inline", "name-pan-zoom": "Geser dan zoom", "name-text": "Teks", @@ -5625,6 +5622,7 @@ "delete-read-only-file-message": "Dasbor ini tidak dapat dihapus langsung dari Grafana karena repositori bersifat hanya-baca. Untuk menghapus dasbor ini, harap hapus file dari repositori Git Anda.", "deleting": "Menghapus...", "drawer-title": "Hapus Dasbor yang Disediakan", + "success-message": "", "title-this-repository-is-read-only": "Repositori ini hanya dapat dibaca" }, "description-label": { @@ -5637,9 +5635,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "Perubahan dasbor berhasil disimpan" - }, "email-list": { "aria-label-emailmenu": "Alihkan tombol menu email" }, @@ -5797,6 +5792,7 @@ "usage-count_other": "Digunakan pada {{count}} dasbor" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5806,6 +5802,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -10982,6 +10979,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Fitur ini saat ini sedang dalam pengembangan aktif. Untuk pengalaman terbaik dan peningkatan terbaru, kami merekomendasikan Anda untuk menggunakan <2>versi nightly Grafana." @@ -11834,7 +11834,7 @@ "recommended": "Disarankan", "results": "Hasil" }, - "search": "Cari" + "search": "" } }, "search": { @@ -12469,6 +12469,18 @@ "label-medium": "Sedang", "label-small": "Kecil" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "Jika dipilih, seluruh baris akan berwarna seperti sel ini.", "description-wrap-text": "Jika teks yang dipilih akan dipecah sesuai lebar teks di kolom yang telah dikonfigurasi", diff --git a/public/locales/it-IT/grafana.json b/public/locales/it-IT/grafana.json index b9280ddbc9f..76a93f29384 100644 --- a/public/locales/it-IT/grafana.json +++ b/public/locales/it-IT/grafana.json @@ -3563,12 +3563,12 @@ "tags-column": "Tag" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "", "api-error": "", "button-cancel": "", "button-delete": "", "button-deleting": "", - "delete-warning": "" + "delete-warning": "", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Impossibile recuperare le informazioni sui discendenti" @@ -3611,7 +3611,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Errore durante la creazione della cartella", - "alert-folder-created-successfully": "Cartella creata con successo", "button-create": "Crea", "button-creating": "Creazione in corso...", "cancel": "Annulla", @@ -3759,7 +3758,6 @@ } }, "description-experimental-types": "", - "description-infinite-panning": "", "description-inline-editing": "", "description-pan-zoom": "", "direction-options": { @@ -3860,7 +3858,6 @@ "name-align-text": "", "name-color": "", "name-experimental-types": "", - "name-infinite-panning": "", "name-inline-editing": "", "name-pan-zoom": "", "name-text": "", @@ -5645,6 +5642,7 @@ "delete-read-only-file-message": "", "deleting": "Eliminazione in corso...", "drawer-title": "", + "success-message": "", "title-this-repository-is-read-only": "Questo repository è di sola lettura" }, "description-label": { @@ -5657,9 +5655,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "" - }, "email-list": { "aria-label-emailmenu": "Attiva/disattiva il menu e-mail" }, @@ -5818,6 +5813,7 @@ "usage-count_other": "Utilizzato su {{count}} dashboard" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5827,6 +5823,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11015,6 +11012,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Questa funzione è attualmente in fase di sviluppo attivo. Per un'esperienza ottimale e gli ultimi miglioramenti, consigliamo di utilizzare la <2>nightly build di Grafana." @@ -11874,7 +11874,7 @@ "recommended": "Consigliato", "results": "Risultati" }, - "search": "Cerca" + "search": "" } }, "search": { @@ -12511,6 +12511,18 @@ "label-medium": "", "label-small": "" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "", "description-wrap-text": "", diff --git a/public/locales/ja-JP/grafana.json b/public/locales/ja-JP/grafana.json index 9d43cef2cfb..e3c05000367 100644 --- a/public/locales/ja-JP/grafana.json +++ b/public/locales/ja-JP/grafana.json @@ -3544,12 +3544,12 @@ "tags-column": "タグ" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "フォルダが正常に削除されました", "api-error": "フォルダの削除に失敗しました", "button-cancel": "キャンセル", "button-delete": "削除", "button-deleting": "削除中…", - "delete-warning": "このフォルダとその下位のすべてのフォルダやコンテンツが削除されます。全部で、次に影響します: " + "delete-warning": "このフォルダとその下位のすべてのフォルダやコンテンツが削除されます。全部で、次に影響します: ", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "下位情報を取得できません" @@ -3592,7 +3592,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "フォルダ作成時のエラー", - "alert-folder-created-successfully": "フォルダが正常に作成されました", "button-create": "作成", "button-creating": "作成中...", "cancel": "キャンセル", @@ -3740,7 +3739,6 @@ } }, "description-experimental-types": "実験的な要素タイプの選択を有効化", - "description-infinite-panning": "制限なしのパンを有効化 - 広大なキャンバスに便利。警告: これは実験的な機能で、現在は上部/左側に固定されている要素でのみ正常に動作します", "description-inline-editing": "パネルの直接編集を有効化", "description-pan-zoom": "パンとズームを有効化", "direction-options": { @@ -3841,7 +3839,6 @@ "name-align-text": "テキストの配置", "name-color": "文字色", "name-experimental-types": "実験的な要素タイプ", - "name-infinite-panning": "制限なしのパン", "name-inline-editing": "インライン編集", "name-pan-zoom": "パンとズーム", "name-text": "テキスト", @@ -5625,6 +5622,7 @@ "delete-read-only-file-message": "リポジトリが読み取り専用のため、このダッシュボードをGrafanaから直接削除することはできません。このダッシュボードを削除するには、Gitリポジトリからファイルを削除してください。", "deleting": "削除中…", "drawer-title": "プロビジョニングされたダッシュボードを削除", + "success-message": "", "title-this-repository-is-read-only": "このリポジトリは読み取り専用です" }, "description-label": { @@ -5637,9 +5635,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "ダッシュボードの変更が正常に保存されました" - }, "email-list": { "aria-label-emailmenu": "メールメニューを切り替え" }, @@ -5797,6 +5792,7 @@ "usage-count_other": "{{count}}件のダッシュボードで使用中" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5806,6 +5802,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -10982,6 +10979,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "この機能は現在開発中です。最高の体験と最新の改善を利用するには、Grafanaの<2>ナイトリービルドの使用をお勧めします。" @@ -11834,7 +11834,7 @@ "recommended": "おすすめ", "results": "結果" }, - "search": "検索" + "search": "" } }, "search": { @@ -12469,6 +12469,18 @@ "label-medium": "中", "label-small": "小" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "選択されている場合、行全体がこのセルと同じ色で表示されます。", "description-wrap-text": "選択されている場合、テキストは設定された列のテキスト幅で折り返されます", diff --git a/public/locales/ko-KR/grafana.json b/public/locales/ko-KR/grafana.json index 06e3e47560b..324297aeb54 100644 --- a/public/locales/ko-KR/grafana.json +++ b/public/locales/ko-KR/grafana.json @@ -3544,12 +3544,12 @@ "tags-column": "태그" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "", "api-error": "", "button-cancel": "", "button-delete": "", "button-deleting": "", - "delete-warning": "" + "delete-warning": "", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "하위 정보를 검색할 수 없습니다" @@ -3592,7 +3592,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "폴더 생성 중 오류 발생", - "alert-folder-created-successfully": "폴더가 성공적으로 생성되었습니다", "button-create": "생성", "button-creating": "생성 중...", "cancel": "취소", @@ -3740,7 +3739,6 @@ } }, "description-experimental-types": "", - "description-infinite-panning": "", "description-inline-editing": "", "description-pan-zoom": "", "direction-options": { @@ -3841,7 +3839,6 @@ "name-align-text": "", "name-color": "", "name-experimental-types": "", - "name-infinite-panning": "", "name-inline-editing": "", "name-pan-zoom": "", "name-text": "", @@ -5625,6 +5622,7 @@ "delete-read-only-file-message": "", "deleting": "삭제 중…", "drawer-title": "", + "success-message": "", "title-this-repository-is-read-only": "이 리포지토리는 읽기 전용입니다." }, "description-label": { @@ -5637,9 +5635,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "" - }, "email-list": { "aria-label-emailmenu": "이메일 메뉴 토글" }, @@ -5797,6 +5792,7 @@ "usage-count_other": "{{count}}개의 대시보드에서 사용됨" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5806,6 +5802,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -10982,6 +10979,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "이 기능은 현재 적극적으로 개발 중입니다. 최상의 경험과 최신 개선 사항 적용을 위해 Grafana의 <2>야간 빌드를 사용하는 것이 좋습니다." @@ -11834,7 +11834,7 @@ "recommended": "권장", "results": "결과" }, - "search": "검색" + "search": "" } }, "search": { @@ -12469,6 +12469,18 @@ "label-medium": "", "label-small": "" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "선택하면 전체 행이 이 셀과 같은 색으로 표시됩니다.", "description-wrap-text": "선택한 텍스트가 구성된 열의 텍스트 너비에 맞게 줄 바꿈되는 경우", diff --git a/public/locales/nl-NL/grafana.json b/public/locales/nl-NL/grafana.json index c1603266c7d..17e611245de 100644 --- a/public/locales/nl-NL/grafana.json +++ b/public/locales/nl-NL/grafana.json @@ -3563,12 +3563,12 @@ "tags-column": "Tags" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "Map is verwijderd", "api-error": "Kan map niet verwijderen", "button-cancel": "Annuleren", "button-delete": "Verwijderen", "button-deleting": "Bezig met verwijderen...", - "delete-warning": "Hiermee worden deze map en alle onderliggende mappen verwijderd. In totaal heeft dit invloed op:" + "delete-warning": "Hiermee worden deze map en alle onderliggende mappen verwijderd. In totaal heeft dit invloed op:", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Kan afgeleide informatie niet ophalen" @@ -3611,7 +3611,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Er is een fout opgetreden bij het aanmaken van de map", - "alert-folder-created-successfully": "Map is gemaakt", "button-create": "Aanmaken", "button-creating": "Aanmaken...", "cancel": "Annuleren", @@ -3759,7 +3758,6 @@ } }, "description-experimental-types": "Selectie van experimentele elementtypes inschakelen", - "description-infinite-panning": "Oneindig pannen inschakelen - handig voor grote canvassen. Waarschuwing: dit is een experimentele functie en werkt momenteel alleen goed met elementen die linksboven zijn beperkt", "description-inline-editing": "Rechtstreekse bewerking van het paneel inschakelen", "description-pan-zoom": "Pan en zoom inschakelen", "direction-options": { @@ -3860,7 +3858,6 @@ "name-align-text": "Tekst uitlijnen", "name-color": "Tekstkleur", "name-experimental-types": "Experimentele elementtypes", - "name-infinite-panning": "Oneindig pannen", "name-inline-editing": "Inline bewerken", "name-pan-zoom": "Pennen en zoomen", "name-text": "Tekst", @@ -5645,6 +5642,7 @@ "delete-read-only-file-message": "Dit dashboard kan niet rechtstreeks uit Grafana worden verwijderd omdat de repository alleen-lezen is. Verwijder het bestand uit je Git-repository om dit dashboard te verwijderen.", "deleting": "Bezig met verwijderen ...", "drawer-title": "Kan provisioned dashboard niet verwijderen", + "success-message": "", "title-this-repository-is-read-only": "Deze repository is alleen-lezen" }, "description-label": { @@ -5657,9 +5655,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "Dashboardwijzigingen opgeslagen" - }, "email-list": { "aria-label-emailmenu": "E-mailmenu in-/uitschakelen" }, @@ -5818,6 +5813,7 @@ "usage-count_other": "Gebruikt op {{count}} dashboards" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5827,6 +5823,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11015,6 +11012,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Er wordt momenteel actief gewerkt aan de ontwikkeling van deze functie. Voor de beste ervaring en de nieuwste verbeteringen raden we je aan om de <2>nachtelijke versie van Grafana te gebruiken." @@ -11874,7 +11874,7 @@ "recommended": "Aanbevolen", "results": "Resultaten" }, - "search": "Zoeken" + "search": "" } }, "search": { @@ -12511,6 +12511,18 @@ "label-medium": "Medium", "label-small": "Klein" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "Indien geselecteerd, wordt de hele rij gekleurd zoals deze cel zou zijn.", "description-wrap-text": "Als geselecteerde tekst wordt teruggelopen naar de breedte van de tekst in de geconfigureerde kolom", diff --git a/public/locales/pl-PL/grafana.json b/public/locales/pl-PL/grafana.json index 94f57f04483..1456a69bc9f 100644 --- a/public/locales/pl-PL/grafana.json +++ b/public/locales/pl-PL/grafana.json @@ -3601,12 +3601,12 @@ "tags-column": "Znaczniki" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "", "api-error": "", "button-cancel": "", "button-delete": "", "button-deleting": "", - "delete-warning": "" + "delete-warning": "", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Nie można pobrać informacji o elemencie potomnym" @@ -3649,7 +3649,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Błąd podczas tworzenia folderu", - "alert-folder-created-successfully": "Folder został utworzony", "button-create": "Utwórz", "button-creating": "Tworzenie…", "cancel": "Anuluj", @@ -3797,7 +3796,6 @@ } }, "description-experimental-types": "", - "description-infinite-panning": "", "description-inline-editing": "", "description-pan-zoom": "", "direction-options": { @@ -3898,7 +3896,6 @@ "name-align-text": "", "name-color": "", "name-experimental-types": "", - "name-infinite-panning": "", "name-inline-editing": "", "name-pan-zoom": "", "name-text": "", @@ -5685,6 +5682,7 @@ "delete-read-only-file-message": "", "deleting": "Usuwanie…", "drawer-title": "", + "success-message": "", "title-this-repository-is-read-only": "To repozytorium jest tylko do odczytu" }, "description-label": { @@ -5697,9 +5695,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "" - }, "email-list": { "aria-label-emailmenu": "Menu przełączania konta e-mail" }, @@ -5860,6 +5855,7 @@ "usage-count_other": "Używane na {{count}} pulpitach" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5869,6 +5865,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11081,6 +11078,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Ta funkcja jest obecnie aktywnie rozwijana. Aby uzyskać najlepsze wrażenia i najnowsze ulepszenia, zalecamy korzystanie z <2>nocnej kompilacji aplikacji Grafana." @@ -11954,7 +11954,7 @@ "recommended": "Zalecane", "results": "Wyniki" }, - "search": "Szukaj" + "search": "" } }, "search": { @@ -12595,6 +12595,18 @@ "label-medium": "", "label-small": "" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "W przypadku zaznaczenia cały wiersz będzie kolorowy, tak jak ta komórka.", "description-wrap-text": "Jeśli zaznaczony tekst zostanie zawinięty do szerokości tekstu w skonfigurowanej kolumnie", diff --git a/public/locales/pt-BR/grafana.json b/public/locales/pt-BR/grafana.json index 4515bb35b80..fc4479dde69 100644 --- a/public/locales/pt-BR/grafana.json +++ b/public/locales/pt-BR/grafana.json @@ -3563,12 +3563,12 @@ "tags-column": "Tags" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "", "api-error": "", "button-cancel": "", "button-delete": "", "button-deleting": "", - "delete-warning": "" + "delete-warning": "", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Não é possível recuperar informações de elementos subordinados" @@ -3611,7 +3611,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Erro ao criar pasta", - "alert-folder-created-successfully": "Pasta criada com sucesso", "button-create": "Criar", "button-creating": "Criando…", "cancel": "Cancelar", @@ -3759,7 +3758,6 @@ } }, "description-experimental-types": "", - "description-infinite-panning": "", "description-inline-editing": "", "description-pan-zoom": "", "direction-options": { @@ -3860,7 +3858,6 @@ "name-align-text": "", "name-color": "", "name-experimental-types": "", - "name-infinite-panning": "", "name-inline-editing": "", "name-pan-zoom": "", "name-text": "", @@ -5645,6 +5642,7 @@ "delete-read-only-file-message": "", "deleting": "Excluindo...", "drawer-title": "", + "success-message": "", "title-this-repository-is-read-only": "Este repositório é somente leitura" }, "description-label": { @@ -5657,9 +5655,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "" - }, "email-list": { "aria-label-emailmenu": "Alternar menu de e-mail" }, @@ -5818,6 +5813,7 @@ "usage-count_other": "Usado em {{count}} painéis" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5827,6 +5823,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11015,6 +11012,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Este recurso está em desenvolvimento ativo no momento. Para ter uma melhor experiência e conferir as melhorias mais recentes, recomendamos usar a <2>compilação noturna da Grafana." @@ -11874,7 +11874,7 @@ "recommended": "Recomendado", "results": "Resultados" }, - "search": "Pesquisar" + "search": "" } }, "search": { @@ -12511,6 +12511,18 @@ "label-medium": "", "label-small": "" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "Se selecionada, toda a linha será colorida como esta célula.", "description-wrap-text": "Se selecionado, o texto será ajustado de acordo com a largura do texto na coluna configurada", diff --git a/public/locales/pt-PT/grafana.json b/public/locales/pt-PT/grafana.json index fd87d26a16b..5ed4085e358 100644 --- a/public/locales/pt-PT/grafana.json +++ b/public/locales/pt-PT/grafana.json @@ -3563,12 +3563,12 @@ "tags-column": "Etiquetas" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "", "api-error": "", "button-cancel": "", "button-delete": "", "button-deleting": "", - "delete-warning": "" + "delete-warning": "", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Não foi possível obter informações sobre os descendentes" @@ -3611,7 +3611,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Erro ao criar a pasta", - "alert-folder-created-successfully": "Pasta criada com sucesso", "button-create": "Criar", "button-creating": "A criar...", "cancel": "Cancelar", @@ -3759,7 +3758,6 @@ } }, "description-experimental-types": "", - "description-infinite-panning": "", "description-inline-editing": "", "description-pan-zoom": "", "direction-options": { @@ -3860,7 +3858,6 @@ "name-align-text": "", "name-color": "", "name-experimental-types": "", - "name-infinite-panning": "", "name-inline-editing": "", "name-pan-zoom": "", "name-text": "", @@ -5645,6 +5642,7 @@ "delete-read-only-file-message": "", "deleting": "A eliminar...", "drawer-title": "", + "success-message": "", "title-this-repository-is-read-only": "Este repositório é apenas de leitura" }, "description-label": { @@ -5657,9 +5655,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "" - }, "email-list": { "aria-label-emailmenu": "Alternar menu de e-mail" }, @@ -5818,6 +5813,7 @@ "usage-count_other": "Utilizado em {{count}} painéis de controlo" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5827,6 +5823,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11015,6 +11012,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Esta funcionalidade está atualmente em desenvolvimento ativo. Para a melhor experiência e as melhorias mais recentes, recomendamos a utilização da <2>compilação noturna da Grafana." @@ -11874,7 +11874,7 @@ "recommended": "Recomendado", "results": "Resultados" }, - "search": "Pesquisar" + "search": "" } }, "search": { @@ -12511,6 +12511,18 @@ "label-medium": "", "label-small": "" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "Se selecionado, toda a linha será colorida como esta célula seria.", "description-wrap-text": "Se o texto selecionado for ajustado à largura do texto na coluna configurada", diff --git a/public/locales/ru-RU/grafana.json b/public/locales/ru-RU/grafana.json index 01ef6fe7de1..64122595b67 100644 --- a/public/locales/ru-RU/grafana.json +++ b/public/locales/ru-RU/grafana.json @@ -3601,12 +3601,12 @@ "tags-column": "Теги" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "", "api-error": "", "button-cancel": "", "button-delete": "", "button-deleting": "", - "delete-warning": "" + "delete-warning": "", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Невозможно получить информацию о потомках" @@ -3649,7 +3649,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Ошибка при создании папки", - "alert-folder-created-successfully": "Папка создана", "button-create": "Создание", "button-creating": "Создание...", "cancel": "Отмена", @@ -3797,7 +3796,6 @@ } }, "description-experimental-types": "", - "description-infinite-panning": "", "description-inline-editing": "", "description-pan-zoom": "", "direction-options": { @@ -3898,7 +3896,6 @@ "name-align-text": "", "name-color": "", "name-experimental-types": "", - "name-infinite-panning": "", "name-inline-editing": "", "name-pan-zoom": "", "name-text": "", @@ -5685,6 +5682,7 @@ "delete-read-only-file-message": "", "deleting": "Удаление...", "drawer-title": "", + "success-message": "", "title-this-repository-is-read-only": "Репозиторий предназначен только для чтения" }, "description-label": { @@ -5697,9 +5695,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "" - }, "email-list": { "aria-label-emailmenu": "Переключить меню электронной почты" }, @@ -5860,6 +5855,7 @@ "usage-count_other": "Используется на {{count}} дашбордах" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5869,6 +5865,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11081,6 +11078,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "В настоящее время эта функция находится в стадии активной разработки. Чтобы обеспечить максимальное удобство пользования и получить доступ к последним улучшениям, рекомендуем использовать <2>ночную сборку Grafana." @@ -11954,7 +11954,7 @@ "recommended": "Рекомендуемые", "results": "Результаты" }, - "search": "Поиск" + "search": "" } }, "search": { @@ -12595,6 +12595,18 @@ "label-medium": "", "label-small": "" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "При выборе этого параметра вся строка будет окрашена аналогично этой ячейке.", "description-wrap-text": "При выборе этого параметра текст будет переноситься по ширине текста в настроенном столбце", diff --git a/public/locales/sv-SE/grafana.json b/public/locales/sv-SE/grafana.json index c25f9d8d19b..b3ef95e164c 100644 --- a/public/locales/sv-SE/grafana.json +++ b/public/locales/sv-SE/grafana.json @@ -3563,12 +3563,12 @@ "tags-column": "Taggar" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "", "api-error": "", "button-cancel": "", "button-delete": "", "button-deleting": "", - "delete-warning": "" + "delete-warning": "", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Det gick inte att hämta underordnad information" @@ -3611,7 +3611,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Fel när mapp skulle skapas", - "alert-folder-created-successfully": "Mappen skapades", "button-create": "Skapa", "button-creating": "Skapar …", "cancel": "Avbryt", @@ -3759,7 +3758,6 @@ } }, "description-experimental-types": "", - "description-infinite-panning": "", "description-inline-editing": "", "description-pan-zoom": "", "direction-options": { @@ -3860,7 +3858,6 @@ "name-align-text": "", "name-color": "", "name-experimental-types": "", - "name-infinite-panning": "", "name-inline-editing": "", "name-pan-zoom": "", "name-text": "", @@ -5645,6 +5642,7 @@ "delete-read-only-file-message": "", "deleting": "Tar bort ...", "drawer-title": "", + "success-message": "", "title-this-repository-is-read-only": "Den här databasen är skrivskyddad" }, "description-label": { @@ -5657,9 +5655,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "" - }, "email-list": { "aria-label-emailmenu": "Växla e-postmeny" }, @@ -5818,6 +5813,7 @@ "usage-count_other": "Används på {{count}} instrumentpaneler" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5827,6 +5823,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11015,6 +11012,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Den här funktionen är för närvarande under aktiv utveckling. För den bästa upplevelsen och de senaste förbättringarna rekommenderar vi att du använder <2> nightly-versionen av Grafana." @@ -11874,7 +11874,7 @@ "recommended": "Rekommenderas", "results": "Resultat" }, - "search": "Sök" + "search": "" } }, "search": { @@ -12511,6 +12511,18 @@ "label-medium": "", "label-small": "" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "Om valt kommer hela raden att färgas som denna cell skulle vara.", "description-wrap-text": "Om vald text kommer att radbrytas till textbredden i den konfigurerade kolumnen", diff --git a/public/locales/tr-TR/grafana.json b/public/locales/tr-TR/grafana.json index ae7289f7817..c0dd88f9e9e 100644 --- a/public/locales/tr-TR/grafana.json +++ b/public/locales/tr-TR/grafana.json @@ -3563,12 +3563,12 @@ "tags-column": "Etiketler" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "", "api-error": "", "button-cancel": "", "button-delete": "", "button-deleting": "", - "delete-warning": "" + "delete-warning": "", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "Alt öge bilgileri alınamıyor" @@ -3611,7 +3611,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "Klasör oluşturulurken hata oluştu", - "alert-folder-created-successfully": "Klasör başarıyla oluşturuldu", "button-create": "Oluştur", "button-creating": "Oluşturuluyor...", "cancel": "İptal", @@ -3759,7 +3758,6 @@ } }, "description-experimental-types": "", - "description-infinite-panning": "", "description-inline-editing": "", "description-pan-zoom": "", "direction-options": { @@ -3860,7 +3858,6 @@ "name-align-text": "", "name-color": "", "name-experimental-types": "", - "name-infinite-panning": "", "name-inline-editing": "", "name-pan-zoom": "", "name-text": "", @@ -5645,6 +5642,7 @@ "delete-read-only-file-message": "", "deleting": "Siliniyor...", "drawer-title": "", + "success-message": "", "title-this-repository-is-read-only": "Bu depo salt okunur" }, "description-label": { @@ -5657,9 +5655,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "" - }, "email-list": { "aria-label-emailmenu": "E-posta menüsünü aç/kapat" }, @@ -5818,6 +5813,7 @@ "usage-count_other": "{{count}} panoda kullanılıyor" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5827,6 +5823,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -11015,6 +11012,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "Bu özellik şu anda aktif geliştirme aşamasındadır. En iyi deneyim ve en yeni geliştirmeler için Grafana'nın <2>gecelik derleme sürümünü kullanmanızı öneririz." @@ -11874,7 +11874,7 @@ "recommended": "Önerilen", "results": "Sonuçlar" }, - "search": "Ara" + "search": "" } }, "search": { @@ -12511,6 +12511,18 @@ "label-medium": "", "label-small": "" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "Seçilirse tüm satır bu hücre gibi renklendirilecektir.", "description-wrap-text": "Seçilirse metin yapılandırılan sütunun metin genişliğine göre sığdırılır", diff --git a/public/locales/zh-Hans/grafana.json b/public/locales/zh-Hans/grafana.json index 6a0e7daee75..68923de4d6b 100644 --- a/public/locales/zh-Hans/grafana.json +++ b/public/locales/zh-Hans/grafana.json @@ -3544,12 +3544,12 @@ "tags-column": "标签" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "文件夹已成功删除", "api-error": "删除文件夹失败", "button-cancel": "取消", "button-delete": "删除", "button-deleting": "正在删除...", - "delete-warning": "这将删除此文件夹及其所有子文件夹。总体而言,这将影响:" + "delete-warning": "这将删除此文件夹及其所有子文件夹。总体而言,这将影响:", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "无法检索后代信息" @@ -3592,7 +3592,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "创建文件夹时出错", - "alert-folder-created-successfully": "文件夹创建成功", "button-create": "创建", "button-creating": "正在创建...", "cancel": "取消", @@ -3740,7 +3739,6 @@ } }, "description-experimental-types": "启用实验元素类型的选择", - "description-infinite-panning": "启用无限平移 - 适用于内容宽广的画布。警告:这是一项实验性功能,目前仅适用于受顶部/左侧约束的元素", "description-inline-editing": "启用直接编辑面板", "description-pan-zoom": "启用平移和缩放", "direction-options": { @@ -3841,7 +3839,6 @@ "name-align-text": "对齐文字", "name-color": "文字颜色", "name-experimental-types": "实验性元素类型", - "name-infinite-panning": "无限平移", "name-inline-editing": "嵌入式编辑", "name-pan-zoom": "平移和缩放", "name-text": "文字", @@ -5625,6 +5622,7 @@ "delete-read-only-file-message": "此数据面板无法直接从 Grafana 删除,因为存储库是只读的。要删除此数据面板,请从 Git 存储库中移除相应文件。", "deleting": "正在删除...", "drawer-title": "删除已预置的数据面板", + "success-message": "", "title-this-repository-is-read-only": "此存储库为只读" }, "description-label": { @@ -5637,9 +5635,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "数据面板更改已成功保存" - }, "email-list": { "aria-label-emailmenu": "切换电子邮件菜单" }, @@ -5797,6 +5792,7 @@ "usage-count_other": "用于 {{count}} 个数据面板" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5806,6 +5802,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -10982,6 +10979,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "此功能目前正在积极开发中。为了获得最佳体验和最新改进,我们建议您使用 Grafana 的<2>夜间版本。" @@ -11834,7 +11834,7 @@ "recommended": "推荐", "results": "结果" }, - "search": "搜索" + "search": "" } }, "search": { @@ -12469,6 +12469,18 @@ "label-medium": "中", "label-small": "小" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "如果选中,整行将按此单元格的颜色显示。", "description-wrap-text": "如果选中,文本将根据配置列的文本宽度自动换行", diff --git a/public/locales/zh-Hant/grafana.json b/public/locales/zh-Hant/grafana.json index 13ff7bc7f60..79e17eb09a4 100644 --- a/public/locales/zh-Hant/grafana.json +++ b/public/locales/zh-Hant/grafana.json @@ -3544,12 +3544,12 @@ "tags-column": "標籤" }, "delete-provisioned-folder-form": { - "alert-folder-deleted-successfully": "已成功刪除資料夾", "api-error": "無法刪除資料夾", "button-cancel": "取消", "button-delete": "刪除", "button-deleting": "正在刪除…", - "delete-warning": "這將刪除此資料夾及其所有子資料夾。總體而言,這會影響:" + "delete-warning": "這將刪除此資料夾及其所有子資料夾。總體而言,這會影響:", + "success-message": "" }, "descendant-count": { "title-unable-to-retrieve-descendant-information": "無法擷取子系資訊" @@ -3592,7 +3592,6 @@ }, "new-provisioned-folder-form": { "alert-error-creating-folder": "建立資料夾時發生錯誤", - "alert-folder-created-successfully": "已成功建立資料夾", "button-create": "建立", "button-creating": "正在建立…", "cancel": "取消", @@ -3740,7 +3739,6 @@ } }, "description-experimental-types": "啟用實驗元素類型的選擇", - "description-infinite-panning": "啟用無限平移 - 適用於寬敞的畫布。警告:這是一項實驗功能,目前僅適用於頂端/左側受限的元素", "description-inline-editing": "啟用直接編輯面板", "description-pan-zoom": "啟用平移和縮放", "direction-options": { @@ -3841,7 +3839,6 @@ "name-align-text": "對齊文字", "name-color": "文字色彩", "name-experimental-types": "實驗性元素類型", - "name-infinite-panning": "無限平移", "name-inline-editing": "直接編輯", "name-pan-zoom": "平移和縮放", "name-text": "文字", @@ -5625,6 +5622,7 @@ "delete-read-only-file-message": "由於儲存庫為唯讀,因此無法直接從 Grafana 刪除此儀表板。若要刪除此儀表板,請從您的 Git 儲存庫中移除該檔案。", "deleting": "正在刪除…", "drawer-title": "刪除已佈建的儀表板", + "success-message": "", "title-this-repository-is-read-only": "此存放庫為唯讀" }, "description-label": { @@ -5637,9 +5635,6 @@ } } }, - "edit-provisioned-dashboard-form": { - "success": "儀表板變更已成功儲存" - }, "email-list": { "aria-label-emailmenu": "切換電子郵件選單" }, @@ -5797,6 +5792,7 @@ "usage-count_other": "用於 {{count}} 個儀表板" }, "move-provisioned-dashboard-form": { + "alert-error-moving-dashboard": "", "api-error": "", "cancel-action": "", "current-file-not-found": "", @@ -5806,6 +5802,7 @@ "move-action": "", "move-read-only-message": "", "moving": "", + "success-message": "", "target-path-label": "", "title-this-repository-is-read-only": "" }, @@ -10982,6 +10979,9 @@ "title-created-branch-in-repo": "", "title-loaded-pull-request-in-repo": "" }, + "provisioned-resource-request-handler": "", + "provisioned-resource-request-handler-dashboard": "", + "provisioned-resource-request-handler-folder": "", "provisioning": { "banner": { "message": "此功能目前正在積極開發中。為了獲得最佳體驗和最新改進版本,建議使用 Grafana 的<2>夜間版本。" @@ -11834,7 +11834,7 @@ "recommended": "建議", "results": "結果" }, - "search": "搜尋" + "search": "" } }, "search": { @@ -12469,6 +12469,18 @@ "label-medium": "中", "label-small": "小" }, + "cell-types": { + "actions": "", + "auto": "", + "color-background": "", + "color-text": "", + "data-links": "", + "gauge": "", + "image": "", + "json": "", + "pill": "", + "sparkline": "" + }, "color-background-cell-options-editor": { "description-apply-to-entire-row": "若選取,整列將以此儲存格的顏色顯示。", "description-wrap-text": "若選取,文字將依配置欄位的寬度換行", From 8e1b3338c6a8fc120cf3833161139a2ff02236c5 Mon Sep 17 00:00:00 2001 From: Sam Jewell <2903904+samjewell@users.noreply.github.com> Date: Fri, 1 Aug 2025 08:55:57 +0100 Subject: [PATCH 06/89] TableNG: Improve AdHoc filter icons (#108968) We removed the "Filter for/out value" tooltips when we reimplemented the Table panel. We don't want to reimplement these, so we're improving the icons instead, to look more like "Filter" and less like "Zoom in/out" --- packages/grafana-data/src/types/icon.ts | 2 ++ .../src/components/Table/TableNG/Cells/TableCellActions.tsx | 4 ++-- public/app/core/icons/cached.json | 2 ++ public/img/icons/unicons/filter-minus.svg | 1 + public/img/icons/unicons/filter-plus.svg | 1 + 5 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 public/img/icons/unicons/filter-minus.svg create mode 100644 public/img/icons/unicons/filter-plus.svg diff --git a/packages/grafana-data/src/types/icon.ts b/packages/grafana-data/src/types/icon.ts index 0cb4a61a25b..34680fc07d1 100644 --- a/packages/grafana-data/src/types/icon.ts +++ b/packages/grafana-data/src/types/icon.ts @@ -120,6 +120,8 @@ export const availableIconsIndex = { 'file-export': true, 'file-landscape-alt': true, filter: true, + 'filter-plus': true, + 'filter-minus': true, flip: true, folder: true, font: true, diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx index c66ed4be81c..746ca7027d1 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx @@ -58,7 +58,7 @@ export function TableCellActions(props: TableCellActionsProps) { {showFilters && ( <> { onCellFilterAdded?.({ @@ -69,7 +69,7 @@ export function TableCellActions(props: TableCellActionsProps) { }} /> { onCellFilterAdded?.({ diff --git a/public/app/core/icons/cached.json b/public/app/core/icons/cached.json index ce86bef4eae..810e2676755 100644 --- a/public/app/core/icons/cached.json +++ b/public/app/core/icons/cached.json @@ -74,6 +74,8 @@ "unicons/file-alt", "unicons/file-blank", "unicons/filter", + "unicons/filter-plus", + "unicons/filter-minus", "unicons/folder", "unicons/folder-open", "unicons/folder-plus", diff --git a/public/img/icons/unicons/filter-minus.svg b/public/img/icons/unicons/filter-minus.svg new file mode 100644 index 00000000000..bf7dd01335b --- /dev/null +++ b/public/img/icons/unicons/filter-minus.svg @@ -0,0 +1 @@ + diff --git a/public/img/icons/unicons/filter-plus.svg b/public/img/icons/unicons/filter-plus.svg new file mode 100644 index 00000000000..f3180a757e0 --- /dev/null +++ b/public/img/icons/unicons/filter-plus.svg @@ -0,0 +1 @@ + From 63cc91facedf5a2b8c5043c0fff0d26d6a24aec7 Mon Sep 17 00:00:00 2001 From: ismail simsek Date: Fri, 1 Aug 2025 10:13:49 +0200 Subject: [PATCH 07/89] Prometheus: Don't use incremental querying if one of the queries has $__range variable (#108823) don't use incremental querying if one of the queries has $__range variable --- .../grafana-prometheus/src/datasource.test.ts | 70 +++++++++++++++++++ packages/grafana-prometheus/src/datasource.ts | 14 ++-- 2 files changed, 77 insertions(+), 7 deletions(-) diff --git a/packages/grafana-prometheus/src/datasource.test.ts b/packages/grafana-prometheus/src/datasource.test.ts index c5fc15d6a8f..73964477bf3 100644 --- a/packages/grafana-prometheus/src/datasource.test.ts +++ b/packages/grafana-prometheus/src/datasource.test.ts @@ -19,6 +19,7 @@ import { config, getBackendSrv, setBackendSrv, TemplateSrv } from '@grafana/runt import { extractResourceMatcher, extractRuleMappingFromGroups, PrometheusDatasource } from './datasource'; import { prometheusRegularEscape, prometheusSpecialRegexEscape } from './escaping'; import { PrometheusLanguageProviderInterface } from './language_provider'; +import { CacheRequestInfo } from './querycache/QueryCache'; import { createDataRequest, createDefaultPromResponse, @@ -1253,3 +1254,72 @@ describe('modifyQuery', () => { }); }); }); + +describe('PrometheusDatasource incremental query logic', () => { + let ds: PrometheusDatasource; + let mockCache: { + requestInfo: jest.MockedFunction<(request: DataQueryRequest) => CacheRequestInfo>; + procFrames: jest.MockedFunction<(...args: unknown[]) => unknown[]>; + }; + + beforeEach(() => { + jest.clearAllMocks(); + + mockCache = { + requestInfo: jest.fn().mockReturnValue({ + requests: [{ targets: [], range: getMockTimeRange() }], + targetSignatures: new Map(), + shouldCache: true, + }), + procFrames: jest.fn().mockReturnValue([]), + }; + + const incrementalInstanceSettings = { + url: 'proxied', + id: 1, + uid: 'ABCDEF', + access: 'proxy', + user: 'test', + password: 'mupp', + jsonData: { + customQueryParameters: '', + cacheLevel: PrometheusCacheLevel.Low, + incrementalQuerying: true, + } as Partial, + } as unknown as DataSourceInstanceSettings; + + ds = new PrometheusDatasource(incrementalInstanceSettings, templateSrvStub); + ds.cache = mockCache as unknown as typeof ds.cache; + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it('should use incremental query for normal queries when incrementalQuerying is true', async () => { + const request = createDataRequest([{ expr: 'up', refId: 'A' }]); + await lastValueFrom(ds.query(request)); + expect(mockCache.requestInfo).toHaveBeenCalled(); + }); + + it('should disable incremental query when query contains $__range', async () => { + const request = createDataRequest([{ expr: 'rate(up[$__range])', refId: 'A' }]); + await lastValueFrom(ds.query(request)); + expect(mockCache.requestInfo).not.toHaveBeenCalled(); + }); + + it('should disable incremental query when any target contains $__range', async () => { + const request = createDataRequest([ + { expr: 'up', refId: 'A' }, + { expr: 'rate(cpu[$__range])', refId: 'B' }, + ]); + await lastValueFrom(ds.query(request)); + expect(mockCache.requestInfo).not.toHaveBeenCalled(); + }); + + it('should disable incremental query for instant queries', async () => { + const request = createDataRequest([{ expr: 'up', refId: 'A', instant: true }]); + await lastValueFrom(ds.query(request)); + expect(mockCache.requestInfo).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/grafana-prometheus/src/datasource.ts b/packages/grafana-prometheus/src/datasource.ts index 1cc48500a80..2239b63be54 100644 --- a/packages/grafana-prometheus/src/datasource.ts +++ b/packages/grafana-prometheus/src/datasource.ts @@ -492,16 +492,16 @@ export class PrometheusDatasource return this.directAccessError(); } - let fullOrPartialRequest: DataQueryRequest; - let requestInfo: CacheRequestInfo | undefined = undefined; - const hasInstantQuery = request.targets.some((target) => target.instant); + // Use incremental query only if enabled and no instant queries or no $__range variables + const shouldUseIncrementalQuery = + this.hasIncrementalQuery && !request.targets.some((target) => target.instant || target.expr.includes('$__range')); - // Don't cache instant queries - if (this.hasIncrementalQuery && !hasInstantQuery) { + let fullOrPartialRequest: DataQueryRequest = request; + let requestInfo: CacheRequestInfo | undefined = undefined; + + if (shouldUseIncrementalQuery) { requestInfo = this.cache.requestInfo(request); fullOrPartialRequest = requestInfo.requests[0]; - } else { - fullOrPartialRequest = request; } const targets = fullOrPartialRequest.targets.map((target) => this.processTargetV2(target, fullOrPartialRequest)); From cc34f6033dc9c0a7d0b346441b073180e7647b19 Mon Sep 17 00:00:00 2001 From: Sven Grossmann Date: Fri, 1 Aug 2025 10:32:12 +0200 Subject: [PATCH 08/89] Assistant: Add "Assistant" menu item (#108926) * Assistant: Add "Assistant" menu item * update-workspace --- pkg/services/navtree/models.go | 1 + pkg/services/navtree/navtreeimpl/applinks.go | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/services/navtree/models.go b/pkg/services/navtree/models.go index 5514705ed9a..250b3bf8717 100644 --- a/pkg/services/navtree/models.go +++ b/pkg/services/navtree/models.go @@ -17,6 +17,7 @@ const ( WeightDashboard WeightExplore WeightDrilldown + WeightAssistant WeightAlerting WeightAlertsAndIncidents WeightAIAndML diff --git a/pkg/services/navtree/navtreeimpl/applinks.go b/pkg/services/navtree/navtreeimpl/applinks.go index 42770b6ee96..b4571c88a69 100644 --- a/pkg/services/navtree/navtreeimpl/applinks.go +++ b/pkg/services/navtree/navtreeimpl/applinks.go @@ -324,7 +324,8 @@ func (s *ServiceImpl) readNavigationSettings() { "grafana-irm-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 3, Text: "IRM"}, "grafana-oncall-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 4, Text: "OnCall"}, "grafana-incident-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 5, Text: "Incident"}, - "grafana-ml-app": {SectionID: navtree.NavIDRoot, SortWeight: navtree.WeightAIAndML, Text: "AI & machine learning", SubTitle: "Explore AI and machine learning features", Icon: "gf-ml-alt"}, + "grafana-assistant-app": {SectionID: navtree.NavIDRoot, SortWeight: navtree.WeightAssistant, Text: "Assistant", SubTitle: "AI-powered assistant for Grafana", Icon: "ai-sparkle", IsNew: true}, + "grafana-ml-app": {SectionID: navtree.NavIDRoot, SortWeight: navtree.WeightAIAndML, Text: "Machine Learning", SubTitle: "Explore AI and machine learning features", Icon: "gf-ml-alt"}, "grafana-slo-app": {SectionID: navtree.NavIDAlertsAndIncidents, SortWeight: 7}, "grafana-cloud-link-app": {SectionID: navtree.NavIDCfgPlugins, SortWeight: 3}, "grafana-costmanagementui-app": {SectionID: navtree.NavIDCfg, Text: "Cost management"}, From ce2fd8a46ffc90d8bd663736e45e202e13658234 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 09:48:39 +0100 Subject: [PATCH 09/89] Update dependency @rsdoctor/webpack-plugin to v1 (#108996) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 291 +++++++++++++++++++++++++-------------------------- 2 files changed, 145 insertions(+), 148 deletions(-) diff --git a/package.json b/package.json index 8a70fc05731..92fbbcce6d3 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "@react-types/menu": "3.10.3", "@react-types/overlays": "3.9.0", "@react-types/shared": "3.31.0", - "@rsdoctor/webpack-plugin": "^0.4.6", + "@rsdoctor/webpack-plugin": "^1.0.0", "@rtk-query/codegen-openapi": "^2.0.0", "@rtsao/plugin-proposal-class-properties": "7.0.1-patch.1", "@stylistic/eslint-plugin-ts": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index 4fd15247adf..c27ab0ec36c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -111,13 +111,14 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:7.25.7": - version: 7.25.7 - resolution: "@babel/code-frame@npm:7.25.7" +"@babel/code-frame@npm:7.26.2": + version: 7.26.2 + resolution: "@babel/code-frame@npm:7.26.2" dependencies: - "@babel/highlight": "npm:^7.25.7" + "@babel/helper-validator-identifier": "npm:^7.25.9" + js-tokens: "npm:^4.0.0" picocolors: "npm:^1.0.0" - checksum: 10/000fb8299fb35b6217d4f6c6580dcc1fa2f6c0f82d0a54b8a029966f633a8b19b490a7a906b56a94e9d8bee91c3bc44c74c44c33fb0abaa588202f6280186291 + checksum: 10/db2c2122af79d31ca916755331bb4bac96feb2b334cdaca5097a6b467fdd41963b89b14b6836a14f083de7ff887fc78fa1b3c10b14e743d33e12dbfe5ee3d223 languageName: node linkType: hard @@ -386,18 +387,6 @@ __metadata: languageName: node linkType: hard -"@babel/highlight@npm:^7.25.7": - version: 7.25.9 - resolution: "@babel/highlight@npm:7.25.9" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.25.9" - chalk: "npm:^2.4.2" - js-tokens: "npm:^4.0.0" - picocolors: "npm:^1.0.0" - checksum: 10/0d165283dd4eb312292cea8fec3ae0d376874b1885f476014f0136784ed5b564b2c2ba2d270587ed546ee92505056dab56493f7960c01c4e6394d71d1b2e7db6 - languageName: node - linkType: hard - "@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.27.2, @babel/parser@npm:^7.28.0": version: 7.28.0 resolution: "@babel/parser@npm:7.28.0" @@ -7031,55 +7020,75 @@ __metadata: languageName: node linkType: hard -"@rsdoctor/client@npm:0.4.13": - version: 0.4.13 - resolution: "@rsdoctor/client@npm:0.4.13" - checksum: 10/6eaa768eceedf76aa940fcb5980eb39f5960f4f341c13c96ecddac8abb456c8248497dfbc0d7de933d02ad837f761af93bc54d76e84dca45591a6d99f000556b +"@rsbuild/plugin-check-syntax@npm:1.3.0": + version: 1.3.0 + resolution: "@rsbuild/plugin-check-syntax@npm:1.3.0" + dependencies: + acorn: "npm:^8.14.0" + browserslist-to-es-version: "npm:^1.0.0" + htmlparser2: "npm:10.0.0" + picocolors: "npm:^1.1.1" + source-map: "npm:^0.7.4" + peerDependencies: + "@rsbuild/core": 1.x + peerDependenciesMeta: + "@rsbuild/core": + optional: true + checksum: 10/8fc3729ba91324b936cb46eaeaf6dcc2d8b45d7d00f821af3fed3c14cb38e9174d61f199236658be3ef1046231d80ecc506404f577acc0c057f94711bf10d9da languageName: node linkType: hard -"@rsdoctor/core@npm:0.4.13": - version: 0.4.13 - resolution: "@rsdoctor/core@npm:0.4.13" +"@rsdoctor/client@npm:1.1.10": + version: 1.1.10 + resolution: "@rsdoctor/client@npm:1.1.10" + checksum: 10/f741188606d5ee04d09be69325f4074d8fac2940590c70a8724c5c9fe87edf78ac9a6fc46f5541db3ca38e36acd0f7a6d6e058564656aa2a73fe76bf37b10a0c + languageName: node + linkType: hard + +"@rsdoctor/core@npm:1.1.10": + version: 1.1.10 + resolution: "@rsdoctor/core@npm:1.1.10" dependencies: - "@rsdoctor/graph": "npm:0.4.13" - "@rsdoctor/sdk": "npm:0.4.13" - "@rsdoctor/types": "npm:0.4.13" - "@rsdoctor/utils": "npm:0.4.13" - axios: "npm:^1.7.9" + "@rsbuild/plugin-check-syntax": "npm:1.3.0" + "@rsdoctor/graph": "npm:1.1.10" + "@rsdoctor/sdk": "npm:1.1.10" + "@rsdoctor/types": "npm:1.1.10" + "@rsdoctor/utils": "npm:1.1.10" + axios: "npm:^1.10.0" + browserslist-load-config: "npm:^1.0.0" enhanced-resolve: "npm:5.12.0" filesize: "npm:^10.1.6" fs-extra: "npm:^11.1.1" lodash: "npm:^4.17.21" path-browserify: "npm:1.0.1" - semver: "npm:^7.6.3" + semver: "npm:^7.7.2" source-map: "npm:^0.7.4" webpack-bundle-analyzer: "npm:^4.10.2" - checksum: 10/c105de8a0933ec7abf2104762a7db1046f0bd2c418fc67fad8315c44f22cdb5a6ec34dbcf5da24c8a698959d475f120cc598ec012870fe757fc968fbe603ced3 + checksum: 10/83373048039f6d06ae8a6e419d77c8bd4b9ed094753bb97cd40aa9fcbe6f5f41572672a1b991b5233546fc7e1dd89dadb53a180aefb6b7ad9388be05b87a366c languageName: node linkType: hard -"@rsdoctor/graph@npm:0.4.13": - version: 0.4.13 - resolution: "@rsdoctor/graph@npm:0.4.13" +"@rsdoctor/graph@npm:1.1.10": + version: 1.1.10 + resolution: "@rsdoctor/graph@npm:1.1.10" dependencies: - "@rsdoctor/types": "npm:0.4.13" - "@rsdoctor/utils": "npm:0.4.13" + "@rsdoctor/types": "npm:1.1.10" + "@rsdoctor/utils": "npm:1.1.10" lodash.unionby: "npm:^4.8.0" socket.io: "npm:4.8.1" source-map: "npm:^0.7.4" - checksum: 10/40080b9726661d51bbec931ec85376039eec9f02c6a5523eb78365dbe0c7d2f86798fa2ff7ca29c13e844c5ab686bd8b6947d064aa0caaa97b06754f8a167ea1 + checksum: 10/eb752e1ac296fdd90b657052429ed33ba7be8e67bbf29e4ba7d1ab23a5610d0d58789b13275af66c828f6bac86de7ae9942bbdae49468b2302c991695c30e9af languageName: node linkType: hard -"@rsdoctor/sdk@npm:0.4.13": - version: 0.4.13 - resolution: "@rsdoctor/sdk@npm:0.4.13" +"@rsdoctor/sdk@npm:1.1.10": + version: 1.1.10 + resolution: "@rsdoctor/sdk@npm:1.1.10" dependencies: - "@rsdoctor/client": "npm:0.4.13" - "@rsdoctor/graph": "npm:0.4.13" - "@rsdoctor/types": "npm:0.4.13" - "@rsdoctor/utils": "npm:0.4.13" + "@rsdoctor/client": "npm:1.1.10" + "@rsdoctor/graph": "npm:1.1.10" + "@rsdoctor/types": "npm:1.1.10" + "@rsdoctor/utils": "npm:1.1.10" "@types/fs-extra": "npm:^11.0.4" body-parser: "npm:1.20.3" cors: "npm:2.8.5" @@ -7088,17 +7097,17 @@ __metadata: json-cycle: "npm:^1.5.0" lodash: "npm:^4.17.21" open: "npm:^8.4.2" - serve-static: "npm:1.16.2" + sirv: "npm:2.0.4" socket.io: "npm:4.8.1" source-map: "npm:^0.7.4" - tapable: "npm:2.2.1" - checksum: 10/017cfe877952038a573d6e498dc4c5da1b0754bd5e50ccaf02e5263581a3ca901600b77b59cd9556cc9baefef8c37b0ccf5e7364342fb080c14e4b72d6005e97 + tapable: "npm:2.2.2" + checksum: 10/1451e931ef5767328af119c948071133bf2a59713d27b9b2451342607c4498996b7834476d98bb74f0c318cfd201e24061f54981cb83a05094ab5873754729ce languageName: node linkType: hard -"@rsdoctor/types@npm:0.4.13": - version: 0.4.13 - resolution: "@rsdoctor/types@npm:0.4.13" +"@rsdoctor/types@npm:1.1.10": + version: 1.1.10 + resolution: "@rsdoctor/types@npm:1.1.10" dependencies: "@types/connect": "npm:3.4.38" "@types/estree": "npm:1.0.5" @@ -7110,21 +7119,22 @@ __metadata: peerDependenciesMeta: "@rspack/core": optional: true - checksum: 10/a6e51bfc9e88779e9043d6f75420604f2839bbd7f7608a58556374ae74e7191b9a47872f9a426cf76e2e7756c8724550237398e093a415f6b8fbab84fae2dde5 + webpack: + optional: true + checksum: 10/3327b8ec1c8feab4fd326f405890c11fc33d532c176a94f2927a5b0fd4e65944e3628b58f1fe0181ed58cf04ca641f5edf130171f5897c90759bb2f1b427696d languageName: node linkType: hard -"@rsdoctor/utils@npm:0.4.13": - version: 0.4.13 - resolution: "@rsdoctor/utils@npm:0.4.13" +"@rsdoctor/utils@npm:1.1.10": + version: 1.1.10 + resolution: "@rsdoctor/utils@npm:1.1.10" dependencies: - "@babel/code-frame": "npm:7.25.7" - "@rsdoctor/types": "npm:0.4.13" + "@babel/code-frame": "npm:7.26.2" + "@rsdoctor/types": "npm:1.1.10" "@types/estree": "npm:1.0.5" acorn: "npm:^8.10.0" - acorn-import-assertions: "npm:1.9.0" + acorn-import-attributes: "npm:^1.9.5" acorn-walk: "npm:8.3.4" - chalk: "npm:^4.1.2" connect: "npm:3.7.0" deep-eql: "npm:4.1.4" envinfo: "npm:7.14.0" @@ -7133,26 +7143,27 @@ __metadata: get-port: "npm:5.1.1" json-stream-stringify: "npm:3.0.1" lines-and-columns: "npm:2.0.4" - rslog: "npm:^1.2.3" + picocolors: "npm:^1.1.1" + rslog: "npm:^1.2.8" strip-ansi: "npm:^6.0.1" - checksum: 10/e102670b4432ee0ed47cda15eef8fc90e703451f3d8c7efe8d7e4817fe92b2702b33a303b156fd5409d6abcc0c5712be3a81817dd21f09dd9a6bec5ecf1c72ef + checksum: 10/710a5cf045f26545f6854610144dd14e4d96c87a9887604429cdd14268d0903dbcd45727670b3ff91dac33fb3e2ea948006c0974db57736c146fd571f6c133c3 languageName: node linkType: hard -"@rsdoctor/webpack-plugin@npm:^0.4.6": - version: 0.4.13 - resolution: "@rsdoctor/webpack-plugin@npm:0.4.13" +"@rsdoctor/webpack-plugin@npm:^1.0.0": + version: 1.1.10 + resolution: "@rsdoctor/webpack-plugin@npm:1.1.10" dependencies: - "@rsdoctor/core": "npm:0.4.13" - "@rsdoctor/graph": "npm:0.4.13" - "@rsdoctor/sdk": "npm:0.4.13" - "@rsdoctor/types": "npm:0.4.13" - "@rsdoctor/utils": "npm:0.4.13" + "@rsdoctor/core": "npm:1.1.10" + "@rsdoctor/graph": "npm:1.1.10" + "@rsdoctor/sdk": "npm:1.1.10" + "@rsdoctor/types": "npm:1.1.10" + "@rsdoctor/utils": "npm:1.1.10" fs-extra: "npm:^11.1.1" lodash: "npm:^4.17.21" peerDependencies: webpack: 5.x - checksum: 10/f244ef8f1b28192cb766d66099e6999ba5a042d19bd1ab29f023f4844807a6a444e26a73b31a077e03c600979d5f10ec70fd1a42e9af9766b6f22241f124b990 + checksum: 10/7cca30b682137f1af3407b586359f0387a744b64d68de09aa42a36009aa36cf62c386d45f2d4d49e5b45a1d29263e019ca6062e250a0e300ad2b1579ac8dd2d6 languageName: node linkType: hard @@ -10975,15 +10986,6 @@ __metadata: languageName: node linkType: hard -"acorn-import-assertions@npm:1.9.0": - version: 1.9.0 - resolution: "acorn-import-assertions@npm:1.9.0" - peerDependencies: - acorn: ^8 - checksum: 10/af8dd58f6b0c6a43e85849744534b99f2133835c6fcdabda9eea27d0a0da625a0d323c4793ba7cb25cf4507609d0f747c210ccc2fc9b5866de04b0e59c9c5617 - languageName: node - linkType: hard - "acorn-import-attributes@npm:^1.9.5": version: 1.9.5 resolution: "acorn-import-attributes@npm:1.9.5" @@ -11020,7 +11022,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.10.0, acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.0, acorn@npm:^8.8.2": +"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.10.0, acorn@npm:^8.11.0, acorn@npm:^8.14.0, acorn@npm:^8.15.0, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.0, acorn@npm:^8.8.2": version: 8.15.0 resolution: "acorn@npm:8.15.0" bin: @@ -11764,7 +11766,7 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1, axios@npm:^1.6.1, axios@npm:^1.7.9, axios@npm:^1.8.3, axios@npm:^1.9.0": +"axios@npm:^1, axios@npm:^1.10.0, axios@npm:^1.6.1, axios@npm:^1.8.3, axios@npm:^1.9.0": version: 1.11.0 resolution: "axios@npm:1.11.0" dependencies: @@ -12316,6 +12318,22 @@ __metadata: languageName: node linkType: hard +"browserslist-load-config@npm:^1.0.0": + version: 1.0.0 + resolution: "browserslist-load-config@npm:1.0.0" + checksum: 10/6326ef0cddf3d92816aec0a066eda53be769ea55cc1c85cb016935a8976fec7e3351d1c4f7b5a053252c29394a50cd9013de351f4af533b94960d4493c448f08 + languageName: node + linkType: hard + +"browserslist-to-es-version@npm:^1.0.0": + version: 1.1.0 + resolution: "browserslist-to-es-version@npm:1.1.0" + dependencies: + browserslist: "npm:^4.25.1" + checksum: 10/5e5bfbd290d4f8e30b2341f0b9c0171dc72359340aef9956aa4db60eb2b1659f2f9e0bbd34e5854901a9b985d1a1a5088bde6f0b26faf3c9c2fe41f2287bb68f + languageName: node + linkType: hard + "browserslist@npm:^4.0.0, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.24.0, browserslist@npm:^4.24.4, browserslist@npm:^4.24.5, browserslist@npm:^4.25.1": version: 4.25.1 resolution: "browserslist@npm:4.25.1" @@ -15283,14 +15301,14 @@ __metadata: languageName: node linkType: hard -"domutils@npm:^3.0.1, domutils@npm:^3.1.0": - version: 3.1.0 - resolution: "domutils@npm:3.1.0" +"domutils@npm:^3.0.1, domutils@npm:^3.1.0, domutils@npm:^3.2.1": + version: 3.2.2 + resolution: "domutils@npm:3.2.2" dependencies: dom-serializer: "npm:^2.0.0" domelementtype: "npm:^2.3.0" domhandler: "npm:^5.0.3" - checksum: 10/9a169a6e57ac4c738269a73ab4caf785114ed70e46254139c1bbc8144ac3102aacb28a6149508395ae34aa5d6a40081f4fa5313855dc8319c6d8359866b6dfea + checksum: 10/2e08842151aa406f50fe5e6d494f4ec73c2373199fa00d1f77b56ec604e566b7f226312ae35ab8160bb7f27a27c7285d574c8044779053e499282ca9198be210 languageName: node linkType: hard @@ -15467,7 +15485,7 @@ __metadata: languageName: node linkType: hard -"encodeurl@npm:^2.0.0, encodeurl@npm:~2.0.0": +"encodeurl@npm:^2.0.0": version: 2.0.0 resolution: "encodeurl@npm:2.0.0" checksum: 10/abf5cd51b78082cf8af7be6785813c33b6df2068ce5191a40ca8b1afe6a86f9230af9a9ce694a5ce4665955e5c1120871826df9c128a642e09c58d592e2807fe @@ -15616,6 +15634,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^6.0.0": + version: 6.0.1 + resolution: "entities@npm:6.0.1" + checksum: 10/62af1307202884349d2867f0aac5c60d8b57102ea0b0e768b16246099512c28e239254ad772d6834e7e14cb1b6f153fc3d0c031934e3183b086c86d3838d874a + languageName: node + linkType: hard + "env-paths@npm:^2.2.0, env-paths@npm:^2.2.1": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -16496,7 +16521,7 @@ __metadata: languageName: node linkType: hard -"etag@npm:^1.8.1, etag@npm:~1.8.1": +"etag@npm:^1.8.1": version: 1.8.1 resolution: "etag@npm:1.8.1" checksum: 10/571aeb3dbe0f2bbd4e4fadbdb44f325fc75335cd5f6f6b6a091e6a06a9f25ed5392f0863c5442acb0646787446e816f13cbfc6edce5b07658541dff573cab1ff @@ -17395,13 +17420,6 @@ __metadata: languageName: node linkType: hard -"fresh@npm:0.5.2": - version: 0.5.2 - resolution: "fresh@npm:0.5.2" - checksum: 10/64c88e489b5d08e2f29664eb3c79c705ff9a8eb15d3e597198ef76546d4ade295897a44abb0abd2700e7ef784b2e3cbf1161e4fbf16f59129193fd1030d16da1 - languageName: node - linkType: hard - "fresh@npm:^2.0.0": version: 2.0.0 resolution: "fresh@npm:2.0.0" @@ -18271,7 +18289,7 @@ __metadata: "@react-types/overlays": "npm:3.9.0" "@react-types/shared": "npm:3.31.0" "@reduxjs/toolkit": "npm:2.8.2" - "@rsdoctor/webpack-plugin": "npm:^0.4.6" + "@rsdoctor/webpack-plugin": "npm:^1.0.0" "@rtk-query/codegen-openapi": "npm:^2.0.0" "@rtsao/plugin-proposal-class-properties": "npm:7.0.1-patch.1" "@stylistic/eslint-plugin-ts": "npm:^4.0.0" @@ -19026,6 +19044,18 @@ __metadata: languageName: node linkType: hard +"htmlparser2@npm:10.0.0": + version: 10.0.0 + resolution: "htmlparser2@npm:10.0.0" + dependencies: + domelementtype: "npm:^2.3.0" + domhandler: "npm:^5.0.3" + domutils: "npm:^3.2.1" + entities: "npm:^6.0.0" + checksum: 10/768870f0e020dca19dc45df206cb6ac466c5dba6566c8fca4ca880347eed409f9977028d08644ac516bca8628ac9c7ded5a3847dc3ee1c043f049abf9e817154 + languageName: node + linkType: hard + "htmlparser2@npm:^3.9.2": version: 3.10.1 resolution: "htmlparser2@npm:3.10.1" @@ -22825,15 +22855,6 @@ __metadata: languageName: node linkType: hard -"mime@npm:1.6.0, mime@npm:^1.6.0": - version: 1.6.0 - resolution: "mime@npm:1.6.0" - bin: - mime: cli.js - checksum: 10/b7d98bb1e006c0e63e2c91b590fe1163b872abf8f7ef224d53dd31499c2197278a6d3d0864c45239b1a93d22feaf6f9477e9fc847eef945838150b8c02d03170 - languageName: node - linkType: hard - "mime@npm:3": version: 3.0.0 resolution: "mime@npm:3.0.0" @@ -22843,6 +22864,15 @@ __metadata: languageName: node linkType: hard +"mime@npm:^1.6.0": + version: 1.6.0 + resolution: "mime@npm:1.6.0" + bin: + mime: cli.js + checksum: 10/b7d98bb1e006c0e63e2c91b590fe1163b872abf8f7ef224d53dd31499c2197278a6d3d0864c45239b1a93d22feaf6f9477e9fc847eef945838150b8c02d03170 + languageName: node + linkType: hard + "mimic-fn@npm:^2.1.0": version: 2.1.0 resolution: "mimic-fn@npm:2.1.0" @@ -23314,7 +23344,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3": +"ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: 10/aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -26542,7 +26572,7 @@ __metadata: languageName: node linkType: hard -"range-parser@npm:^1.2.1, range-parser@npm:~1.2.1": +"range-parser@npm:^1.2.1": version: 1.2.1 resolution: "range-parser@npm:1.2.1" checksum: 10/ce21ef2a2dd40506893157970dc76e835c78cf56437e26e19189c48d5291e7279314477b06ac38abd6a401b661a6840f7b03bd0b1249da9b691deeaa15872c26 @@ -28520,10 +28550,10 @@ __metadata: languageName: node linkType: hard -"rslog@npm:^1.2.3": - version: 1.2.3 - resolution: "rslog@npm:1.2.3" - checksum: 10/b655304394dba95b83e3b932c3788a5a9f408c113a25b5fd08950904f1f80476fc049c67744bc427837d47dfb1fc0a9a0b48cfd7c21f536bb6cb8d86d46f90e8 +"rslog@npm:^1.2.8": + version: 1.2.9 + resolution: "rslog@npm:1.2.9" + checksum: 10/f8c1d890049671aa73fa9c5682befd756c76fcfe885841ca3d6e1167edf1798a890dd57fb94a1493de7c7d28b41a9e42119dd9a483495acaa666ac04f149ee86 languageName: node linkType: hard @@ -28842,27 +28872,6 @@ __metadata: languageName: node linkType: hard -"send@npm:0.19.0": - version: 0.19.0 - resolution: "send@npm:0.19.0" - dependencies: - debug: "npm:2.6.9" - depd: "npm:2.0.0" - destroy: "npm:1.2.0" - encodeurl: "npm:~1.0.2" - escape-html: "npm:~1.0.3" - etag: "npm:~1.8.1" - fresh: "npm:0.5.2" - http-errors: "npm:2.0.0" - mime: "npm:1.6.0" - ms: "npm:2.1.3" - on-finished: "npm:2.4.1" - range-parser: "npm:~1.2.1" - statuses: "npm:2.0.1" - checksum: 10/1f6064dea0ae4cbe4878437aedc9270c33f2a6650a77b56a16b62d057527f2766d96ee282997dd53ec0339082f2aad935bc7d989b46b48c82fc610800dc3a1d0 - languageName: node - linkType: hard - "send@npm:^1.1.0, send@npm:^1.2.0": version: 1.2.0 resolution: "send@npm:1.2.0" @@ -28911,18 +28920,6 @@ __metadata: languageName: node linkType: hard -"serve-static@npm:1.16.2": - version: 1.16.2 - resolution: "serve-static@npm:1.16.2" - dependencies: - encodeurl: "npm:~2.0.0" - escape-html: "npm:~1.0.3" - parseurl: "npm:~1.3.3" - send: "npm:0.19.0" - checksum: 10/7fa9d9c68090f6289976b34fc13c50ac8cd7f16ae6bce08d16459300f7fc61fbc2d7ebfa02884c073ec9d6ab9e7e704c89561882bbe338e99fcacb2912fde737 - languageName: node - linkType: hard - "serve-static@npm:^2.2.0": version: 2.2.0 resolution: "serve-static@npm:2.2.0" @@ -29197,7 +29194,7 @@ __metadata: languageName: node linkType: hard -"sirv@npm:^2.0.3": +"sirv@npm:2.0.4, sirv@npm:^2.0.3": version: 2.0.4 resolution: "sirv@npm:2.0.4" dependencies: @@ -30567,10 +30564,10 @@ __metadata: languageName: node linkType: hard -"tapable@npm:2.2.1, tapable@npm:^2.0.0, tapable@npm:^2.1.1, tapable@npm:^2.2.0, tapable@npm:^2.2.1": - version: 2.2.1 - resolution: "tapable@npm:2.2.1" - checksum: 10/1769336dd21481ae6347611ca5fca47add0962fd8e80466515032125eca0084a4f0ede11e65341b9c0018ef4e1cf1ad820adbb0fba7cc99865c6005734000b0a +"tapable@npm:2.2.2, tapable@npm:^2.0.0, tapable@npm:^2.1.1, tapable@npm:^2.2.0, tapable@npm:^2.2.1": + version: 2.2.2 + resolution: "tapable@npm:2.2.2" + checksum: 10/065a0dc44aba1b32020faa1c27c719e8f76e5345347515d8494bf158524f36e9f22ad9eaa5b5494f9d5d67bf0640afdd5698505948c46d720b6b7e69d19349a6 languageName: node linkType: hard From bfa6bb02646e92c97248a8d585ef774c86696ec8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 11:24:38 +0100 Subject: [PATCH 10/89] Update dependency typescript to v5.9.2 (#109025) * Update dependency typescript to v5.9.2 * remove unused ts-expect-error --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Ashley Harrison --- package.json | 2 +- packages/grafana-alerting/package.json | 2 +- packages/grafana-data/package.json | 2 +- packages/grafana-e2e-selectors/package.json | 2 +- packages/grafana-flamegraph/package.json | 2 +- packages/grafana-i18n/package.json | 2 +- .../grafana-o11y-ds-frontend/package.json | 2 +- packages/grafana-plugin-configs/package.json | 2 +- packages/grafana-prometheus/package.json | 2 +- packages/grafana-runtime/package.json | 2 +- packages/grafana-schema/package.json | 2 +- packages/grafana-sql/package.json | 2 +- packages/grafana-test-utils/package.json | 2 +- packages/grafana-ui/package.json | 2 +- .../logs/components/LogRowMenuCell.tsx | 1 - .../datasource/azuremonitor/package.json | 2 +- .../datasource/cloud-monitoring/package.json | 2 +- .../package.json | 2 +- .../grafana-pyroscope-datasource/package.json | 2 +- .../grafana-testdata-datasource/package.json | 2 +- .../plugins/datasource/jaeger/package.json | 2 +- .../app/plugins/datasource/loki/package.json | 2 +- .../app/plugins/datasource/mssql/package.json | 2 +- .../app/plugins/datasource/mysql/package.json | 2 +- .../app/plugins/datasource/parca/package.json | 2 +- .../app/plugins/datasource/tempo/package.json | 2 +- .../plugins/datasource/zipkin/package.json | 2 +- yarn.lock | 68 +++++++++---------- 28 files changed, 60 insertions(+), 61 deletions(-) diff --git a/package.json b/package.json index 92fbbcce6d3..5d74735f039 100644 --- a/package.json +++ b/package.json @@ -250,7 +250,7 @@ "tracelib": "1.0.1", "ts-jest": "29.4.0", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0", "webpack-assets-manifest": "^5.1.0", "webpack-cli": "6.0.1", diff --git a/packages/grafana-alerting/package.json b/packages/grafana-alerting/package.json index a777abcc684..27ba36f953a 100644 --- a/packages/grafana-alerting/package.json +++ b/packages/grafana-alerting/package.json @@ -78,7 +78,7 @@ "rollup-plugin-esbuild": "6.2.1", "rollup-plugin-node-externals": "^8.0.0", "type-fest": "^4.40.0", - "typescript": "5.8.3" + "typescript": "5.9.2" }, "peerDependencies": { "@grafana/runtime": ">=11.6 <= 12.x", diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index 10a5d2e046f..77cbb8f36d6 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -100,7 +100,7 @@ "rollup": "^4.22.4", "rollup-plugin-esbuild": "6.2.1", "rollup-plugin-node-externals": "^8.0.0", - "typescript": "5.8.3" + "typescript": "5.9.2" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/grafana-e2e-selectors/package.json b/packages/grafana-e2e-selectors/package.json index 2e5dd9f65a4..bc25b3d1bb3 100644 --- a/packages/grafana-e2e-selectors/package.json +++ b/packages/grafana-e2e-selectors/package.json @@ -52,6 +52,6 @@ "@grafana/tsconfig": "^2.0.0", "semver": "^7.7.0", "tslib": "2.8.1", - "typescript": "5.8.3" + "typescript": "5.9.2" } } diff --git a/packages/grafana-flamegraph/package.json b/packages/grafana-flamegraph/package.json index 3152966e799..c25abdd0104 100644 --- a/packages/grafana-flamegraph/package.json +++ b/packages/grafana-flamegraph/package.json @@ -81,7 +81,7 @@ "rollup-plugin-node-externals": "^8.0.0", "ts-jest": "29.4.0", "ts-node": "10.9.2", - "typescript": "5.8.3" + "typescript": "5.9.2" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/grafana-i18n/package.json b/packages/grafana-i18n/package.json index 6ffd95918f4..036a63834e4 100644 --- a/packages/grafana-i18n/package.json +++ b/packages/grafana-i18n/package.json @@ -67,7 +67,7 @@ "@types/react": "18.3.18", "rollup": "^4.22.4", "rollup-plugin-copy": "3.5.0", - "typescript": "5.8.3" + "typescript": "5.9.2" }, "peerDependencies": { "react": ">=18" diff --git a/packages/grafana-o11y-ds-frontend/package.json b/packages/grafana-o11y-ds-frontend/package.json index 11ef5bdce98..e2fef5480c2 100644 --- a/packages/grafana-o11y-ds-frontend/package.json +++ b/packages/grafana-o11y-ds-frontend/package.json @@ -43,7 +43,7 @@ "react": "18.3.1", "ts-jest": "29.4.0", "ts-node": "10.9.2", - "typescript": "5.8.3" + "typescript": "5.9.2" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/grafana-plugin-configs/package.json b/packages/grafana-plugin-configs/package.json index a2edd65dd30..7d068121b19 100644 --- a/packages/grafana-plugin-configs/package.json +++ b/packages/grafana-plugin-configs/package.json @@ -25,7 +25,7 @@ "jest-environment-jsdom": "29.7.0", "replace-in-file-webpack-plugin": "1.0.6", "swc-loader": "0.2.6", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0", "webpack-bundle-analyzer": "^4.10.2", "webpack-virtual-modules": "^0.6.2" diff --git a/packages/grafana-prometheus/package.json b/packages/grafana-prometheus/package.json index b75ebc36f99..8dc8f8a9a78 100644 --- a/packages/grafana-prometheus/package.json +++ b/packages/grafana-prometheus/package.json @@ -102,7 +102,7 @@ "rollup-plugin-esbuild": "6.2.1", "rollup-plugin-node-externals": "^8.0.0", "testing-library-selector": "0.3.1", - "typescript": "5.8.3" + "typescript": "5.9.2" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/grafana-runtime/package.json b/packages/grafana-runtime/package.json index f32cc4639da..dfae8069cfe 100644 --- a/packages/grafana-runtime/package.json +++ b/packages/grafana-runtime/package.json @@ -87,7 +87,7 @@ "rollup-plugin-esbuild": "6.2.1", "rollup-plugin-node-externals": "^8.0.0", "rollup-plugin-sourcemaps": "0.6.3", - "typescript": "5.8.3" + "typescript": "5.9.2" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/grafana-schema/package.json b/packages/grafana-schema/package.json index 9896376d716..ef7cc40d4c5 100644 --- a/packages/grafana-schema/package.json +++ b/packages/grafana-schema/package.json @@ -44,7 +44,7 @@ "rollup": "^4.22.4", "rollup-plugin-esbuild": "6.2.1", "rollup-plugin-node-externals": "^8.0.0", - "typescript": "5.8.3" + "typescript": "5.9.2" }, "dependencies": { "tslib": "2.8.1" diff --git a/packages/grafana-sql/package.json b/packages/grafana-sql/package.json index e99c2f9a737..e045f423bd5 100644 --- a/packages/grafana-sql/package.json +++ b/packages/grafana-sql/package.json @@ -53,7 +53,7 @@ "jest": "^29.6.4", "ts-jest": "29.4.0", "ts-node": "10.9.2", - "typescript": "5.8.3" + "typescript": "5.9.2" }, "peerDependencies": { "@grafana/runtime": "10.4.0-pre" diff --git a/packages/grafana-test-utils/package.json b/packages/grafana-test-utils/package.json index fe04697966f..99eedba93d4 100644 --- a/packages/grafana-test-utils/package.json +++ b/packages/grafana-test-utils/package.json @@ -62,6 +62,6 @@ "@types/jest": "29.5.14", "@types/node": "22.17.0", "jest": "29.7.0", - "typescript": "5.8.3" + "typescript": "5.9.2" } } diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 2193c02d0e8..dfb0c9754ea 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -203,7 +203,7 @@ "sass-loader": "16.0.5", "storybook": "^8.6.2", "style-loader": "4.0.0", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/public/app/features/logs/components/LogRowMenuCell.tsx b/public/app/features/logs/components/LogRowMenuCell.tsx index 2e3699733fd..892a5eea68b 100644 --- a/public/app/features/logs/components/LogRowMenuCell.tsx +++ b/public/app/features/logs/components/LogRowMenuCell.tsx @@ -194,7 +194,6 @@ function addClickListenersToNode(nodes: ReactNode[], row: LogRowModel) { return node; } return cloneElement(node, { - // @ts-expect-error onClick: (event: MouseEvent) => { onClick(event, row); }, diff --git a/public/app/plugins/datasource/azuremonitor/package.json b/public/app/plugins/datasource/azuremonitor/package.json index 056b8688f35..7e171898989 100644 --- a/public/app/plugins/datasource/azuremonitor/package.json +++ b/public/app/plugins/datasource/azuremonitor/package.json @@ -42,7 +42,7 @@ "jest": "29.7.0", "react-select-event": "5.5.1", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/public/app/plugins/datasource/cloud-monitoring/package.json b/public/app/plugins/datasource/cloud-monitoring/package.json index 7181c557951..538804b9904 100644 --- a/public/app/plugins/datasource/cloud-monitoring/package.json +++ b/public/app/plugins/datasource/cloud-monitoring/package.json @@ -42,7 +42,7 @@ "jest": "29.7.0", "react-select-event": "5.5.1", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/public/app/plugins/datasource/grafana-postgresql-datasource/package.json b/public/app/plugins/datasource/grafana-postgresql-datasource/package.json index 40ca80efa0b..8c50ca4f3ee 100644 --- a/public/app/plugins/datasource/grafana-postgresql-datasource/package.json +++ b/public/app/plugins/datasource/grafana-postgresql-datasource/package.json @@ -27,7 +27,7 @@ "@types/react": "18.3.18", "jest": "29.7.0", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json b/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json index 612b26365b0..974cfaa729f 100644 --- a/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json +++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json @@ -35,7 +35,7 @@ "jest": "29.7.0", "style-loader": "4.0.0", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/public/app/plugins/datasource/grafana-testdata-datasource/package.json b/public/app/plugins/datasource/grafana-testdata-datasource/package.json index aafaa01cfb5..641fe7cea96 100644 --- a/public/app/plugins/datasource/grafana-testdata-datasource/package.json +++ b/public/app/plugins/datasource/grafana-testdata-datasource/package.json @@ -36,7 +36,7 @@ "@types/uuid": "10.0.0", "jest": "29.7.0", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/public/app/plugins/datasource/jaeger/package.json b/public/app/plugins/datasource/jaeger/package.json index 7733e2817ef..052ccac2b5b 100644 --- a/public/app/plugins/datasource/jaeger/package.json +++ b/public/app/plugins/datasource/jaeger/package.json @@ -38,7 +38,7 @@ "@types/uuid": "10.0.0", "jest": "29.7.0", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/public/app/plugins/datasource/loki/package.json b/public/app/plugins/datasource/loki/package.json index 937fba60812..d34f48d7c34 100644 --- a/public/app/plugins/datasource/loki/package.json +++ b/public/app/plugins/datasource/loki/package.json @@ -39,7 +39,7 @@ "@types/uuid": "10.0.0", "jest": "29.7.0", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/public/app/plugins/datasource/mssql/package.json b/public/app/plugins/datasource/mssql/package.json index 48940aedbdd..8a2bfadaa02 100644 --- a/public/app/plugins/datasource/mssql/package.json +++ b/public/app/plugins/datasource/mssql/package.json @@ -28,7 +28,7 @@ "@types/react": "18.3.18", "i18next-parser": "9.3.0", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/public/app/plugins/datasource/mysql/package.json b/public/app/plugins/datasource/mysql/package.json index b8bcf1e9e14..7e03ed499fb 100644 --- a/public/app/plugins/datasource/mysql/package.json +++ b/public/app/plugins/datasource/mysql/package.json @@ -27,7 +27,7 @@ "@types/react": "18.3.18", "jest": "29.7.0", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/public/app/plugins/datasource/parca/package.json b/public/app/plugins/datasource/parca/package.json index a3c421b7a16..d4785ed9846 100644 --- a/public/app/plugins/datasource/parca/package.json +++ b/public/app/plugins/datasource/parca/package.json @@ -28,7 +28,7 @@ "@types/react-dom": "18.3.5", "jest": "29.7.0", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/public/app/plugins/datasource/tempo/package.json b/public/app/plugins/datasource/tempo/package.json index 7afedbaff53..cc592a1f15f 100644 --- a/public/app/plugins/datasource/tempo/package.json +++ b/public/app/plugins/datasource/tempo/package.json @@ -55,7 +55,7 @@ "jest": "29.7.0", "react-select-event": "5.5.1", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/public/app/plugins/datasource/zipkin/package.json b/public/app/plugins/datasource/zipkin/package.json index bb336e2173d..fb9bbf0ef7b 100644 --- a/public/app/plugins/datasource/zipkin/package.json +++ b/public/app/plugins/datasource/zipkin/package.json @@ -31,7 +31,7 @@ "@types/react-dom": "18.3.5", "jest": "29.7.0", "ts-node": "10.9.2", - "typescript": "5.8.3", + "typescript": "5.9.2", "webpack": "5.101.0" }, "peerDependencies": { diff --git a/yarn.lock b/yarn.lock index c27ab0ec36c..a0ac7fc9772 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2571,7 +2571,7 @@ __metadata: rxjs: "npm:7.8.2" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" webpack: "npm:5.101.0" peerDependencies: "@grafana/runtime": "*" @@ -2603,7 +2603,7 @@ __metadata: rxjs: "npm:7.8.2" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" webpack: "npm:5.101.0" peerDependencies: "@grafana/runtime": "*" @@ -2643,7 +2643,7 @@ __metadata: style-loader: "npm:4.0.0" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" webpack: "npm:5.101.0" peerDependencies: "@grafana/runtime": "*" @@ -2683,7 +2683,7 @@ __metadata: rxjs: "npm:7.8.2" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" uuid: "npm:11.1.0" webpack: "npm:5.101.0" peerDependencies: @@ -2726,7 +2726,7 @@ __metadata: stream-browserify: "npm:3.0.0" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" uuid: "npm:11.1.0" webpack: "npm:5.101.0" peerDependencies: @@ -2770,7 +2770,7 @@ __metadata: rxjs: "npm:7.8.2" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" uuid: "npm:11.1.0" webpack: "npm:5.101.0" peerDependencies: @@ -2804,7 +2804,7 @@ __metadata: rxjs: "npm:7.8.2" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" webpack: "npm:5.101.0" peerDependencies: "@grafana/runtime": "*" @@ -2836,7 +2836,7 @@ __metadata: rxjs: "npm:7.8.2" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" webpack: "npm:5.101.0" peerDependencies: "@grafana/runtime": "*" @@ -2869,7 +2869,7 @@ __metadata: rxjs: "npm:7.8.2" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" webpack: "npm:5.101.0" peerDependencies: "@grafana/runtime": "*" @@ -2916,7 +2916,7 @@ __metadata: rxjs: "npm:7.8.2" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" webpack: "npm:5.101.0" peerDependencies: "@grafana/runtime": "*" @@ -2975,7 +2975,7 @@ __metadata: string_decoder: "npm:1.3.0" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" uuid: "npm:11.1.0" webpack: "npm:5.101.0" peerDependencies: @@ -3012,7 +3012,7 @@ __metadata: rxjs: "npm:7.8.2" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" webpack: "npm:5.101.0" peerDependencies: "@grafana/runtime": "*" @@ -3043,7 +3043,7 @@ __metadata: rollup-plugin-esbuild: "npm:6.2.1" rollup-plugin-node-externals: "npm:^8.0.0" type-fest: "npm:^4.40.0" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" peerDependencies: "@grafana/runtime": ">=11.6 <= 12.x" "@grafana/ui": ">=11.6 <= 12.x" @@ -3143,7 +3143,7 @@ __metadata: string-hash: "npm:^1.1.3" tinycolor2: "npm:1.6.0" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" uplot: "npm:1.6.32" xss: "npm:^1.0.14" peerDependencies: @@ -3167,7 +3167,7 @@ __metadata: rollup-plugin-node-externals: "npm:^8.0.0" semver: "npm:^7.7.0" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" languageName: unknown linkType: soft @@ -3285,7 +3285,7 @@ __metadata: ts-jest: "npm:29.4.0" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" peerDependencies: react: ^18.0.0 react-dom: ^18.0.0 @@ -3320,7 +3320,7 @@ __metadata: react-i18next: "npm:^15.0.0" rollup: "npm:^4.22.4" rollup-plugin-copy: "npm:3.5.0" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" peerDependencies: react: ">=18" languageName: unknown @@ -3398,7 +3398,7 @@ __metadata: ts-jest: "npm:29.4.0" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" peerDependencies: react: ^18.0.0 react-dom: ^18.0.0 @@ -3427,7 +3427,7 @@ __metadata: replace-in-file-webpack-plugin: "npm:1.0.6" swc-loader: "npm:0.2.6" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" webpack: "npm:5.101.0" webpack-bundle-analyzer: "npm:^4.10.2" webpack-virtual-modules: "npm:^0.6.2" @@ -3540,7 +3540,7 @@ __metadata: rxjs: "npm:7.8.2" semver: "npm:7.7.2" testing-library-selector: "npm:0.3.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" uuid: "npm:11.1.0" peerDependencies: react: ^18.0.0 @@ -3583,7 +3583,7 @@ __metadata: rollup-plugin-sourcemaps: "npm:0.6.3" rxjs: "npm:7.8.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" peerDependencies: react: ^18.0.0 react-dom: ^18.0.0 @@ -3649,7 +3649,7 @@ __metadata: rollup-plugin-esbuild: "npm:6.2.1" rollup-plugin-node-externals: "npm:^8.0.0" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" languageName: unknown linkType: soft @@ -3692,7 +3692,7 @@ __metadata: ts-jest: "npm:29.4.0" ts-node: "npm:10.9.2" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" uuid: "npm:11.1.0" peerDependencies: "@grafana/runtime": 10.4.0-pre @@ -3710,7 +3710,7 @@ __metadata: "@types/node": "npm:22.17.0" jest: "npm:29.7.0" msw: "npm:2.10.4" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" languageName: unknown linkType: soft @@ -3860,7 +3860,7 @@ __metadata: style-loader: "npm:4.0.0" tinycolor2: "npm:1.6.0" tslib: "npm:2.8.1" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" uplot: "npm:1.6.32" uuid: "npm:11.1.0" uwrap: "npm:0.1.2" @@ -18547,7 +18547,7 @@ __metadata: tslib: "npm:2.8.1" tween-functions: "npm:^1.2.0" type-fest: "npm:^4.18.2" - typescript: "npm:5.8.3" + typescript: "npm:5.9.2" uplot: "npm:1.6.32" uuid: "npm:11.1.0" vis-data: "npm:^8.0.0" @@ -31588,13 +31588,13 @@ __metadata: languageName: node linkType: hard -"typescript@npm:5.8.3, typescript@npm:>=2.7, typescript@npm:>=3 < 6, typescript@npm:^5.0.4, typescript@npm:^5.4.5, typescript@npm:^5.5.4": - version: 5.8.3 - resolution: "typescript@npm:5.8.3" +"typescript@npm:5.9.2, typescript@npm:>=2.7, typescript@npm:>=3 < 6, typescript@npm:^5.0.4, typescript@npm:^5.4.5, typescript@npm:^5.5.4": + version: 5.9.2 + resolution: "typescript@npm:5.9.2" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10/65c40944c51b513b0172c6710ee62e951b70af6f75d5a5da745cb7fab132c09ae27ffdf7838996e3ed603bb015dadd099006658046941bd0ba30340cc563ae92 + checksum: 10/cc2fe6c822819de5d453fa25aa9f32096bf70dde215d481faa1ad84a283dfb264e33988ed8f6d36bc803dd0b16dbe943efa311a798ef76d5b3892a05dfbfd628 languageName: node linkType: hard @@ -31618,13 +31618,13 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A5.8.3#optional!builtin, typescript@patch:typescript@npm%3A>=2.7#optional!builtin, typescript@patch:typescript@npm%3A>=3 < 6#optional!builtin, typescript@patch:typescript@npm%3A^5.0.4#optional!builtin, typescript@patch:typescript@npm%3A^5.4.5#optional!builtin, typescript@patch:typescript@npm%3A^5.5.4#optional!builtin": - version: 5.8.3 - resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5" +"typescript@patch:typescript@npm%3A5.9.2#optional!builtin, typescript@patch:typescript@npm%3A>=2.7#optional!builtin, typescript@patch:typescript@npm%3A>=3 < 6#optional!builtin, typescript@patch:typescript@npm%3A^5.0.4#optional!builtin, typescript@patch:typescript@npm%3A^5.4.5#optional!builtin, typescript@patch:typescript@npm%3A^5.5.4#optional!builtin": + version: 5.9.2 + resolution: "typescript@patch:typescript@npm%3A5.9.2#optional!builtin::version=5.9.2&hash=5786d5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10/b9b1e73dabac5dc730c041325dbd9c99467c1b0d239f1b74ec3b90d831384af3e2ba973946232df670519147eb51a2c20f6f96163cea2b359f03de1e2091cc4f + checksum: 10/bd810ab13e8e557225a8b5122370385440b933e4e077d5c7641a8afd207fdc8be9c346e3c678adba934b64e0e70b0acf5eef9493ea05170a48ce22bef845fdc7 languageName: node linkType: hard From f3cd54769ce08176ece40f626a7275dacb741f49 Mon Sep 17 00:00:00 2001 From: Bogdan Matei Date: Fri, 1 Aug 2025 13:38:11 +0300 Subject: [PATCH 11/89] Dashboard: Fix for change detector in dashboards with live refresh (#108903) --- .../saving/DashboardSceneChangeTracker.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/public/app/features/dashboard-scene/saving/DashboardSceneChangeTracker.ts b/public/app/features/dashboard-scene/saving/DashboardSceneChangeTracker.ts index 6fc70618106..5b02068f80c 100644 --- a/public/app/features/dashboard-scene/saving/DashboardSceneChangeTracker.ts +++ b/public/app/features/dashboard-scene/saving/DashboardSceneChangeTracker.ts @@ -46,20 +46,24 @@ export class DashboardSceneChangeTracker { } static isUpdatingPersistedState({ payload }: SceneObjectStateChangedEvent) { + const partialUpdateKeys = Object.keys(payload.partialUpdate); + // If there are no changes in the state, the check is not needed - if (Object.keys(payload.partialUpdate).length === 0) { + if (partialUpdateKeys.length === 0) { return false; } - // Any change in the panel should trigger a change detection + // Any change in the grid item should trigger a change detection // The PanelTimeRange includes the overrides configuration - if ( - payload.changedObject instanceof VizPanel || - payload.changedObject instanceof DashboardGridItem || - payload.changedObject instanceof PanelTimeRange - ) { + if (payload.changedObject instanceof DashboardGridItem || payload.changedObject instanceof PanelTimeRange) { return true; } + // Panels contain a _renderCounter state prop which should not be marked as a change + if (payload.changedObject instanceof VizPanel) { + if (partialUpdateKeys.length > 1 || partialUpdateKeys[0] !== '_renderCounter') { + return true; + } + } // SceneQueryRunner includes the DS configuration if (payload.changedObject instanceof SceneQueryRunner) { if (!Object.prototype.hasOwnProperty.call(payload.partialUpdate, 'data')) { From 88a52bb6f4eecd275ee4f35a7ba86af64bd15dcb Mon Sep 17 00:00:00 2001 From: Bogdan Matei Date: Fri, 1 Aug 2025 13:46:41 +0300 Subject: [PATCH 12/89] Dashboards: Improve lazy loading (#108854) --- .../dashboard-group-panels.spec.ts | 274 ++++++++++-------- .../dashboards-edit-query-variables.spec.ts | 6 +- .../dashboards-panel-layouts.spec.ts | 13 + .../dashboards-remove-panel.spec.ts | 4 + .../dashboards/TestV2Dashboard.json | 84 +++--- package.json | 4 +- .../src/selectors/components.ts | 3 + .../dashboard-scene/scene/DashboardScene.tsx | 3 +- .../scene/layout-auto-grid/AutoGridLayout.tsx | 3 - .../AutoGridLayoutRenderer.tsx | 8 +- .../DefaultGridLayoutManager.tsx | 11 +- .../scene/layout-rows/RowItemRenderer.tsx | 1 + .../scene/layout-rows/RowsLayoutManager.tsx | 3 +- .../scene/layouts-shared/utils.ts | 6 + .../DefaultGridLayoutSerializer.ts | 4 +- .../transformSaveModelToScene.ts | 4 +- yarn.lock | 22 +- 17 files changed, 264 insertions(+), 189 deletions(-) diff --git a/e2e-playwright/dashboard-new-layouts/dashboard-group-panels.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboard-group-panels.spec.ts index 12023c9de6c..9824d0d08df 100644 --- a/e2e-playwright/dashboard-new-layouts/dashboard-group-panels.spec.ts +++ b/e2e-playwright/dashboard-new-layouts/dashboard-group-panels.spec.ts @@ -14,7 +14,7 @@ test.use({ // these tests require a larger viewport test.use({ - viewport: { width: 1280, height: 1080 }, + viewport: { width: 1920, height: 1080 }, }); test.describe( @@ -124,37 +124,49 @@ test.describe( await dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow).click(); await dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addPanel).last().click(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 2')) - ).toBeVisible(); + const firstRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row')); + await expect(firstRow).toBeVisible(); + await firstRow.scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) - ).toHaveCount(5); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow }) + ).toHaveCount(3); + + const secondRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row 1')); + await expect(secondRow).toBeVisible(); + + await secondRow.scrollIntoViewIfNeeded(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow }) + ).toHaveCount(1); + + const thirdRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row 2')); + await expect(thirdRow).toBeVisible(); + + await thirdRow.scrollIntoViewIfNeeded(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: thirdRow }) + ).toHaveCount(1); // Save dashboard and reload await saveDashboard(dashboardPage, selectors); await page.reload(); + await expect(firstRow).toBeVisible(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 2')) - ).toBeVisible(); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow }) + ).toHaveCount(3); + await expect(secondRow).toBeVisible(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) - ).toHaveCount(5); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow }) + ).toHaveCount(1); + + thirdRow.scrollIntoViewIfNeeded(); + await expect(thirdRow).toBeVisible(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: thirdRow }) + ).toHaveCount(1); await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); @@ -172,15 +184,9 @@ test.describe( await dashboardPage.getByGrafanaSelector(selectors.components.EditPaneHeader.deleteButton).click(); await dashboardPage.getByGrafanaSelector(selectors.pages.ConfirmModal.delete).click(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')) - ).toBeHidden(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 2')) - ).toBeHidden(); + await expect(firstRow).toBeVisible(); + await expect(secondRow).toBeHidden(); + await expect(thirdRow).toBeHidden(); await expect( dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) ).toHaveCount(3); @@ -188,15 +194,9 @@ test.describe( await saveDashboard(dashboardPage, selectors); await page.reload(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')) - ).toBeHidden(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 2')) - ).toBeHidden(); + await expect(firstRow).toBeVisible(); + await expect(secondRow).toBeHidden(); + await expect(thirdRow).toBeHidden(); await expect( dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) ).toHaveCount(3); @@ -224,15 +224,21 @@ test.describe( .getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow) .scrollIntoViewIfNeeded(); + const firstRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row')); + await expect(firstRow).toBeVisible(); + + firstRow.scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')) - ).toBeVisible(); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow }) + ).toHaveCount(3); + + const secondRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row 1')); + await expect(secondRow).toBeVisible(); + + secondRow.scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) - ).toHaveCount(6); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow }) + ).toHaveCount(3); await saveDashboard(dashboardPage, selectors); await page.reload(); @@ -243,15 +249,18 @@ test.describe( .last() .scrollIntoViewIfNeeded(); + await expect(firstRow).toBeVisible(); + await expect(secondRow).toBeVisible(); + + firstRow.scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')) - ).toBeVisible(); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow }) + ).toHaveCount(3); + + secondRow.scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) - ).toHaveCount(6); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow }) + ).toHaveCount(3); }); test('can duplicate a row', async ({ dashboardPage, selectors, page }) => { @@ -274,15 +283,21 @@ test.describe( .getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow) .scrollIntoViewIfNeeded(); + const firstRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row')); + await expect(firstRow).toBeVisible(); + + firstRow.scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')) - ).toBeVisible(); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow }) + ).toHaveCount(3); + + const secondRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row 1')); + await expect(secondRow).toBeVisible(); + + secondRow.scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) - ).toHaveCount(6); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow }) + ).toHaveCount(3); await saveDashboard(dashboardPage, selectors); await page.reload(); @@ -293,15 +308,18 @@ test.describe( .last() .scrollIntoViewIfNeeded(); + await expect(firstRow).toBeVisible(); + await expect(secondRow).toBeVisible(); + + firstRow.scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')) - ).toBeVisible(); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow }) + ).toHaveCount(3); + + secondRow.scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) - ).toHaveCount(6); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow }) + ).toHaveCount(3); }); test('can collapse rows', async ({ dashboardPage, selectors, page }) => { @@ -324,26 +342,29 @@ test.describe( .getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow) .scrollIntoViewIfNeeded(); + const firstRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row')); + await expect(firstRow).toBeVisible(); + + firstRow.scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')) - ).toBeVisible(); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow }) + ).toHaveCount(3); + + const secondRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New row 1')); + await expect(secondRow).toBeVisible(); + + secondRow.scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) - ).toHaveCount(6); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow }) + ).toHaveCount(3); // Collapse rows by clicking on their titles await dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')).click(); await dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')).click(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')) - ).toBeVisible(); + await expect(firstRow).toBeVisible(); + await expect(secondRow).toBeVisible(); + await expect( dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) ).toHaveCount(0); @@ -351,12 +372,9 @@ test.describe( await saveDashboard(dashboardPage, selectors); await page.reload(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row')) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New row 1')) - ).toBeVisible(); + await expect(firstRow).toBeVisible(); + await expect(secondRow).toBeVisible(); + await expect( dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) ).toHaveCount(0); @@ -684,67 +702,75 @@ test.describe( // Select rows layout await page.getByLabel('Rows').click(); + await dashboardPage + .getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New tab 1')) + .scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab')) + dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New tab 1')) ).toBeVisible(); + await dashboardPage + .getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New tab 2')) + .scrollIntoViewIfNeeded(); + + const firstRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New tab')); + const secondRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New tab 1')); + const thirdRow = dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.wrapper('New tab 2')); + + firstRow.scrollIntoViewIfNeeded(); + await expect(firstRow).toBeVisible(); // Wait for panels to load await expect( dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')).first() ).toBeVisible(); - await dashboardPage - .getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 1')) - .scrollIntoViewIfNeeded(); + await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 1')) - ).toBeVisible(); - await dashboardPage - .getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 2')) - .scrollIntoViewIfNeeded(); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow }) + ).toHaveCount(3); + + secondRow.scrollIntoViewIfNeeded(); + await expect(secondRow).toBeVisible(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 2')) - ).toBeVisible(); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow }) + ).toHaveCount(3); + + thirdRow.scrollIntoViewIfNeeded(); + await expect(thirdRow).toBeVisible(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: thirdRow }) + ).toHaveCount(3); // scroll `New row` into view - this is at the bottom of the dashboard body await dashboardPage .getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow) .scrollIntoViewIfNeeded(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) - ).toHaveCount(9); + await expect(dashboardPage.getByGrafanaSelector(selectors.components.CanvasGridAddActions.addRow)).toBeVisible(); await saveDashboard(dashboardPage, selectors); await page.reload(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab')) - ).toBeVisible(); + await expect(firstRow).toBeVisible(); + // Wait for panels to load await expect( dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')).first() ).toBeVisible(); - await dashboardPage - .getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 1')) - .scrollIntoViewIfNeeded(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 1')) - ).toBeVisible(); - await dashboardPage - .getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 2')) - .scrollIntoViewIfNeeded(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title('New tab 2')) - ).toBeVisible(); - - // scroll last `New panel` into view - this is at the bottom of the dashboard body - await dashboardPage - .getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) - .last() - .scrollIntoViewIfNeeded(); await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')) - ).toHaveCount(9); + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: firstRow }) + ).toHaveCount(3); + + secondRow.scrollIntoViewIfNeeded(); + await expect(secondRow).toBeVisible(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: secondRow }) + ).toHaveCount(3); + + thirdRow.scrollIntoViewIfNeeded(); + await expect(thirdRow).toBeVisible(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel'), { root: thirdRow }) + ).toHaveCount(3); }); test('can group and ungroup new panels into tab with row', async ({ dashboardPage, selectors, page }) => { diff --git a/e2e-playwright/dashboard-new-layouts/dashboards-edit-query-variables.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboards-edit-query-variables.spec.ts index 6c55988a309..2e6b80b7b3c 100644 --- a/e2e-playwright/dashboard-new-layouts/dashboards-edit-query-variables.spec.ts +++ b/e2e-playwright/dashboard-new-layouts/dashboards-edit-query-variables.spec.ts @@ -10,6 +10,10 @@ test.use({ }, }); +test.use({ + viewport: { width: 1920, height: 1080 }, +}); + const PAGE_UNDER_TEST = 'kVi2Gex7z/test-variable-output'; const DASHBOARD_NAME = 'Test variable output'; @@ -55,7 +59,7 @@ test.describe( const firstPreviewOption = dashboardPage .getByGrafanaSelector(selectors.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption) .first(); - await expect(firstPreviewOption).toBeVisible(); + await expect(firstPreviewOption).toBeVisible({ timeout: 15_000 }); const previewOptionText = await firstPreviewOption.textContent(); const previewOption = previewOptionText?.trim() || ''; diff --git a/e2e-playwright/dashboard-new-layouts/dashboards-panel-layouts.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboards-panel-layouts.spec.ts index 78889efbbbe..6cd56e19a11 100644 --- a/e2e-playwright/dashboard-new-layouts/dashboards-panel-layouts.spec.ts +++ b/e2e-playwright/dashboard-new-layouts/dashboards-panel-layouts.spec.ts @@ -12,6 +12,10 @@ test.use({ }, }); +test.use({ + viewport: { width: 1920, height: 1080 }, +}); + test.describe( 'Dashboard Panel Layouts', { @@ -171,6 +175,10 @@ test.describe( test('can change max columns in auto grid layout', async ({ dashboardPage, selectors, page }) => { await importTestDashboard(page, selectors, 'Set max columns'); + await await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')).first() + ).toBeVisible(); + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); await expect( @@ -384,6 +392,11 @@ async function importTestDashboard(page: Page, selectors: E2ESelectorGroups, tit await page.getByTestId(selectors.components.DataSourcePicker.inputV2).click(); await page.locator('div[data-testid="data-source-card"]').first().click(); await page.getByTestId(selectors.components.ImportDashboardForm.submit).click(); + const undockMenuButton = page.locator('[aria-label="Undock menu"]'); + const undockMenuVisible = await undockMenuButton.isVisible(); + if (undockMenuVisible) { + undockMenuButton.click(); + } } async function saveDashboard(dashboardPage: DashboardPage, selectors: E2ESelectorGroups) { diff --git a/e2e-playwright/dashboard-new-layouts/dashboards-remove-panel.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboards-remove-panel.spec.ts index 5b5202f1455..61fb78ab5a7 100644 --- a/e2e-playwright/dashboard-new-layouts/dashboards-remove-panel.spec.ts +++ b/e2e-playwright/dashboard-new-layouts/dashboards-remove-panel.spec.ts @@ -10,6 +10,10 @@ test.use({ const PAGE_UNDER_TEST = 'edediimbjhdz4b/a-tall-dashboard'; +test.use({ + viewport: { width: 1920, height: 1080 }, +}); + test.describe( 'Dashboard panels', { diff --git a/e2e-playwright/dashboards/TestV2Dashboard.json b/e2e-playwright/dashboards/TestV2Dashboard.json index 25917da59fa..e4b81d82bf4 100644 --- a/e2e-playwright/dashboards/TestV2Dashboard.json +++ b/e2e-playwright/dashboards/TestV2Dashboard.json @@ -2,32 +2,27 @@ "apiVersion": "dashboard.grafana.app/v2beta1", "kind": "Dashboard", "metadata": { - "name": "fa400625-2a44-4add-a369-e6c972eb4bd6", - "generation": 1, - "creationTimestamp": "2025-05-27T11:40:22Z", - "labels": {}, - "annotations": {} + "name": "addfpww", + "namespace": "default", + "uid": "AvXN09JdxuVNDqODs5IYU2iStlk5ntizuPGIfY1ywZgX", + "resourceVersion": "1", + "generation": 2, + "creationTimestamp": "2025-07-31T13:37:11Z", + "labels": { + "grafana.app/deprecatedInternalID": "6844" + }, + "annotations": { + "grafana.app/createdBy": "user:cejvsh18uudxcf", + "grafana.app/updatedBy": "user:cejvsh18uudxcf", + "grafana.app/updatedTimestamp": "2025-07-31T13:37:11Z", + "grafana.app/folder": "", + "grafana.app/saved-from-ui": "Grafana v12.2.0-pre (69d1226c9a)" + } }, "spec": { - "annotations": [ - { - "kind": "AnnotationQuery", - "spec": { - "builtIn": true, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "query": { - "group": "grafana", - "kind": "DataQuery", - "spec": {}, - "version": "v0" - } - } - } - ], + "annotations": [], "cursorSync": "Off", + "description": "", "editable": true, "elements": { "panel-1": { @@ -42,6 +37,9 @@ "spec": { "hidden": false, "query": { + "datasource": { + "name": "PD8C576611E62080A" + }, "group": "grafana-testdata-datasource", "kind": "DataQuery", "spec": {}, @@ -60,7 +58,8 @@ "links": [], "title": "New panel", "vizConfig": { - "kind": "timeseries", + "group": "timeseries", + "kind": "VizConfig", "spec": { "fieldConfig": { "defaults": { @@ -128,9 +127,9 @@ "mode": "single", "sort": "none" } - }, - "pluginVersion": "12.1.0-pre" - } + } + }, + "version": "12.2.0-pre" } } }, @@ -146,9 +145,15 @@ "spec": { "hidden": false, "query": { + "datasource": { + "name": "PD8C576611E62080A" + }, "group": "grafana-testdata-datasource", "kind": "DataQuery", - "spec": {}, + "spec": { + "scenarioId": "random_walk", + "seriesCount": 1 + }, "version": "v0" }, "refId": "A" @@ -164,7 +169,8 @@ "links": [], "title": "New panel", "vizConfig": { - "kind": "timeseries", + "group": "timeseries", + "kind": "VizConfig", "spec": { "fieldConfig": { "defaults": { @@ -232,9 +238,9 @@ "mode": "single", "sort": "none" } - }, - "pluginVersion": "12.1.0-pre" - } + } + }, + "version": "12.2.0-pre" } } }, @@ -250,6 +256,9 @@ "spec": { "hidden": false, "query": { + "datasource": { + "name": "PD8C576611E62080A" + }, "group": "grafana-testdata-datasource", "kind": "DataQuery", "spec": {}, @@ -268,7 +277,8 @@ "links": [], "title": "New panel", "vizConfig": { - "kind": "timeseries", + "group": "timeseries", + "kind": "VizConfig", "spec": { "fieldConfig": { "defaults": { @@ -336,9 +346,9 @@ "mode": "single", "sort": "none" } - }, - "pluginVersion": "12.1.0-pre" - } + } + }, + "version": "12.2.0-pre" } } } @@ -402,7 +412,7 @@ "timezone": "browser", "to": "now" }, - "title": "Test V2 Dashboard", + "title": "TEST!!!!", "variables": [] }, "status": {} diff --git a/package.json b/package.json index 5d74735f039..cc339866f02 100644 --- a/package.json +++ b/package.json @@ -290,8 +290,8 @@ "@grafana/plugin-ui": "0.10.7", "@grafana/prometheus": "workspace:*", "@grafana/runtime": "workspace:*", - "@grafana/scenes": "6.28.6", - "@grafana/scenes-react": "6.28.6", + "@grafana/scenes": "6.29.0", + "@grafana/scenes-react": "6.29.0", "@grafana/schema": "workspace:*", "@grafana/sql": "workspace:*", "@grafana/ui": "workspace:*", diff --git a/packages/grafana-e2e-selectors/src/selectors/components.ts b/packages/grafana-e2e-selectors/src/selectors/components.ts index adf4f2efbfe..9ac23a5b24c 100644 --- a/packages/grafana-e2e-selectors/src/selectors/components.ts +++ b/packages/grafana-e2e-selectors/src/selectors/components.ts @@ -1239,6 +1239,9 @@ export const versionedComponents = { title: { [MIN_GRAFANA_VERSION]: (title: string) => `data-testid dashboard-row-title-${title}`, }, + wrapper: { + '12.1.0': (title: string) => `data-testid dashboard-row-wrapper-for-${title}`, + }, }, UserProfile: { profileSaveButton: { diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.tsx index 662d92a32df..48581e303ae 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.tsx @@ -88,6 +88,7 @@ import { DashboardGridItem } from './layout-default/DashboardGridItem'; import { DefaultGridLayoutManager } from './layout-default/DefaultGridLayoutManager'; import { addNewRowTo } from './layouts-shared/addNew'; import { clearClipboard } from './layouts-shared/paste'; +import { getIsLazy } from './layouts-shared/utils'; import { DashboardLayoutManager } from './types/DashboardLayoutManager'; import { LayoutParent } from './types/LayoutParent'; @@ -198,7 +199,7 @@ export class DashboardScene extends SceneObjectBase impleme meta: {}, editable: true, $timeRange: state.$timeRange ?? new SceneTimeRange({}), - body: state.body ?? DefaultGridLayoutManager.fromVizPanels(), + body: state.body ?? DefaultGridLayoutManager.fromVizPanels([], getIsLazy(state.preload)), links: state.links ?? [], ...state, editPane: new DashboardEditPane(), diff --git a/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridLayout.tsx b/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridLayout.tsx index be19f886d83..b96550cfa22 100644 --- a/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridLayout.tsx +++ b/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridLayout.tsx @@ -22,9 +22,6 @@ export interface AutoGridLayoutState extends SceneObjectState, AutoGridLayoutOpt */ md?: AutoGridLayoutOptions; - /** True when the items should be lazy loaded */ - isLazy?: boolean; - /** True when the items should be draggable */ isDraggable?: boolean; diff --git a/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridLayoutRenderer.tsx b/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridLayoutRenderer.tsx index 7f66994354d..2a44564b536 100644 --- a/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridLayoutRenderer.tsx +++ b/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridLayoutRenderer.tsx @@ -1,4 +1,5 @@ import { css, cx } from '@emotion/css'; +import { useMemo } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { LazyLoader, SceneComponentProps, sceneGraph } from '@grafana/scenes'; @@ -8,18 +9,21 @@ import { useHasClonedParents } from '../../utils/clone'; import { useDashboardState } from '../../utils/utils'; import { CanvasGridAddActions } from '../layouts-shared/CanvasGridAddActions'; import { dashboardCanvasAddButtonHoverStyles } from '../layouts-shared/styles'; +import { getIsLazy } from '../layouts-shared/utils'; import { AutoGridLayout, AutoGridLayoutState } from './AutoGridLayout'; import { AutoGridLayoutManager } from './AutoGridLayoutManager'; export function AutoGridLayoutRenderer({ model }: SceneComponentProps) { - const { children, isHidden, isLazy } = model.useState(); + const { children, isHidden } = model.useState(); const hasClonedParents = useHasClonedParents(model); const styles = useStyles2(getStyles, model.state); - const { layoutOrchestrator, isEditing } = useDashboardState(model); + const { layoutOrchestrator, isEditing, preload } = useDashboardState(model); const layoutManager = sceneGraph.getAncestor(model, AutoGridLayoutManager); const { fillScreen } = layoutManager.useState(); + const isLazy = useMemo(() => getIsLazy(preload), [preload]); + if (isHidden || !layoutOrchestrator) { return null; } diff --git a/public/app/features/dashboard-scene/scene/layout-default/DefaultGridLayoutManager.tsx b/public/app/features/dashboard-scene/scene/layout-default/DefaultGridLayoutManager.tsx index b85cb2bcf4b..76fffddd0a5 100644 --- a/public/app/features/dashboard-scene/scene/layout-default/DefaultGridLayoutManager.tsx +++ b/public/app/features/dashboard-scene/scene/layout-default/DefaultGridLayoutManager.tsx @@ -46,6 +46,7 @@ import { AutoGridItem } from '../layout-auto-grid/AutoGridItem'; import { CanvasGridAddActions } from '../layouts-shared/CanvasGridAddActions'; import { clearClipboard, getDashboardGridItemFromClipboard } from '../layouts-shared/paste'; import { dashboardCanvasAddButtonHoverStyles } from '../layouts-shared/styles'; +import { getIsLazy } from '../layouts-shared/utils'; import { DashboardLayoutManager } from '../types/DashboardLayoutManager'; import { LayoutRegistryItem } from '../types/LayoutRegistryItem'; @@ -558,10 +559,11 @@ export class DefaultGridLayoutManager public static createFromLayout(currentLayout: DashboardLayoutManager): DefaultGridLayoutManager { const panels = currentLayout.getVizPanels(); - return DefaultGridLayoutManager.fromVizPanels(panels); + const isLazy = getIsLazy(getDashboardSceneFor(currentLayout).state.preload)!; + return DefaultGridLayoutManager.fromVizPanels(panels, isLazy); } - public static fromVizPanels(panels: VizPanel[] = []): DefaultGridLayoutManager { + public static fromVizPanels(panels: VizPanel[] = [], isLazy?: boolean | undefined): DefaultGridLayoutManager { const children: DashboardGridItem[] = []; const panelHeight = 10; const panelWidth = GRID_COLUMN_COUNT / 3; @@ -599,6 +601,7 @@ export class DefaultGridLayoutManager children: children, isDraggable: true, isResizable: true, + isLazy, }), }); } @@ -606,7 +609,8 @@ export class DefaultGridLayoutManager public static fromGridItems( gridItems: SceneGridItemLike[], isDraggable?: boolean, - isResizable?: boolean + isResizable?: boolean, + isLazy?: boolean | undefined ): DefaultGridLayoutManager { const children = gridItems.reduce((acc, gridItem) => { gridItem.clearParent(); @@ -620,6 +624,7 @@ export class DefaultGridLayoutManager children, isDraggable, isResizable, + isLazy, }), }); } diff --git a/public/app/features/dashboard-scene/scene/layout-rows/RowItemRenderer.tsx b/public/app/features/dashboard-scene/scene/layout-rows/RowItemRenderer.tsx index b03b8b26e26..affa68d54ea 100644 --- a/public/app/features/dashboard-scene/scene/layout-rows/RowItemRenderer.tsx +++ b/public/app/features/dashboard-scene/scene/layout-rows/RowItemRenderer.tsx @@ -83,6 +83,7 @@ export function RowItemRenderer({ model }: SceneComponentProps) { setTimeout(() => onSelect?.(evt)); }} + data-testid={selectors.components.DashboardRow.wrapper(title!)} {...dragProvided.draggableProps} > {(!isHeaderHidden || isEditing) && ( diff --git a/public/app/features/dashboard-scene/scene/layout-rows/RowsLayoutManager.tsx b/public/app/features/dashboard-scene/scene/layout-rows/RowsLayoutManager.tsx index 34b2a9e3a1a..1b04a9d6c23 100644 --- a/public/app/features/dashboard-scene/scene/layout-rows/RowsLayoutManager.tsx +++ b/public/app/features/dashboard-scene/scene/layout-rows/RowsLayoutManager.tsx @@ -258,7 +258,8 @@ export class RowsLayoutManager extends SceneObjectBase i layout: DefaultGridLayoutManager.fromGridItems( rowConfig.children, rowConfig.isDraggable ?? layout.state.grid.state.isDraggable, - rowConfig.isResizable ?? layout.state.grid.state.isResizable + rowConfig.isResizable ?? layout.state.grid.state.isResizable, + layout.state.grid.state.isLazy ), }) ); diff --git a/public/app/features/dashboard-scene/scene/layouts-shared/utils.ts b/public/app/features/dashboard-scene/scene/layouts-shared/utils.ts index 41402564081..eac9ff86333 100644 --- a/public/app/features/dashboard-scene/scene/layouts-shared/utils.ts +++ b/public/app/features/dashboard-scene/scene/layouts-shared/utils.ts @@ -1,6 +1,7 @@ import { useEffect, useRef } from 'react'; import { SceneObject } from '@grafana/scenes'; +import { contextSrv } from 'app/core/core'; import { DashboardLayoutManager, isDashboardLayoutManager } from '../types/DashboardLayoutManager'; import { isLayoutParent } from '../types/LayoutParent'; @@ -75,3 +76,8 @@ export function ungroupLayout(layout: DashboardLayoutManager, innerLayout: Dashb layoutParent.switchLayout(innerLayout); } } + +export function getIsLazy(preload: boolean | undefined): boolean { + // We don't want to lazy load panels in the case of image renderer + return !(preload || (contextSrv.user && contextSrv.user.authenticatedBy === 'render')); +} diff --git a/public/app/features/dashboard-scene/serialization/layoutSerializers/DefaultGridLayoutSerializer.ts b/public/app/features/dashboard-scene/serialization/layoutSerializers/DefaultGridLayoutSerializer.ts index 8688d1cbb08..e19059547b7 100644 --- a/public/app/features/dashboard-scene/serialization/layoutSerializers/DefaultGridLayoutSerializer.ts +++ b/public/app/features/dashboard-scene/serialization/layoutSerializers/DefaultGridLayoutSerializer.ts @@ -9,10 +9,10 @@ import { PanelKind, LibraryPanelKind, } from '@grafana/schema/dist/esm/schema/dashboard/v2'; -import { contextSrv } from 'app/core/core'; import { DashboardGridItem } from '../../scene/layout-default/DashboardGridItem'; import { DefaultGridLayoutManager } from '../../scene/layout-default/DefaultGridLayoutManager'; +import { getIsLazy } from '../../scene/layouts-shared/utils'; import { dashboardSceneGraph } from '../../utils/dashboardSceneGraph'; import { calculateGridItemDimensions, isLibraryPanel } from '../../utils/utils'; @@ -41,7 +41,7 @@ export function deserializeDefaultGridLayout( } return new DefaultGridLayoutManager({ grid: new SceneGridLayout({ - isLazy: !(preload || contextSrv.user.authenticatedBy === 'render'), + isLazy: getIsLazy(preload), children: createSceneGridLayoutForItems(layout, elements, panelIdGenerator), }), }); diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts index b7af7080ea8..8657af91ba1 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts @@ -20,7 +20,6 @@ import { SceneObjectState, } from '@grafana/scenes'; import { isWeekStart } from '@grafana/ui'; -import { contextSrv } from 'app/core/core'; import { K8S_V1_DASHBOARD_API_CONFIG } from 'app/features/dashboard/api/v1'; import { getDashboardInteractionCallback, @@ -50,6 +49,7 @@ import { RowRepeaterBehavior } from '../scene/layout-default/RowRepeaterBehavior import { RowActions } from '../scene/layout-default/row-actions/RowActions'; import { RowItem } from '../scene/layout-rows/RowItem'; import { RowsLayoutManager } from '../scene/layout-rows/RowsLayoutManager'; +import { getIsLazy } from '../scene/layouts-shared/utils'; import { setDashboardPanelContext } from '../scene/setDashboardPanelContext'; import { DashboardLayoutManager } from '../scene/types/DashboardLayoutManager'; import { createPanelDataProvider } from '../utils/createPanelDataProvider'; @@ -326,7 +326,7 @@ export function createDashboardSceneFromDashboardModel(oldModel: DashboardModel, } else { body = new DefaultGridLayoutManager({ grid: new SceneGridLayout({ - isLazy: !(dto.preload || contextSrv.user.authenticatedBy === 'render'), + isLazy: getIsLazy(dto.preload), children: createSceneObjectsForPanels(oldModel.panels), }), }); diff --git a/yarn.lock b/yarn.lock index a0ac7fc9772..a9cb48e452e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3590,11 +3590,11 @@ __metadata: languageName: unknown linkType: soft -"@grafana/scenes-react@npm:6.28.6": - version: 6.28.6 - resolution: "@grafana/scenes-react@npm:6.28.6" +"@grafana/scenes-react@npm:6.29.0": + version: 6.29.0 + resolution: "@grafana/scenes-react@npm:6.29.0" dependencies: - "@grafana/scenes": "npm:6.28.6" + "@grafana/scenes": "npm:6.29.0" lru-cache: "npm:^10.2.2" react-use: "npm:^17.4.0" peerDependencies: @@ -3606,13 +3606,13 @@ __metadata: react: ^18.0.0 react-dom: ^18.0.0 react-router-dom: ^6.28.0 - checksum: 10/55dfe20a6454f218b7c5ab2dc728678885d48e53656d046c125b555b201891e121e0960e108229372c2d70336cfe3dade9b392ed001fef90aec57cbcc13f76ca + checksum: 10/3cf401ecb143d4bf130ea406b2d6e789c1ac49f5490f4fa80e2cc330d84cee434d4543ae58ad0cae228e1b3b73972888bb95eed217a9d2fa0524088361710878 languageName: node linkType: hard -"@grafana/scenes@npm:6.28.6": - version: 6.28.6 - resolution: "@grafana/scenes@npm:6.28.6" +"@grafana/scenes@npm:6.29.0": + version: 6.29.0 + resolution: "@grafana/scenes@npm:6.29.0" dependencies: "@floating-ui/react": "npm:^0.26.16" "@leeoniya/ufuzzy": "npm:^1.0.16" @@ -3632,7 +3632,7 @@ __metadata: react: ^18.0.0 react-dom: ^18.0.0 react-router-dom: ^6.28.0 - checksum: 10/fcfcf663e2eb63ad25fad27ec50af8590b1a6c9e802927e8e457bf2f81d04cf971c2f12f456a04a502c929ec7a1d50ef7118baee095134b133ecc92b269a6907 + checksum: 10/ab28ab9a8612e51e189e7ae497cbe3be709515a917deb35e05be3b142c0d541acf22b441501eb6c162ba4bc7da443672ac13312b68f3dbf64ab8556aacdc2999 languageName: node linkType: hard @@ -18253,8 +18253,8 @@ __metadata: "@grafana/plugin-ui": "npm:0.10.7" "@grafana/prometheus": "workspace:*" "@grafana/runtime": "workspace:*" - "@grafana/scenes": "npm:6.28.6" - "@grafana/scenes-react": "npm:6.28.6" + "@grafana/scenes": "npm:6.29.0" + "@grafana/scenes-react": "npm:6.29.0" "@grafana/schema": "workspace:*" "@grafana/sql": "workspace:*" "@grafana/test-utils": "workspace:*" From 9ca0750134cb583b1ac0b88477766195aaa53e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Jim=C3=A9nez=20S=C3=A1nchez?= Date: Fri, 1 Aug 2025 13:17:15 +0200 Subject: [PATCH 13/89] Provisioning: skip export of already managed resources and parent folder export (#108893) * Skip export on already managed resources * Add integration test * Add integration test * Handle nothing to commit error * Fix leaky abstraction issue * Handle the no commit error on commit and not on push * Fix linting * Some fixes for integration test * Improve tree to work with a root * Some fixes with hacks * Add additional checks * Fix comment * Fix path problems in test * Fix more stuff * Revert to use empty tree * Remove changes in tree * Finally fix the tests work * Remove stale comment * Fix linting * Revert changes in test * Fix error message for folder not found in resource tree Co-authored-by: roberto.jimenez --------- Co-authored-by: Cursor Agent --- .../apis/provisioning/jobs/export/folders.go | 5 +- .../provisioning/jobs/export/folders_test.go | 89 ++++---- .../provisioning/jobs/export/resources.go | 18 ++ .../jobs/export/resources_test.go | 35 ++++ .../provisioning/repository/git/repository.go | 4 + .../provisioning/repository/git/staged.go | 14 +- .../repository/git/staged_test.go | 56 ++++- .../apis/provisioning/repository/staged.go | 9 +- .../provisioning/repository/staged_test.go | 79 +++++++ .../apis/provisioning/resources/resources.go | 18 +- pkg/tests/apis/provisioning/helper_test.go | 48 ++++- .../apis/provisioning/provisioning_test.go | 193 ++++++++++++++++++ 12 files changed, 518 insertions(+), 50 deletions(-) diff --git a/pkg/registry/apis/provisioning/jobs/export/folders.go b/pkg/registry/apis/provisioning/jobs/export/folders.go index afc7db05a87..c8b108d6023 100644 --- a/pkg/registry/apis/provisioning/jobs/export/folders.go +++ b/pkg/registry/apis/provisioning/jobs/export/folders.go @@ -32,8 +32,9 @@ func ExportFolders(ctx context.Context, repoName string, options provisioning.Ex } manager, _ := meta.GetManagerProperties() - if manager.Identity == repoName { - return nil // skip it... already in tree? + // Skip if already managed by any manager (repository, file provisioning, etc.) + if manager.Identity != "" { + return nil } return tree.AddUnstructured(item) diff --git a/pkg/registry/apis/provisioning/jobs/export/folders_test.go b/pkg/registry/apis/provisioning/jobs/export/folders_test.go index bec0214d7ef..49c07a64347 100644 --- a/pkg/registry/apis/provisioning/jobs/export/folders_test.go +++ b/pkg/registry/apis/provisioning/jobs/export/folders_test.go @@ -298,38 +298,21 @@ func TestExportFolders(t *testing.T) { progress.On("SetMessage", mock.Anything, "read folder tree from API server").Return() progress.On("SetMessage", mock.Anything, "write folders to repository").Return() progress.On("Record", mock.Anything, mock.MatchedBy(func(result jobs.JobResourceResult) bool { - return result.Name == "parent-uid" && result.Action == repository.FileActionCreated + return result.Name == "parent-folder" && result.Action == repository.FileActionCreated })).Return() progress.On("Record", mock.Anything, mock.MatchedBy(func(result jobs.JobResourceResult) bool { - return result.Name == "child-uid" && result.Action == repository.FileActionCreated + return result.Name == "child-folder" && result.Action == repository.FileActionCreated })).Return() progress.On("TooManyErrors").Return(nil) progress.On("TooManyErrors").Return(nil) }, setupResources: func(repoResources *resources.MockRepositoryResources) { repoResources.On("EnsureFolderTreeExists", mock.Anything, "feature/branch", "grafana", mock.MatchedBy(func(tree resources.FolderTree) bool { - expectedFolders := []resources.Folder{ - {ID: "parent-folder", Path: "parent-folder"}, - {ID: "child-folder", Path: "parent-folder/child-folder"}, - } - - if tree.Count() != len(expectedFolders) { - return false - } - - for _, folder := range expectedFolders { - dir, ok := tree.DirPath(folder.ID, "") - if !ok || dir.Path != folder.Path { - return false - } - } - - return true + return tree.Count() == 2 }), mock.MatchedBy(func(fn func(folder resources.Folder, created bool, err error) error) bool { - // Parent folder should be processed first - require.NoError(t, fn(resources.Folder{ID: "parent-uid", Path: "grafana/parent-folder"}, true, nil)) - // Then child folder with nested path - require.NoError(t, fn(resources.Folder{ID: "child-uid", Path: "grafana/parent-folder/child-folder"}, true, nil)) + require.NoError(t, fn(resources.Folder{ID: "parent-folder", Path: "grafana/parent-folder"}, true, nil)) + require.NoError(t, fn(resources.Folder{ID: "child-folder", Path: "grafana/parent-folder/child-folder"}, true, nil)) + return true })).Return(nil) }, @@ -380,7 +363,7 @@ func TestExportFolders(t *testing.T) { } func TestFolderMetaAccessor(t *testing.T) { - t.Run("should export folders from another manager", func(t *testing.T) { + t.Run("should skip folders from another manager", func(t *testing.T) { obj := &unstructured.Unstructured{ Object: map[string]interface{}{ "metadata": map[string]interface{}{ @@ -405,21 +388,12 @@ func TestFolderMetaAccessor(t *testing.T) { mockRepoResources := resources.NewMockRepositoryResources(t) mockRepoResources.On("EnsureFolderTreeExists", mock.Anything, "feature/branch", "grafana", mock.MatchedBy(func(tree resources.FolderTree) bool { - return tree.Count() == 1 - }), mock.MatchedBy(func(fn func(folder resources.Folder, created bool, err error) error) bool { - require.NoError(t, fn(resources.Folder{ID: "test-folder-uid", Path: "grafana/test-folder"}, true, nil)) - return true - })).Return(nil) + return tree.Count() == 0 // Should be 0 since folder is managed by other manager + }), mock.Anything).Return(nil) progress := jobs.NewMockJobProgressRecorder(t) - progress.On("SetMessage", mock.Anything, mock.Anything).Return() - progress.On("Record", mock.Anything, mock.MatchedBy(func(result jobs.JobResourceResult) bool { - return result.Action == repository.FileActionCreated && - result.Name == "test-folder-uid" && - result.Error == nil && - result.Path == "grafana/test-folder" - })).Return() - progress.On("TooManyErrors").Return(nil) + progress.On("SetMessage", mock.Anything, mock.Anything).Return().Twice() + // No Record calls expected since folder should be skipped err = ExportFolders(context.Background(), "test-repo", v0alpha1.ExportJobOptions{ Path: "grafana", Branch: "feature/branch", @@ -430,7 +404,7 @@ func TestFolderMetaAccessor(t *testing.T) { mockRepoResources.AssertExpectations(t) progress.AssertExpectations(t) }) - t.Run("should skip if repo is the manager", func(t *testing.T) { + t.Run("should skip if current repo is the manager", func(t *testing.T) { obj := &unstructured.Unstructured{ Object: map[string]interface{}{ "metadata": map[string]interface{}{ @@ -492,6 +466,45 @@ func TestFolderMetaAccessor(t *testing.T) { mockRepoResources.AssertExpectations(t) progress.AssertExpectations(t) }) + t.Run("should skip if managed by any other manager", func(t *testing.T) { + obj := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "metadata": map[string]interface{}{ + "name": "test-folder", + "annotations": map[string]interface{}{ + "folder.grafana.app/uid": "test-folder-uid", + }, + }, + }, + } + meta, err := utils.MetaAccessor(obj) + require.NoError(t, err) + meta.SetManagerProperties(utils.ManagerProperties{ + Kind: utils.ManagerKindTerraform, + Identity: "terraform-provisioning", + AllowsEdits: false, + Suspended: false, + }) + fakeFolderClient := &mockDynamicInterface{ + items: []unstructured.Unstructured{*obj}, + } + + mockRepoResources := resources.NewMockRepositoryResources(t) + progress := jobs.NewMockJobProgressRecorder(t) + progress.On("SetMessage", mock.Anything, mock.Anything).Return().Twice() + mockRepoResources.On("EnsureFolderTreeExists", mock.Anything, "feature/branch", "grafana", mock.MatchedBy(func(tree resources.FolderTree) bool { + return tree.Count() == 0 // Should be empty since folder was skipped + }), mock.Anything).Return(nil) + + err = ExportFolders(context.Background(), "test-repo", v0alpha1.ExportJobOptions{ + Path: "grafana", + Branch: "feature/branch", + }, fakeFolderClient, mockRepoResources, progress) + + require.NoError(t, err) + mockRepoResources.AssertExpectations(t) + progress.AssertExpectations(t) + }) } // mockDynamicInterface implements a simplified version of the dynamic.ResourceInterface diff --git a/pkg/registry/apis/provisioning/jobs/export/resources.go b/pkg/registry/apis/provisioning/jobs/export/resources.go index b986392c3d6..54805784cee 100644 --- a/pkg/registry/apis/provisioning/jobs/export/resources.go +++ b/pkg/registry/apis/provisioning/jobs/export/resources.go @@ -10,6 +10,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/client-go/dynamic" + "github.com/grafana/grafana/pkg/apimachinery/utils" provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" @@ -103,6 +104,23 @@ func exportResource(ctx context.Context, Action: repository.FileActionCreated, } + // Check if resource is already managed by a repository + meta, err := utils.MetaAccessor(item) + if err != nil { + result.Action = repository.FileActionIgnored + result.Error = fmt.Errorf("extract meta accessor: %w", err) + progress.Record(ctx, result) + return nil + } + + manager, _ := meta.GetManagerProperties() + // Skip if already managed by any manager (repository, file provisioning, etc.) + if manager.Identity != "" { + result.Action = repository.FileActionIgnored + progress.Record(ctx, result) + return nil + } + if shim != nil { item, err = shim(ctx, item) } diff --git a/pkg/registry/apis/provisioning/jobs/export/resources_test.go b/pkg/registry/apis/provisioning/jobs/export/resources_test.go index db8209cf414..e77ae6105ed 100644 --- a/pkg/registry/apis/provisioning/jobs/export/resources_test.go +++ b/pkg/registry/apis/provisioning/jobs/export/resources_test.go @@ -5,6 +5,7 @@ import ( "fmt" "testing" + "github.com/grafana/grafana/pkg/apimachinery/utils" mock "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -532,3 +533,37 @@ func TestExportResources_Dashboards_V2beta1_ClientError(t *testing.T) { err := runExportTest(t, mockItems, setupProgress, setupResources) require.NoError(t, err) } + +func TestExportResources_Dashboards_SkipsManagedResources(t *testing.T) { + // Create a dashboard managed by file provisioning + dashboard := createDashboardObject("managed-dashboard") + + // Add manager metadata using utils package + meta, err := utils.MetaAccessor(&dashboard) + require.NoError(t, err) + meta.SetManagerProperties(utils.ManagerProperties{ + Kind: utils.ManagerKindTerraform, + Identity: "terraform-provisioning", + AllowsEdits: false, + Suspended: false, + }) + + mockItems := []unstructured.Unstructured{dashboard} + + setupProgress := func(progress *jobs.MockJobProgressRecorder) { + progress.On("SetMessage", mock.Anything, "start resource export").Return() + progress.On("SetMessage", mock.Anything, "export dashboards").Return() + progress.On("Record", mock.Anything, mock.MatchedBy(func(result jobs.JobResourceResult) bool { + return result.Name == "managed-dashboard" && result.Action == repository.FileActionIgnored + })).Return() + progress.On("TooManyErrors").Return(nil).Maybe() + } + + setupResources := func(repoResources *resources.MockRepositoryResources, resourceClients *resources.MockResourceClients, mockClient *mockDynamicInterface, gvk schema.GroupVersionKind) { + resourceClients.On("ForResource", resources.DashboardResource).Return(mockClient, gvk, nil) + // No WriteResourceFileFromObject call expected since resource should be skipped + } + + err = runExportTest(t, mockItems, setupProgress, setupResources) + require.NoError(t, err) +} diff --git a/pkg/registry/apis/provisioning/repository/git/repository.go b/pkg/registry/apis/provisioning/repository/git/repository.go index 5bcdb12cd94..7ca9ed8998e 100644 --- a/pkg/registry/apis/provisioning/repository/git/repository.go +++ b/pkg/registry/apis/provisioning/repository/git/repository.go @@ -790,6 +790,10 @@ func (r *gitRepository) createSignature(ctx context.Context) (nanogit.Author, na func (r *gitRepository) commit(ctx context.Context, writer nanogit.StagedWriter, comment string) error { author, committer := r.createSignature(ctx) if _, err := writer.Commit(ctx, comment, author, committer); err != nil { + if errors.Is(err, nanogit.ErrNothingToCommit) { + return repository.ErrNothingToCommit + } + return fmt.Errorf("commit changes: %w", err) } return nil diff --git a/pkg/registry/apis/provisioning/repository/git/staged.go b/pkg/registry/apis/provisioning/repository/git/staged.go index a3f79567029..f55eb709341 100644 --- a/pkg/registry/apis/provisioning/repository/git/staged.go +++ b/pkg/registry/apis/provisioning/repository/git/staged.go @@ -219,12 +219,24 @@ func (r *stagedGitRepository) Push(ctx context.Context) error { if message == "" { message = "Staged changes" } + if err := r.commit(ctx, r.writer, message); err != nil { return err } } - return r.writer.Push(ctx) + err := r.writer.Push(ctx) + if err != nil { + // Convert nanogit-specific errors to repository-level errors to avoid leaky abstraction + if errors.Is(err, nanogit.ErrNothingToPush) { + return repository.ErrNothingToPush + } + if errors.Is(err, nanogit.ErrNothingToCommit) { + return repository.ErrNothingToCommit + } + return err + } + return nil } func (r *stagedGitRepository) Remove(ctx context.Context) error { diff --git a/pkg/registry/apis/provisioning/repository/git/staged_test.go b/pkg/registry/apis/provisioning/repository/git/staged_test.go index 4501a087e7a..77c1d8b5edb 100644 --- a/pkg/registry/apis/provisioning/repository/git/staged_test.go +++ b/pkg/registry/apis/provisioning/repository/git/staged_test.go @@ -3,6 +3,7 @@ package git import ( "context" "errors" + "fmt" "strings" "testing" "time" @@ -995,6 +996,54 @@ func TestStagedGitRepository_Push(t *testing.T) { expectPushCalls: 1, expectCommitCalls: 1, }, + { + name: "returns repository ErrNothingToPush when nanogit returns ErrNothingToPush", + opts: repository.StageOptions{}, + setupMock: func(mockWriter *mocks.FakeStagedWriter) { + mockWriter.PushReturns(nanogit.ErrNothingToPush) + }, + wantError: repository.ErrNothingToPush, + expectPushCalls: 1, + expectCommitCalls: 0, + }, + { + name: "returns repository ErrNothingToCommit when nanogit returns ErrNothingToCommit", + opts: repository.StageOptions{ + Mode: repository.StageModeCommitOnlyOnce, + }, + setupMock: func(mockWriter *mocks.FakeStagedWriter) { + mockWriter.CommitReturns(nil, nanogit.ErrNothingToCommit) + }, + wantError: repository.ErrNothingToCommit, + expectPushCalls: 0, + expectCommitCalls: 1, + }, + { + name: "returns repository ErrNothingToPush when nanogit returns wrapped ErrNothingToPush", + opts: repository.StageOptions{}, + setupMock: func(mockWriter *mocks.FakeStagedWriter) { + // Use fmt.Errorf with %w to create a wrapped error that errors.Is can detect + wrappedErr := fmt.Errorf("git operation failed: %w", nanogit.ErrNothingToPush) + mockWriter.PushReturns(wrappedErr) + }, + wantError: repository.ErrNothingToPush, + expectPushCalls: 1, + expectCommitCalls: 0, + }, + { + name: "returns repository ErrNothingToCommit when nanogit returns wrapped ErrNothingToCommit", + opts: repository.StageOptions{ + Mode: repository.StageModeCommitOnlyOnce, + }, + setupMock: func(mockWriter *mocks.FakeStagedWriter) { + // Use fmt.Errorf with %w to create a wrapped error that errors.Is can detect + wrappedErr := fmt.Errorf("git operation failed: %w", nanogit.ErrNothingToCommit) + mockWriter.CommitReturns(nil, wrappedErr) + }, + wantError: repository.ErrNothingToCommit, + expectPushCalls: 0, + expectCommitCalls: 1, + }, } for _, tt := range tests { @@ -1007,7 +1056,12 @@ func TestStagedGitRepository_Push(t *testing.T) { err := stagedRepo.Push(context.Background()) if tt.wantError != nil { - require.EqualError(t, err, tt.wantError.Error()) + // For nanogit error conversion tests, use ErrorIs to verify type conversion + if errors.Is(tt.wantError, repository.ErrNothingToPush) || errors.Is(tt.wantError, repository.ErrNothingToCommit) { + require.ErrorIs(t, err, tt.wantError) + } else { + require.EqualError(t, err, tt.wantError.Error()) + } } else { require.NoError(t, err) } diff --git a/pkg/registry/apis/provisioning/repository/staged.go b/pkg/registry/apis/provisioning/repository/staged.go index ca5b59c72c9..1861d66336c 100644 --- a/pkg/registry/apis/provisioning/repository/staged.go +++ b/pkg/registry/apis/provisioning/repository/staged.go @@ -7,9 +7,14 @@ import ( "time" "github.com/grafana/grafana-app-sdk/logging" - "github.com/grafana/nanogit" ) +// ErrNothingToPush indicates that there are no changes to push to the remote repository +var ErrNothingToPush = errors.New("nothing to push") + +// ErrNothingToCommit indicates that there are no changes to commit +var ErrNothingToCommit = errors.New("nothing to commit") + //go:generate mockery --name WrapWithStageFn --structname MockWrapWithStageFn --inpackage --filename mock_wrap_with_stage_fn.go --with-expecter type WrapWithStageFn func(ctx context.Context, repo Repository, stageOptions StageOptions, fn func(repo Repository, staged bool) error) error @@ -83,7 +88,7 @@ func WrapWithStageAndPushIfPossible( } if err = staged.Push(ctx); err != nil { - if errors.Is(err, nanogit.ErrNothingToPush) { + if errors.Is(err, ErrNothingToPush) || errors.Is(err, ErrNothingToCommit) { return nil // OK, already pushed } return fmt.Errorf("wrapped push error: %w", err) diff --git a/pkg/registry/apis/provisioning/repository/staged_test.go b/pkg/registry/apis/provisioning/repository/staged_test.go index 3efe8ebbd5e..c640e2cd0db 100644 --- a/pkg/registry/apis/provisioning/repository/staged_test.go +++ b/pkg/registry/apis/provisioning/repository/staged_test.go @@ -3,6 +3,7 @@ package repository import ( "context" "errors" + "fmt" "testing" "github.com/stretchr/testify/mock" @@ -127,6 +128,84 @@ func TestWrapWithStageAndPushIfPossible(t *testing.T) { return nil }, }, + { + name: "nothing to push - should not error", + setupMocks: func(t *testing.T) *mockStagedRepo { + mockRepo := NewMockStageableRepository(t) + mockStaged := NewMockStagedRepository(t) + + mockRepo.EXPECT().Stage(mock.Anything, StageOptions{}).Return(mockStaged, nil) + mockStaged.EXPECT().Push(mock.Anything).Return(ErrNothingToPush) + mockStaged.EXPECT().Remove(mock.Anything).Return(nil) + + return &mockStagedRepo{ + MockStageableRepository: mockRepo, + MockStagedRepository: mockStaged, + } + }, + operation: func(repo Repository, staged bool) error { + return nil + }, + }, + { + name: "nothing to commit - should not error", + setupMocks: func(t *testing.T) *mockStagedRepo { + mockRepo := NewMockStageableRepository(t) + mockStaged := NewMockStagedRepository(t) + + mockRepo.EXPECT().Stage(mock.Anything, StageOptions{}).Return(mockStaged, nil) + mockStaged.EXPECT().Push(mock.Anything).Return(ErrNothingToCommit) + mockStaged.EXPECT().Remove(mock.Anything).Return(nil) + + return &mockStagedRepo{ + MockStageableRepository: mockRepo, + MockStagedRepository: mockStaged, + } + }, + operation: func(repo Repository, staged bool) error { + return nil + }, + }, + { + name: "wrapped nothing to push error - should not error", + setupMocks: func(t *testing.T) *mockStagedRepo { + mockRepo := NewMockStageableRepository(t) + mockStaged := NewMockStagedRepository(t) + + wrappedErr := fmt.Errorf("some wrapper: %w", ErrNothingToPush) + mockRepo.EXPECT().Stage(mock.Anything, StageOptions{}).Return(mockStaged, nil) + mockStaged.EXPECT().Push(mock.Anything).Return(wrappedErr) + mockStaged.EXPECT().Remove(mock.Anything).Return(nil) + + return &mockStagedRepo{ + MockStageableRepository: mockRepo, + MockStagedRepository: mockStaged, + } + }, + operation: func(repo Repository, staged bool) error { + return nil + }, + }, + { + name: "wrapped nothing to commit error - should not error", + setupMocks: func(t *testing.T) *mockStagedRepo { + mockRepo := NewMockStageableRepository(t) + mockStaged := NewMockStagedRepository(t) + + wrappedErr := fmt.Errorf("some wrapper: %w", ErrNothingToCommit) + mockRepo.EXPECT().Stage(mock.Anything, StageOptions{}).Return(mockStaged, nil) + mockStaged.EXPECT().Push(mock.Anything).Return(wrappedErr) + mockStaged.EXPECT().Remove(mock.Anything).Return(nil) + + return &mockStagedRepo{ + MockStageableRepository: mockRepo, + MockStagedRepository: mockStaged, + } + }, + operation: func(repo Repository, staged bool) error { + return nil + }, + }, } for _, tt := range tests { diff --git a/pkg/registry/apis/provisioning/resources/resources.go b/pkg/registry/apis/provisioning/resources/resources.go index 28dd06ea43a..ec5942c21ec 100644 --- a/pkg/registry/apis/provisioning/resources/resources.go +++ b/pkg/registry/apis/provisioning/resources/resources.go @@ -92,19 +92,29 @@ func (r *ResourcesManager) WriteResourceFileFromObject(ctx context.Context, obj if title == "" { title = name } - folder := meta.GetFolder() + folder := meta.GetFolder() // Get the absolute path of the folder rootFolder := RootFolder(r.repo.Config()) - fid, ok := r.folders.Tree().DirPath(folder, rootFolder) - if !ok { - return "", fmt.Errorf("folder not found in tree: %s", folder) + + // If no folder is specified in the file, set it to the root to ensure everything is written under it + var fid Folder + if folder == "" { + fid = Folder{ID: rootFolder} + meta.SetFolder(rootFolder) // Set the folder in the metadata to the root folder + } else { + var ok bool + fid, ok = r.folders.Tree().DirPath(folder, rootFolder) + if !ok { + return "", fmt.Errorf("folder %s NOT found in tree with root: %s", folder, rootFolder) + } } fileName := slugify.Slugify(title) + ".json" if fid.Path != "" { fileName = safepath.Join(fid.Path, fileName) } + if options.Path != "" { fileName = safepath.Join(options.Path, fileName) } diff --git a/pkg/tests/apis/provisioning/helper_test.go b/pkg/tests/apis/provisioning/helper_test.go index 2d5585b819f..03ca9342f31 100644 --- a/pkg/tests/apis/provisioning/helper_test.go +++ b/pkg/tests/apis/provisioning/helper_test.go @@ -112,11 +112,11 @@ func (h *provisioningTestHelper) AwaitJobSuccess(t *testing.T, ctx context.Conte require.NoError(t, err) require.NotNil(t, result) + errors := mustNestedStringSlice(result.Object, "status", "errors") + require.Empty(t, errors, "historic job '%s' has errors: %v", job.GetName(), errors) state := mustNestedString(result.Object, "status", "state") require.Equal(t, string(provisioning.JobStateSuccess), state, "historic job '%s' was not successful", job.GetName()) - errors := mustNestedStringSlice(result.Object, "status", "errors") - require.Empty(t, errors, "historic job '%s' has errors: %v", job.GetName(), errors) }, time.Second*10, time.Millisecond*25) { // We also want to add the job details to the error when it fails. job, err := h.Jobs.Resource.Get(ctx, job.GetName(), metav1.GetOptions{}) @@ -163,6 +163,50 @@ func (h *provisioningTestHelper) AwaitJobs(t *testing.T, repoName string) { } } +// AwaitJobsWithStates waits for all jobs for a repository to complete and accepts multiple valid end states +func (h *provisioningTestHelper) AwaitJobsWithStates(t *testing.T, repoName string, acceptedStates []string) { + t.Helper() + + // First, we wait for all jobs for the repository to disappear (i.e. complete/fail). + require.EventuallyWithT(t, func(collect *assert.CollectT) { + list, err := h.Jobs.Resource.List(context.Background(), metav1.ListOptions{}) + if assert.NoError(collect, err, "failed to list active jobs") { + for _, elem := range list.Items { + repo, _, err := unstructured.NestedString(elem.Object, "spec", "repository") + require.NoError(t, err) + if repo == repoName { + collect.Errorf("there are still remaining jobs for %s: %+v", repoName, elem) + return + } + } + } + }, time.Second*10, time.Millisecond*25, "job queue must be empty") + + // Then, as all jobs are now historic jobs, we make sure they are in an accepted state. + result, err := h.Repositories.Resource.Get(context.Background(), repoName, metav1.GetOptions{}, "jobs") + require.NoError(t, err, "failed to list historic jobs") + + list, err := result.ToList() + require.NoError(t, err, "results should be a list") + require.NotEmpty(t, list.Items, "expect at least one job") + + for _, elem := range list.Items { + require.Equal(t, repoName, elem.GetLabels()[jobs.LabelRepository], "should have repo label") + + state := mustNestedString(elem.Object, "status", "state") + + // Check if state is in accepted states + found := false + for _, acceptedState := range acceptedStates { + if state == acceptedState { + found = true + break + } + } + require.True(t, found, "job %s completed with unexpected state %s (expected one of %v): %+v", elem.GetName(), state, acceptedStates, elem.Object) + } +} + // RenderObject reads the filePath and renders it as a template with the given values. // The template is expected to be a YAML or JSON file. // diff --git a/pkg/tests/apis/provisioning/provisioning_test.go b/pkg/tests/apis/provisioning/provisioning_test.go index cdf210e2133..e04406787fe 100644 --- a/pkg/tests/apis/provisioning/provisioning_test.go +++ b/pkg/tests/apis/provisioning/provisioning_test.go @@ -2107,3 +2107,196 @@ func TestIntegrationProvisioning_MoveResources(t *testing.T) { }, time.Second*10, time.Millisecond*100, "Expected move job to handle non-existent resource") }) } + +func TestIntegrationProvisioning_SecondRepositoryOnlyExportsNewDashboards(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + + helper := runGrafana(t) + ctx := context.Background() + + // Create some unmanaged dashboards directly in Grafana first + dashboard1 := helper.LoadYAMLOrJSONFile("exportunifiedtorepository/dashboard-test-v1.yaml") + dashboard1Obj, err := helper.DashboardsV1.Resource.Create(ctx, dashboard1, metav1.CreateOptions{}) + require.NoError(t, err, "should be able to create first dashboard") + dashboard1Name := dashboard1Obj.GetName() + + dashboard2 := helper.LoadYAMLOrJSONFile("exportunifiedtorepository/dashboard-test-v2beta1.yaml") + dashboard2Obj, err := helper.DashboardsV2beta1.Resource.Create(ctx, dashboard2, metav1.CreateOptions{}) + require.NoError(t, err, "should be able to create second dashboard") + dashboard2Name := dashboard2Obj.GetName() + + // Create the first repository with sync enabled + const repo1 = "first-repository" + repo1Path := filepath.Join(helper.ProvisioningPath, repo1) + err = os.MkdirAll(repo1Path, 0750) + require.NoError(t, err, "should be able to create repository path") + + createBody1 := helper.RenderObject(t, "testdata/local-write.json.tmpl", map[string]any{ + "Name": repo1, + "SyncEnabled": true, + "SyncTarget": "folder", + "Path": repo1Path, + }) + _, err = helper.Repositories.Resource.Create(ctx, createBody1, metav1.CreateOptions{}) + require.NoError(t, err, "should be able to create first repository") + + // Print file tree before export + printFileTree(t, helper.ProvisioningPath) + + // Initial export + result := helper.AdminREST.Post(). + Namespace("default"). + Resource("repositories"). + Name(repo1). + SubResource("jobs"). + SetHeader("Content-Type", "application/json"). + Body(asJSON(&provisioning.JobSpec{ + Push: &provisioning.ExportJobOptions{ + Folder: "", // export entire instance + Path: "", // no prefix necessary for testing + }, + })). + Do(ctx) + require.NoError(t, result.Error(), "should be able to create export job for first repo") + helper.AwaitJobsWithStates(t, repo1, []string{"success"}) + // Wait for first repository to sync + helper.SyncAndWait(t, repo1, nil) + + printFileTree(t, helper.ProvisioningPath) + // Verify that the first repository has claimed ownership of the dashboards + managedDash1, err := helper.DashboardsV1.Resource.Get(ctx, dashboard1Name, metav1.GetOptions{}) + require.NoError(t, err) + require.Equal(t, repo1, managedDash1.GetAnnotations()[utils.AnnoKeyManagerIdentity], "dashboard1 should be managed by first repo") + + managedDash2, err := helper.DashboardsV2beta1.Resource.Get(ctx, dashboard2Name, metav1.GetOptions{}) + require.NoError(t, err) + require.Equal(t, repo1, managedDash2.GetAnnotations()[utils.AnnoKeyManagerIdentity], "dashboard2 should be managed by first repo") + + // Create second repository - enable sync and set different target + + const repo2 = "second-repository" + repo2Path := filepath.Join(helper.ProvisioningPath, repo2) + err = os.MkdirAll(repo2Path, 0750) + require.NoError(t, err, "should be able to create seconrd repository path") + + printFileTree(t, helper.ProvisioningPath) + + createBody2 := helper.RenderObject(t, "testdata/local-write.json.tmpl", map[string]any{ + "Name": repo2, + "SyncEnabled": true, + "SyncTarget": "folder", + "Path": repo2Path, + }) + + _, err = helper.Repositories.Resource.Create(ctx, createBody2, metav1.CreateOptions{}) + require.NoError(t, err, "should be able to create second repository") + + // Wait for second repository to sync + helper.SyncAndWait(t, repo2, nil) + + // Validate that folders for both repositories exist + folders, err := helper.Folders.Resource.List(ctx, metav1.ListOptions{}) + require.NoError(t, err, "should be able to list folders") + + var repo1FolderFound, repo2FolderFound bool + for _, folder := range folders.Items { + if folder.GetName() == repo1 { + repo1FolderFound = true + } + if folder.GetName() == repo2 { + repo2FolderFound = true + } + } + require.True(t, repo1FolderFound, "folder for first repository %s should exist after sync", repo1) + require.True(t, repo2FolderFound, "folder for second repository %s should exist after sync", repo2) + + // Create a third dashboard that won't be claimed by the first repo + dashboard3 := helper.LoadYAMLOrJSONFile("exportunifiedtorepository/dashboard-test-v0.yaml") + dashboard3Obj, err := helper.DashboardsV0.Resource.Create(ctx, dashboard3, metav1.CreateOptions{}) + require.NoError(t, err, "should be able to create third dashboard") + dashboard3Name := dashboard3Obj.GetName() + + // Verify dashboard3 is not managed by anyone initially + unmanagedDash3, err := helper.DashboardsV0.Resource.Get(ctx, dashboard3Name, metav1.GetOptions{}) + require.NoError(t, err) + manager, found := unmanagedDash3.GetAnnotations()[utils.AnnoKeyManagerIdentity] + require.True(t, !found || manager == "", "dashboard3 should not be managed initially") + + printFileTree(t, helper.ProvisioningPath) + // Count files in first repo before second export + files1Before, err := countFilesInDir(repo1Path) + require.NoError(t, err) + + // Export from second repository - this should only export the unmanaged dashboard3 + result = helper.AdminREST.Post(). + Namespace("default"). + Resource("repositories"). + Name(repo2). + SubResource("jobs"). + SetHeader("Content-Type", "application/json"). + Body(asJSON(&provisioning.JobSpec{ + Push: &provisioning.ExportJobOptions{ + Folder: "", // export entire instance + Path: "", // no prefix necessary for testing + }, + })). + Do(ctx) + require.NoError(t, result.Error(), "should be able to create export job for second repo") + + // Wait for second repository export to complete + helper.AwaitJobsWithStates(t, repo2, []string{"success"}) + + // Wait for second repository to sync + helper.SyncAndWait(t, repo1, nil) + helper.SyncAndWait(t, repo2, nil) + + printFileTree(t, helper.ProvisioningPath) + files1After, err := countFilesInDir(repo1Path) + require.NoError(t, err) + + actualNewFiles := files1After - files1Before + require.Equal(t, 0, actualNewFiles, + "second repository should skip managed dashboards and had folder issues with unmanaged dashboard (expected %d new files, got %d)", + 0, actualNewFiles) + + // Verify files in the second repository + files2After, err := countFilesInDir(repo2Path) + require.NoError(t, err) + require.Equal(t, 1, files2After, + "second repository should only export the unmanaged dashboard (expected %d new files, got %d)", + 1, files2After) + + // Verify dashboard1 and dashboard2 are still managed by repo1 (unchanged) + stillManagedDash1, err := helper.DashboardsV1.Resource.Get(ctx, dashboard1Name, metav1.GetOptions{}) + require.NoError(t, err) + require.Equal(t, repo1, stillManagedDash1.GetAnnotations()[utils.AnnoKeyManagerIdentity], + "dashboard1 should still be managed by first repo") + + stillManagedDash2, err := helper.DashboardsV2beta1.Resource.Get(ctx, dashboard2Name, metav1.GetOptions{}) + require.NoError(t, err) + require.Equal(t, repo1, stillManagedDash2.GetAnnotations()[utils.AnnoKeyManagerIdentity], + "dashboard2 should still be managed by first repo") + + // Verify dashboard3 is now managed by repo2 + stillManagedDash3, err := helper.DashboardsV0.Resource.Get(ctx, dashboard3Name, metav1.GetOptions{}) + require.NoError(t, err) + require.Equal(t, repo2, stillManagedDash3.GetAnnotations()[utils.AnnoKeyManagerIdentity], + "dashboard3 should now be managed by second repo") +} + +// Helper function to count files in a directory recursively +func countFilesInDir(rootPath string) (int, error) { + count := 0 + err := filepath.WalkDir(rootPath, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if !d.IsDir() { + count++ + } + return nil + }) + return count, err +} From 3f90c85c4eea9657bac14b49c925ba32d208c54e Mon Sep 17 00:00:00 2001 From: Matias Chomicki Date: Fri, 1 Aug 2025 13:30:17 +0200 Subject: [PATCH 14/89] New Logs Context: Logs context using the new Logs Panel (#108852) * LogLineContext: initial support * LogLineContext: infinite scroll bottom * LogLineContext: clean up styles and support both scrolls * InfiniteScroll: support top scrolling * LogLineContext: support center matched line * LogLineContext: read options from storage * LogLineContext: move padding container * LogLineContext: reset on ui change * LogLineContext: improve sort order and fix open in split * LogLineContext: show log line * Translations * LogsPanel: integrate new context component * LogLineContext: add unit test * Prettier * Remove unused import * InfiniteScroll: add "scroll to load more" top * LogLineContext: rename collapsible * Update tests * LogLineContext: refactor center button * LogLineContext: handle overflow in small viewports * LogLineContext: format referenced log line * Memoize * LogLineContext: make modal bigger * LogList: improve a11y * LogLineContext: flexbox magic * LogLineContext: revert center button change * LogsPanel: hide overflow * LogLineContext: responsive min-height * LogLineContext: fix wrap log message * InfiniteScroll: improve direction handling * Add feature flag * Implement feature flag * InfiniteScroll: report direction --- .../src/types/featureToggles.gen.ts | 4 + pkg/services/featuremgmt/registry.go | 7 + pkg/services/featuremgmt/toggles_gen.csv | 1 + pkg/services/featuremgmt/toggles_gen.go | 4 + pkg/services/featuremgmt/toggles_gen.json | 13 + public/app/features/explore/Logs/Logs.tsx | 18 +- .../logs/components/InfiniteScroll.tsx | 2 +- .../logs/components/panel/InfiniteScroll.tsx | 115 +++- .../logs/components/panel/LogLine.tsx | 8 + .../components/panel/LogLineContext.test.tsx | 545 ++++++++++++++++++ .../logs/components/panel/LogLineContext.tsx | 447 ++++++++++++++ .../panel/LogLineDetailsComponent.tsx | 5 +- .../components/panel/LogLineDetailsLog.tsx | 5 +- .../logs/components/panel/LogList.tsx | 71 ++- .../logs/components/panel/virtualization.ts | 2 +- public/app/plugins/panel/logs/LogsPanel.tsx | 18 +- public/locales/en-US/grafana.json | 9 + 17 files changed, 1207 insertions(+), 67 deletions(-) create mode 100644 public/app/features/logs/components/panel/LogLineContext.test.tsx create mode 100644 public/app/features/logs/components/panel/LogLineContext.tsx diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 87a3dee8d06..68564d1ce0e 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -1091,4 +1091,8 @@ export interface FeatureToggles { * Enable adhoc filter buttons in visualization tooltips */ adhocFiltersInTooltips?: boolean; + /** + * New Log Context component + */ + newLogContext?: boolean; } diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index 9a0c468f0f1..7b74ad685e8 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -1890,6 +1890,13 @@ var ( Owner: grafanaDataProSquad, FrontendOnly: true, }, + { + Name: "newLogContext", + Description: "New Log Context component", + Stage: FeatureStageExperimental, + Owner: grafanaObservabilityLogsSquad, + FrontendOnly: true, + }, } ) diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index 14f65065ed9..6e5c55cfd35 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -244,3 +244,4 @@ dashboardDsAdHocFiltering,experimental,@grafana/datapro,false,false,true dashboardLevelTimeMacros,experimental,@grafana/dashboards-squad,false,false,true alertmanagerRemoteSecondaryWithRemoteState,experimental,@grafana/alerting-squad,false,false,false adhocFiltersInTooltips,experimental,@grafana/datapro,false,false,true +newLogContext,experimental,@grafana/observability-logs,false,false,true diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index c74ce4befc4..0b00cf45ac1 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -986,4 +986,8 @@ const ( // FlagAdhocFiltersInTooltips // Enable adhoc filter buttons in visualization tooltips FlagAdhocFiltersInTooltips = "adhocFiltersInTooltips" + + // FlagNewLogContext + // New Log Context component + FlagNewLogContext = "newLogContext" ) diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index 2324d34c0f8..e47603d79d4 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -2150,6 +2150,19 @@ "expression": "false" } }, + { + "metadata": { + "name": "newLogContext", + "resourceVersion": "1754044501326", + "creationTimestamp": "2025-08-01T10:35:01Z" + }, + "spec": { + "description": "New Log Context component", + "stage": "experimental", + "codeowner": "@grafana/observability-logs", + "frontend": true + } + }, { "metadata": { "name": "newLogsPanel", diff --git a/public/app/features/explore/Logs/Logs.tsx b/public/app/features/explore/Logs/Logs.tsx index a6d4040a446..fbac705c277 100644 --- a/public/app/features/explore/Logs/Logs.tsx +++ b/public/app/features/explore/Logs/Logs.tsx @@ -52,6 +52,7 @@ import { ControlledLogRows } from 'app/features/logs/components/ControlledLogRow import { InfiniteScroll } from 'app/features/logs/components/InfiniteScroll'; import { LogRows } from 'app/features/logs/components/LogRows'; import { LogRowContextModal } from 'app/features/logs/components/log-context/LogRowContextModal'; +import { LogLineContext } from 'app/features/logs/components/panel/LogLineContext'; import { LogList, LogListControlOptions } from 'app/features/logs/components/panel/LogList'; import { isDedupStrategy, isLogsSortOrder } from 'app/features/logs/components/panel/LogListContext'; import { LogLevelColor, dedupLogRows } from 'app/features/logs/logsModel'; @@ -767,7 +768,7 @@ const UnthemedLogs: React.FunctionComponent = (props: Props) => { return ( <> - {getRowContext && contextRow && ( + {(!config.featureToggles.newLogsPanel || !config.featureToggles.newLogContext) && getRowContext && contextRow && ( = (props: Props) => { timeZone={timeZone} /> )} + {config.featureToggles.newLogsPanel && config.featureToggles.newLogContext && getRowContext && contextRow && ( + getRowContext(row, contextRow, options)} + getRowContextQuery={getRowContextQuery} + getLogRowContextUi={getLogRowContextUi} + logOptionsStorageKey={SETTING_KEY_ROOT} + timeZone={timeZone} + displayedFields={displayedFields} + onClickShowField={showField} + onClickHideField={hideField} + /> + )} ReactNode; displayedFields: string[]; handleOverflow: (index: number, id: string, height?: number) => void; - loadMore?: (range: AbsoluteTimeRange) => void; + infiniteScrollMode: InfiniteScrollMode; + loadMore?: LoadMoreLogsType; logs: LogListModel[]; onClick: (e: MouseEvent, log: LogListModel) => void; scrollElement: HTMLDivElement | null; @@ -38,12 +39,17 @@ interface Props { wrapLogMessage: boolean; } -type InfiniteLoaderState = 'idle' | 'out-of-bounds' | 'pre-scroll' | 'loading'; +type InfiniteLoaderState = 'idle' | 'out-of-bounds' | 'pre-scroll-top' | 'pre-scroll-bottom' | 'loading'; +export type InfiniteScrollMode = 'interval' | 'unlimited'; +export type LoadMoreLogsType = + | ((range: AbsoluteTimeRange) => void) + | ((range: AbsoluteTimeRange, scrollDirection: ScrollDirection) => void); export const InfiniteScroll = ({ children, displayedFields, handleOverflow, + infiniteScrollMode, loadMore, logs, onClick, @@ -65,6 +71,7 @@ export const InfiniteScroll = ({ const countRef = useRef(0); const lastLogOfPage = useRef([]); const styles = useStyles2(getStyles, virtualization); + const resetStateTimeout = useRef | null>(null); useEffect(() => { // Logs have not changed, ignore effect @@ -74,12 +81,14 @@ export const InfiniteScroll = ({ // New logs are from infinite scrolling if (infiniteLoaderState === 'loading') { // out-of-bounds if no new logs returned - setInfiniteLoaderState(logs.length === prevLogs.length ? 'out-of-bounds' : 'idle'); + setInfiniteLoaderState( + logs.length === prevLogs.length && infiniteScrollMode === 'interval' ? 'out-of-bounds' : 'idle' + ); } else { lastLogOfPage.current = []; setAutoScroll(true); } - }, [infiniteLoaderState, logs, prevLogs]); + }, [infiniteLoaderState, infiniteScrollMode, logs, prevLogs]); useEffect(() => { if (prevSortOrder && prevSortOrder !== sortOrder) { @@ -94,21 +103,31 @@ export const InfiniteScroll = ({ } }, [autoScroll, setInitialScrollPosition]); - const onLoadMore = useCallback(() => { - const newRange = canScrollBottom(getVisibleRange(logs), timeRange, timeZone, sortOrder); - if (!newRange) { - setInfiniteLoaderState('out-of-bounds'); - return; - } - lastLogOfPage.current.push(logs[logs.length - 1].uid); - setInfiniteLoaderState('loading'); - loadMore?.(newRange); + const onLoadMore = useCallback( + (scrollDirection: ScrollDirection) => { + const newRange = + scrollDirection === ScrollDirection.Bottom + ? canScrollBottom(getVisibleRange(logs), timeRange, timeZone, sortOrder) + : canScrollTop(getVisibleRange(logs), timeRange, timeZone, sortOrder); + if (!newRange && infiniteScrollMode === 'interval') { + setInfiniteLoaderState('out-of-bounds'); + return; + } + if (scrollDirection === ScrollDirection.Bottom) { + lastLogOfPage.current.push(logs[logs.length - 1].uid); + } else { + lastLogOfPage.current.push(logs[0].uid); + } + setInfiniteLoaderState('loading'); + loadMore?.(newRange ?? getVisibleRange(logs), scrollDirection); - reportInteraction('grafana_logs_infinite_scrolling', { - direction: 'bottom', - sort_order: sortOrder, - }); - }, [loadMore, logs, sortOrder, timeRange, timeZone]); + reportInteraction('grafana_logs_infinite_scrolling', { + direction: scrollDirection, + sort_order: sortOrder, + }); + }, + [infiniteScrollMode, loadMore, logs, sortOrder, timeRange, timeZone] + ); useEffect(() => { if (!scrollElement || !loadMore || !config.featureToggles.logsInfiniteScrolling) { @@ -116,14 +135,24 @@ export const InfiniteScroll = ({ } function handleScroll(event: Event | WheelEvent) { - if (!scrollElement || !loadMore || !logs.length || infiniteLoaderState !== 'pre-scroll') { + if (!scrollElement || !loadMore || !logs.length) { return; } const scrollDirection = shouldLoadMore(event, lastEvent.current, countRef, scrollElement, lastScroll.current); lastEvent.current = event; lastScroll.current = scrollElement.scrollTop; - if (scrollDirection === ScrollDirection.Bottom) { - onLoadMore(); + if (infiniteLoaderState !== 'pre-scroll-bottom' && infiniteLoaderState !== 'pre-scroll-top') { + if (infiniteScrollMode === 'unlimited' && scrollDirection === ScrollDirection.Top) { + setInfiniteLoaderState('pre-scroll-top'); + resetStateTimeout.current = setTimeout(() => { + setInfiniteLoaderState((state) => (state === 'pre-scroll-top' ? 'idle' : state)); + }, 10000); + return; + } + return; + } + if (scrollDirection !== ScrollDirection.NoScroll) { + onLoadMore(scrollDirection); } } @@ -134,7 +163,26 @@ export const InfiniteScroll = ({ scrollElement.removeEventListener('scroll', handleScroll); scrollElement.removeEventListener('wheel', handleScroll); }; - }, [infiniteLoaderState, loadMore, logs.length, onLoadMore, scrollElement]); + }, [infiniteLoaderState, infiniteScrollMode, loadMore, logs.length, onLoadMore, scrollElement]); + + useEffect(() => { + return () => { + if (resetStateTimeout.current) { + clearTimeout(resetStateTimeout.current); + } + }; + }, []); + + const loadMoreTop = useCallback(() => { + if (resetStateTimeout.current) { + clearTimeout(resetStateTimeout.current); + } + onLoadMore(ScrollDirection.Top); + }, [onLoadMore]); + + const loadMoreBottom = useCallback(() => { + onLoadMore(ScrollDirection.Bottom); + }, [onLoadMore]); const Renderer = useCallback( ({ index, style }: ListChildComponentProps) => { @@ -143,7 +191,7 @@ export const InfiniteScroll = ({ {getMessageFromInfiniteLoaderState(infiniteLoaderState, sortOrder)} @@ -170,9 +218,9 @@ export const InfiniteScroll = ({ displayedFields, handleOverflow, infiniteLoaderState, + loadMoreBottom, logs, onClick, - onLoadMore, showTime, sortOrder, styles, @@ -192,7 +240,7 @@ export const InfiniteScroll = ({ const lastLogIndex = logs.length - 1; const preScrollIndex = logs.length - 2; if (props.visibleStopIndex >= lastLogIndex) { - setInfiniteLoaderState('pre-scroll'); + setInfiniteLoaderState('pre-scroll-bottom'); } else if (props.visibleStartIndex < preScrollIndex) { setInfiniteLoaderState('idle'); } @@ -204,7 +252,18 @@ export const InfiniteScroll = ({ const itemCount = logs.length && loadMore && infiniteLoaderState !== 'idle' ? logs.length + 1 : logs.length; - return <>{children({ getItemKey, itemCount, onItemsRendered, Renderer })}; + return ( + <> + {infiniteLoaderState === 'pre-scroll-top' && ( +
+ + {t('logs.infinite-scroll.load-more', 'Scroll to load more')} + +
+ )} + {children({ getItemKey, itemCount, onItemsRendered, Renderer })} + + ); }; function getMessageFromInfiniteLoaderState(state: InfiniteLoaderState, order: LogsSortOrder) { @@ -220,7 +279,7 @@ function getMessageFromInfiniteLoaderState(state: InfiniteLoaderState, order: Lo ); - case 'pre-scroll': + case 'pre-scroll-bottom': return t('logs.infinite-scroll.load-more', 'Scroll to load more'); default: return null; diff --git a/public/app/features/logs/components/panel/LogLine.tsx b/public/app/features/logs/components/panel/LogLine.tsx index 4f099dac59a..f3b994250f5 100644 --- a/public/app/features/logs/components/panel/LogLine.tsx +++ b/public/app/features/logs/components/panel/LogLine.tsx @@ -524,6 +524,14 @@ export const getStyles = (theme: GrafanaTheme2, virtualization?: LogLineVirtuali border: 'none', display: 'inline', }), + loadMoreTopContainer: css({ + backgroundColor: tinycolor(theme.colors.background.primary).setAlpha(0.75).toString(), + left: 0, + position: 'absolute', + top: 0, + width: '100%', + zIndex: theme.zIndex.navbarFixed, + }), overflows: css({ outline: 'solid 1px red', }), diff --git a/public/app/features/logs/components/panel/LogLineContext.test.tsx b/public/app/features/logs/components/panel/LogLineContext.test.tsx new file mode 100644 index 00000000000..31f77df4f3e --- /dev/null +++ b/public/app/features/logs/components/panel/LogLineContext.test.tsx @@ -0,0 +1,545 @@ +import { render, screen, waitFor, userEvent } from 'test/test-utils'; + +import { + createDataFrame, + FieldType, + LogRowContextQueryDirection, + LogsSortOrder, + SplitOpenOptions, +} from '@grafana/data'; + +import { dataFrameToLogsModel } from '../../logsModel'; + +import { LogLineContext } from './LogLineContext'; + +jest.mock('@grafana/assistant', () => ({ + ...jest.requireActual('@grafana/assistant'), + useAssistant: jest.fn(() => [true, jest.fn()]), +})); + +const dfBefore = createDataFrame({ + fields: [ + { + name: 'time', + type: FieldType.time, + values: ['2019-04-26T07:28:11.352440161Z', '2019-04-26T09:28:11.352440161Z'], + }, + { + name: 'message', + type: FieldType.string, + values: ['foo123', 'foo123'], + }, + ], +}); +const dfNow = createDataFrame({ + fields: [ + { + name: 'time', + type: FieldType.time, + values: ['2019-04-26T09:28:11.352440161Z'], + }, + { + name: 'message', + type: FieldType.string, + values: ['foo123'], + }, + ], +}); +const dfAfter = createDataFrame({ + fields: [ + { + name: 'time', + type: FieldType.time, + values: ['2019-04-26T14:42:50.991981292Z', '2019-04-26T16:28:11.352440161Z'], + }, + { + name: 'message', + type: FieldType.string, + values: ['foo123', 'bar123'], + }, + ], +}); + +let getRowContext = jest.fn(); +const dispatchMock = jest.fn(); +jest.mock('app/types/store', () => ({ + ...jest.requireActual('app/types/store'), + useDispatch: () => dispatchMock, +})); + +const splitOpenSym = Symbol('splitOpen'); +const splitOpen = jest.fn().mockReturnValue(splitOpenSym); +jest.mock('app/features/explore/state/main', () => ({ + ...jest.requireActual('app/features/explore/state/main'), + splitOpen: (arg?: SplitOpenOptions) => { + return splitOpen(arg); + }, +})); + +const logs = dataFrameToLogsModel([dfNow]); +const row = logs.rows[0]; + +const timeZone = 'UTC'; + +describe('LogLineContext', () => { + let uniqueRefIdCounter = 1; + + beforeEach(() => { + uniqueRefIdCounter = 1; + getRowContext = jest.fn().mockImplementation(async (_, options) => { + uniqueRefIdCounter += 1; + const refId = `refid_${uniqueRefIdCounter}`; + if (options.direction === LogRowContextQueryDirection.Forward) { + return { + data: [ + { + refId, + ...dfBefore, + }, + ], + }; + } else { + return { + data: [ + { + refId, + ...dfAfter, + }, + ], + }; + } + }); + }); + + test('Should not render when it is closed', async () => { + render( + {}} + getRowContext={getRowContext} + timeZone={timeZone} + sortOrder={LogsSortOrder.Descending} + /> + ); + + await waitFor(() => expect(screen.queryByText('Log context')).not.toBeInTheDocument()); + }); + + test('Should render when it is open', async () => { + render( + {}} + getRowContext={getRowContext} + timeZone={timeZone} + sortOrder={LogsSortOrder.Descending} + /> + ); + + await waitFor(() => expect(screen.queryByText('Log context')).toBeInTheDocument()); + }); + + test('Should call not getRowContext when closed', async () => { + render( + {}} + getRowContext={getRowContext} + timeZone={timeZone} + sortOrder={LogsSortOrder.Descending} + /> + ); + + await waitFor(() => expect(getRowContext).not.toHaveBeenCalled()); + }); + + test('Should call getRowContext on open', async () => { + render( + {}} + getRowContext={getRowContext} + timeZone={timeZone} + sortOrder={LogsSortOrder.Descending} + /> + ); + await waitFor(() => expect(getRowContext).toHaveBeenCalledTimes(2)); + }); + + test('should render 3 lines containing `foo123`', async () => { + render( + {}} + getRowContext={getRowContext} + timeZone={timeZone} + sortOrder={LogsSortOrder.Descending} + /> + ); + // 1 in before, 1 in current, 1 in after + await waitFor(() => expect(screen.getAllByText('foo123').length).toBe(3)); + }); + + test('should render 3 lines containing `foo123` with the same ms timestamp', async () => { + const dfBeforeNs = createDataFrame({ + fields: [ + { + name: 'time', + type: FieldType.time, + values: [1, 1], + }, + { + name: 'message', + type: FieldType.string, + values: ['foo123', 'foo123'], + }, + { + name: 'tsNs', + type: FieldType.string, + values: ['1', '2'], + }, + ], + }); + const dfNowNs = createDataFrame({ + fields: [ + { + name: 'time', + type: FieldType.time, + values: [1], + }, + { + name: 'message', + type: FieldType.string, + values: ['foo123'], + }, + { + name: 'tsNs', + type: FieldType.string, + values: ['2'], + }, + ], + }); + const dfAfterNs = createDataFrame({ + fields: [ + { + name: 'time', + type: FieldType.time, + values: [1, 1], + }, + { + name: 'message', + type: FieldType.string, + values: ['foo123', 'foo123'], + }, + { + name: 'tsNs', + type: FieldType.string, + values: ['2', '3'], + }, + ], + }); + + let uniqueRefIdCounter = 1; + const logs = dataFrameToLogsModel([dfNowNs]); + const row = logs.rows[0]; + const getRowContext = jest.fn().mockImplementation(async (_, options) => { + uniqueRefIdCounter += 1; + const refId = `refid_${uniqueRefIdCounter}`; + if (uniqueRefIdCounter === 2) { + return { + data: [ + { + refId, + ...dfBeforeNs, + }, + ], + }; + } else if (uniqueRefIdCounter === 3) { + return { + data: [ + { + refId, + ...dfAfterNs, + }, + ], + }; + } + return { data: [] }; + }); + + render( + {}} + getRowContext={getRowContext} + timeZone={timeZone} + sortOrder={LogsSortOrder.Descending} + /> + ); + + // 1 in before, 1 in current, 1 in after + await waitFor(() => { + expect(screen.getAllByText('foo123').length).toBe(3); + }); + }); + + test('Should highlight the same `foo123` searchwords', async () => { + const dfBeforeNs = createDataFrame({ + fields: [ + { + name: 'time', + type: FieldType.time, + values: [1, 1], + }, + { + name: 'message', + type: FieldType.string, + values: ['this contains foo123', 'this contains foo123'], + }, + { + name: 'tsNs', + type: FieldType.string, + values: ['1', '2'], + }, + ], + }); + const dfNowNs = createDataFrame({ + fields: [ + { + name: 'time', + type: FieldType.time, + values: [1], + }, + { + name: 'message', + type: FieldType.string, + values: ['this contains foo123'], + }, + { + name: 'tsNs', + type: FieldType.string, + values: ['2'], + }, + ], + }); + const dfAfterNs = createDataFrame({ + fields: [ + { + name: 'time', + type: FieldType.time, + values: [1, 1], + }, + { + name: 'message', + type: FieldType.string, + values: ['this contains foo123', 'this contains foo123'], + }, + { + name: 'tsNs', + type: FieldType.string, + values: ['2', '3'], + }, + ], + }); + + let uniqueRefIdCounter = 1; + const logs = dataFrameToLogsModel([dfNowNs]); + const row = logs.rows[0]; + row.searchWords = ['foo123']; + const getRowContext = jest.fn().mockImplementation(async (_, options) => { + uniqueRefIdCounter += 1; + const refId = `refid_${uniqueRefIdCounter}`; + if (uniqueRefIdCounter === 2) { + return { + data: [ + { + refId, + ...dfBeforeNs, + }, + ], + }; + } else if (uniqueRefIdCounter === 3) { + return { + data: [ + { + refId, + ...dfAfterNs, + }, + ], + }; + } + return { data: [] }; + }); + + render( + {}} + getRowContext={getRowContext} + timeZone={timeZone} + sortOrder={LogsSortOrder.Descending} + /> + ); + + // there need to be 3 lines with that message, all `foo123` should be highlighted + await waitFor(() => { + expect(screen.getAllByText('foo123')).toHaveLength(3); + expect(screen.getAllByText('this contains')).toHaveLength(3); + }); + }); + + test('Should show a split view button', async () => { + const getRowContextQuery = jest.fn().mockResolvedValue({ datasource: { uid: 'test-uid' } }); + + render( + {}} + getRowContext={getRowContext} + getRowContextQuery={getRowContextQuery} + timeZone={timeZone} + sortOrder={LogsSortOrder.Descending} + /> + ); + + await waitFor(() => + expect( + screen.getByRole('button', { + name: /open in split view/i, + }) + ).toBeInTheDocument() + ); + }); + + test('Should not show a split view button', async () => { + render( + {}} + getRowContext={getRowContext} + timeZone={timeZone} + sortOrder={LogsSortOrder.Descending} + /> + ); + + await waitFor(() => { + expect( + screen.queryByRole('button', { + name: /open in split view/i, + }) + ).not.toBeInTheDocument(); + }); + }); + + test('Should call getRowContextQuery', async () => { + const getRowContextQuery = jest.fn().mockResolvedValue({ datasource: { uid: 'test-uid' } }); + render( + {}} + getRowContext={getRowContext} + getRowContextQuery={getRowContextQuery} + timeZone={timeZone} + sortOrder={LogsSortOrder.Descending} + /> + ); + + await waitFor(() => expect(getRowContextQuery).toHaveBeenCalledTimes(1)); + }); + + test('Should close modal', async () => { + const getRowContextQuery = jest.fn().mockResolvedValue({ datasource: { uid: 'test-uid' } }); + const onClose = jest.fn(); + render( + + ); + + const splitViewButton = await screen.findByRole('button', { + name: /open in split view/i, + }); + + await userEvent.click(splitViewButton); + + await waitFor(() => expect(onClose).toHaveBeenCalled()); + }); + + test('Should create correct splitOpen', async () => { + const queryObj = { datasource: { uid: 'test-uid' } }; + const getRowContextQuery = jest.fn().mockResolvedValue(queryObj); + const onClose = jest.fn(); + + render( + + ); + + const splitViewButton = await screen.findByRole('button', { + name: /open in split view/i, + }); + + await userEvent.click(splitViewButton); + + await waitFor(() => + expect(splitOpen).toHaveBeenCalledWith( + expect.objectContaining({ + queries: [queryObj], + panelsState: { + logs: { + id: row.uid, + }, + }, + }) + ) + ); + }); + + test('Should dispatch splitOpen', async () => { + const getRowContextQuery = jest.fn().mockResolvedValue({ datasource: { uid: 'test-uid' } }); + const onClose = jest.fn(); + + render( + + ); + + const splitViewButton = await screen.findByRole('button', { + name: /open in split view/i, + }); + + await userEvent.click(splitViewButton); + + await waitFor(() => expect(dispatchMock).toHaveBeenCalledWith(splitOpenSym)); + }); +}); diff --git a/public/app/features/logs/components/panel/LogLineContext.tsx b/public/app/features/logs/components/panel/LogLineContext.tsx new file mode 100644 index 00000000000..db28cdc0fdb --- /dev/null +++ b/public/app/features/logs/components/panel/LogLineContext.tsx @@ -0,0 +1,447 @@ +import { css } from '@emotion/css'; +import { partition } from 'lodash'; +import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; + +import { + DataQueryResponse, + DataSourceWithLogsContextSupport, + GrafanaTheme2, + LogRowContextOptions, + LogRowContextQueryDirection, + LogsDedupStrategy, + LogsSortOrder, + dateTime, + TimeRange, + LoadingState, + CoreApp, + LogRowModel, + AbsoluteTimeRange, + EventBusSrv, + store, +} from '@grafana/data'; +import { Trans, t } from '@grafana/i18n'; +import { config, reportInteraction } from '@grafana/runtime'; +import { DataQuery, TimeZone } from '@grafana/schema'; +import { Button, Collapse, Modal, useTheme2 } from '@grafana/ui'; +import { splitOpen } from 'app/features/explore/state/main'; +import { useDispatch } from 'app/types/store'; + +import { dataFrameToLogsModel } from '../../logsModel'; +import { sortLogRows } from '../../utils'; +import { ScrollDirection } from '../InfiniteScroll'; +import { LoadingIndicator } from '../LoadingIndicator'; + +import { LogLineDetailsLog } from './LogLineDetailsLog'; +import { LogList } from './LogList'; +import { LogListModel } from './processing'; +import { ScrollToLogsEvent } from './virtualization'; + +interface LogLineContextProps { + log: LogRowModel | LogListModel; + logOptionsStorageKey?: string; + open: boolean; + timeZone: TimeZone; + onClose: () => void; + getRowContext: (row: LogRowModel, options: LogRowContextOptions) => Promise; + getRowContextQuery?: ( + row: LogRowModel, + options?: LogRowContextOptions, + cacheFilters?: boolean + ) => Promise; + sortOrder?: LogsSortOrder; + runContextQuery?: () => void; + getLogRowContextUi?: DataSourceWithLogsContextSupport['getLogRowContextUi']; + displayedFields?: string[]; + onClickShowField?: (key: string) => void; + onClickHideField?: (key: string) => void; +} + +const PAGE_SIZE = 100; + +export const LogLineContext = memo( + ({ + log, + logOptionsStorageKey, + open, + sortOrder = logOptionsStorageKey + ? (store.get(`${logOptionsStorageKey}.sortOrder`) ?? LogsSortOrder.Descending) + : LogsSortOrder.Descending, + timeZone, + getLogRowContextUi, + getRowContextQuery, + onClose, + getRowContext, + displayedFields = [], + onClickShowField, + onClickHideField, + }: LogLineContextProps) => { + const containerRef = useRef(null); + const [contextQuery, setContextQuery] = useState(null); + const [aboveLogs, setAboveLogs] = useState([]); + const [belowLogs, setBelowLogs] = useState([]); + const [initialized, setInitialized] = useState(false); + const allLogs = useMemo(() => [...aboveLogs, log, ...belowLogs], [log, belowLogs, aboveLogs]); + const [aboveState, setAboveState] = useState(LoadingState.NotStarted); + const [belowState, setBelowState] = useState(LoadingState.NotStarted); + const [showLog, setShowLog] = useState(false); + const eventBusRef = useRef(new EventBusSrv()); + + const dispatch = useDispatch(); + const theme = useTheme2(); + const styles = getStyles(theme); + + const timeRange = useMemo(() => { + const fromMs = + sortOrder === LogsSortOrder.Ascending ? allLogs[0].timeEpochMs : allLogs[allLogs.length - 1].timeEpochMs; + let toMs = + sortOrder === LogsSortOrder.Ascending ? allLogs[allLogs.length - 1].timeEpochMs : allLogs[0].timeEpochMs; + // In case we have a lot of logs and from and to have same millisecond + // we add 1 millisecond to toMs to make sure we have a range + if (fromMs === toMs) { + toMs += 1; + } + const from = dateTime(fromMs); + const to = dateTime(toMs); + + const range: TimeRange = { + from, + to, + raw: { + from, + to, + }, + }; + return range; + }, [allLogs, sortOrder]); + + const updateContextQuery = useCallback(async () => { + const contextQuery = getRowContextQuery ? await getRowContextQuery(log) : null; + setContextQuery(contextQuery); + }, [log, getRowContextQuery]); + + const updateResults = useCallback(async () => { + setAboveLogs([]); + setBelowLogs([]); + await updateContextQuery(); + setInitialized(false); + }, [updateContextQuery]); + + useEffect(() => { + if (open) { + updateContextQuery(); + } + }, [updateContextQuery, open]); + + const getContextLogs = useCallback( + async (place: 'above' | 'below', refLog: LogRowModel): Promise => { + const result = await getRowContext(normalizeLogRefId(refLog), { + limit: PAGE_SIZE, + direction: getLoadMoreDirection(place, sortOrder), + }); + + const newLogs = dataFrameToLogsModel(result.data).rows; + if (sortOrder === LogsSortOrder.Ascending) { + newLogs.reverse(); + } + return newLogs.filter((r) => !containsRow(allLogs, r)); + }, + [allLogs, getRowContext, sortOrder] + ); + + const loadMore = useCallback( + async (place: 'above' | 'below', refLog: LogRowModel) => { + const setState = place === 'above' ? setAboveState : setBelowState; + setState(LoadingState.Loading); + + try { + const newLogs = (await getContextLogs(place, refLog)).map((r) => + // apply the original row's searchWords to all the rows for highlighting + !r.searchWords || !r.searchWords?.length ? { ...r, searchWords: log.searchWords } : r + ); + const [older, newer] = partition(newLogs, (newRow) => newRow.timeEpochNs > log.timeEpochNs); + const newAbove = sortOrder === LogsSortOrder.Ascending ? newer : older; + const newBelow = sortOrder === LogsSortOrder.Ascending ? older : newer; + + setAboveLogs((aboveLogs: LogRowModel[]) => { + return newAbove.length > 0 ? sortLogRows([...newAbove, ...aboveLogs], sortOrder) : aboveLogs; + }); + setBelowLogs((belowLogs: LogRowModel[]) => { + return newBelow.length > 0 ? sortLogRows([...belowLogs, ...newBelow], sortOrder) : belowLogs; + }); + + setState(LoadingState.NotStarted); + if (!newAbove.length && place === 'above') { + setAboveState(LoadingState.Done); + } + if (!newBelow.length && place === 'below') { + setBelowState(LoadingState.Done); + } + } catch { + setState(LoadingState.Error); + } + }, + [getContextLogs, log, sortOrder] + ); + + useEffect(() => { + if (!open) { + return; + } + if (!initialized) { + Promise.all([loadMore('above', log), loadMore('below', log)]).then(() => {}); + setInitialized(true); + } + }, [initialized, loadMore, log, open]); + + const handleLoadMore = useCallback( + (_: AbsoluteTimeRange, direction: ScrollDirection) => { + if (direction === ScrollDirection.Bottom) { + loadMore('below', allLogs[allLogs.length - 1]); + } else { + loadMore('above', allLogs[0]); + } + }, + [allLogs, loadMore] + ); + + const onScrollCenterClick = useCallback(() => { + eventBusRef.current.publish( + new ScrollToLogsEvent({ + scrollTo: log.uid, + }) + ); + }, [log.uid]); + + const wrapLogMessage = logOptionsStorageKey ? store.getBool(`${logOptionsStorageKey}.wrapLogMessage`, true) : true; + const syntaxHighlighting = logOptionsStorageKey + ? store.getBool(`${logOptionsStorageKey}.syntaxHighlighting`, true) + : true; + // @todo: Remove when the LogRows are deprecated + const logListModel = useMemo( + () => + log instanceof LogListModel + ? log + : new LogListModel(log, { + escape: false, + timeZone, + wrapLogMessage, + }), + [log, timeZone, wrapLogMessage] + ); + + return ( + + {config.featureToggles.logsContextDatasourceUi && getLogRowContextUi && ( +
{getLogRowContextUi(log, updateResults)}
+ )} + setShowLog(!showLog)} + className={styles.referenceLogLine} + label={t('logs.log-line-context.title-log-line', 'Referenced log line')} + > + + +
+ {aboveState === LoadingState.Loading && ( + + )} + {aboveState === LoadingState.Done && ( + No more logs available. + )} +
+
+
+ {containerRef.current && ( + + )} +
+
+
+ {belowState === LoadingState.Loading && ( + + )} + {belowState === LoadingState.Done && ( + No more logs available. + )} +
+ + + + {contextQuery?.datasource?.uid && ( + + )} + +
+ ); + } +); +LogLineContext.displayName = 'LogLineContext'; + +const getStyles = (theme: GrafanaTheme2) => { + return { + modal: css({ + width: '85vw', + height: '80%', + [theme.breakpoints.down('md')]: { + width: '100%', + minHeight: '100%', + }, + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + }), + datasourceUi: css({ + display: 'flex', + alignItems: 'center', + }), + loadingIndicator: css({ + height: theme.spacing(3), + minHeight: theme.spacing(3), + textAlign: 'center', + }), + referenceLogLine: css({ + flex: 0, + }), + wrapper: css({ + border: `1px solid ${theme.colors.border.weak}`, + padding: theme.spacing(0, 1, 1, 0), + flex: 1, + height: '100%', + }), + logsContainer: css({ + height: '100%', + overflow: 'hidden', + }), + flexColumn: css({ + display: 'flex', + flexDirection: 'column', + padding: theme.spacing(0, 3, 3, 3), + height: '100%', + }), + link: css({ + color: theme.colors.text.secondary, + fontSize: theme.typography.bodySmall.fontSize, + ':hover': { + color: theme.colors.text.link, + }, + }), + logPreview: css({ + overflow: 'hidden', + textAlign: 'left', + textOverflow: 'ellipsis', + width: '75vw', + whiteSpace: 'nowrap', + }), + }; +}; + +const getLoadMoreDirection = (place: 'above' | 'below', sortOrder: LogsSortOrder): LogRowContextQueryDirection => { + if (place === 'above' && sortOrder === LogsSortOrder.Descending) { + return LogRowContextQueryDirection.Forward; + } + if (place === 'below' && sortOrder === LogsSortOrder.Ascending) { + return LogRowContextQueryDirection.Forward; + } + + return LogRowContextQueryDirection.Backward; +}; + +const normalizeLogRefId = (log: LogRowModel): LogRowModel => { + // the datasoure plugins often create the context-query based on the row's dataframe's refId, + // by appending something to it. for example: + // - let's say the row's dataframe's refId is "query" + // - the datasource plugin will take "query" and append "-context" to it, so it becomes "query-context". + // - later we want to load even more lines, so we make a context query + // - the datasource plugin does the same transform again, but now the source is "query-context", + // so the new refId becomes "query-context-context" + // - next time it becomes "query-context-context-context", and so on. + // we do not want refIds to grow unbounded. + // to avoid this, we set the refId to a value that does not grow. + // on the other hand, the refId is also used in generating the row's UID, so it is useful + // when the refId is not always the exact same string, otherwise UID duplication can occur, + // which may cause problems. + // so we go with an approach where the refId always changes, but does not grow. + return { + ...log, + dataFrame: { + ...log.dataFrame, + refId: `context_${log.uid ?? log.dataFrame.refId ?? log.timeEpochMs}`, + }, + }; +}; + +const containsRow = (rows: LogRowModel[], row: LogRowModel) => { + return rows.some((r) => r.entry === row.entry && r.timeEpochNs === row.timeEpochNs); +}; diff --git a/public/app/features/logs/components/panel/LogLineDetailsComponent.tsx b/public/app/features/logs/components/panel/LogLineDetailsComponent.tsx index 96429ce4327..fd8490f74cb 100644 --- a/public/app/features/logs/components/panel/LogLineDetailsComponent.tsx +++ b/public/app/features/logs/components/panel/LogLineDetailsComponent.tsx @@ -25,7 +25,8 @@ interface LogLineDetailsComponentProps { } export const LogLineDetailsComponent = memo(({ focusLogLine, log, logs }: LogLineDetailsComponentProps) => { - const { displayedFields, noInteractions, logOptionsStorageKey, setDisplayedFields } = useLogListContext(); + const { displayedFields, noInteractions, logOptionsStorageKey, setDisplayedFields, syntaxHighlighting } = + useLogListContext(); const [search, setSearch] = useState(''); const inputRef = useRef(''); const styles = useStyles2(getStyles); @@ -111,7 +112,7 @@ export const LogLineDetailsComponent = memo(({ focusLogLine, log, logs }: LogLin isOpen={logLineOpen} onToggle={(isOpen: boolean) => handleToggle('logLineOpen', isOpen)} > - + {displayedFields.length > 0 && setDisplayedFields && ( { - const { syntaxHighlighting } = useLogListContext(); +export const LogLineDetailsLog = memo(({ log: originalLog, syntaxHighlighting }: Props) => { const logStyles = useStyles2(getStyles); const log = useMemo(() => { const log = originalLog.clone(); diff --git a/public/app/features/logs/components/panel/LogList.tsx b/public/app/features/logs/components/panel/LogList.tsx index 6350723ff89..df0c8b58fd5 100644 --- a/public/app/features/logs/components/panel/LogList.tsx +++ b/public/app/features/logs/components/panel/LogList.tsx @@ -5,7 +5,6 @@ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, Mou import { Align, VariableSizeList } from 'react-window'; import { - AbsoluteTimeRange, CoreApp, DataFrame, EventBus, @@ -24,7 +23,7 @@ import { ConfirmModal, Icon, PopoverContent, useStyles2, useTheme2 } from '@graf import { PopoverMenu } from 'app/features/explore/Logs/PopoverMenu'; import { GetFieldLinksFn } from 'app/plugins/panel/logs/types'; -import { InfiniteScroll } from './InfiniteScroll'; +import { InfiniteScrollMode, InfiniteScroll, LoadMoreLogsType } from './InfiniteScroll'; import { getGridTemplateColumns } from './LogLine'; import { LogLineDetails, LogLineDetailsMode } from './LogLineDetails'; import { GetRowContextQueryFn, LogLineMenuCustomItem } from './LogLineMenu'; @@ -50,10 +49,11 @@ export interface Props { getFieldLinks?: GetFieldLinksFn; getRowContextQuery?: GetRowContextQueryFn; grammar?: Grammar; + infiniteScrollMode?: InfiniteScrollMode; initialScrollPosition?: 'top' | 'bottom'; isLabelFilterActive?: (key: string, value: string, refId?: string) => Promise; loading?: boolean; - loadMore?: (range: AbsoluteTimeRange) => void; + loadMore?: LoadMoreLogsType; logLineMenuCustomItems?: LogLineMenuCustomItem[]; logOptionsStorageKey?: string; logs: LogRowModel[]; @@ -117,6 +117,7 @@ export const LogList = ({ getFieldLinks, getRowContextQuery, grammar, + infiniteScrollMode, initialScrollPosition = 'top', isLabelFilterActive, loading, @@ -197,6 +198,7 @@ export const LogList = ({ getFieldLinks={getFieldLinks} grammar={grammar} initialScrollPosition={initialScrollPosition} + infiniteScrollMode={infiniteScrollMode} loading={loading} loadMore={loadMore} logs={logs} @@ -215,6 +217,7 @@ const LogListComponent = ({ getFieldLinks, grammar, initialScrollPosition = 'top', + infiniteScrollMode = 'interval', loading, loadMore, logs, @@ -271,6 +274,20 @@ const LogListComponent = ({ useKeyBindings(); const { filterLogs, matchingUids, searchVisible } = useLogListSearchContext(); + const levelFilteredLogs = useMemo( + () => + filterLevels.length === 0 ? processedLogs : processedLogs.filter((log) => filterLevels.includes(log.logLevel)), + [filterLevels, processedLogs] + ); + + const filteredLogs = useMemo( + () => + matchingUids && filterLogs + ? levelFilteredLogs.filter((log) => matchingUids.includes(log.uid)) + : levelFilteredLogs, + [filterLogs, levelFilteredLogs, matchingUids] + ); + const debouncedResetAfterIndex = useMemo(() => { return debounce((index: number) => { listRef.current?.resetAfterIndex(index); @@ -286,10 +303,10 @@ const LogListComponent = ({ useEffect(() => { const subscription = eventBus.subscribe(ScrollToLogsEvent, (e: ScrollToLogsEvent) => - handleScrollToEvent(e, logs.length, listRef.current) + handleScrollToEvent(e, filteredLogs, listRef.current) ); return () => subscription.unsubscribe(); - }, [eventBus, logs.length]); + }, [eventBus, filteredLogs]); useEffect(() => { if (loading) { @@ -379,20 +396,6 @@ const LogListComponent = ({ debouncedResetAfterIndex(0); }, [debouncedResetAfterIndex]); - const levelFilteredLogs = useMemo( - () => - filterLevels.length === 0 ? processedLogs : processedLogs.filter((log) => filterLevels.includes(log.logLevel)), - [filterLevels, processedLogs] - ); - - const filteredLogs = useMemo( - () => - matchingUids && filterLogs - ? levelFilteredLogs.filter((log) => matchingUids.includes(log.uid)) - : levelFilteredLogs, - [filterLogs, levelFilteredLogs, matchingUids] - ); - const focusLogLine = useCallback( (log: LogListModel) => { const index = filteredLogs.indexOf(log); @@ -405,6 +408,15 @@ const LogListComponent = ({ return (
+ {showControls && } + {detailsMode === 'sidebar' && showDetails.length > 0 && ( + + )}
{popoverState.selection && popoverState.selectedRow && (
- {detailsMode === 'sidebar' && showDetails.length > 0 && ( - - )} - {showControls && }
); }; @@ -515,6 +519,7 @@ function getStyles( }), logListContainer: css({ display: 'flex', + flexDirection: 'row-reverse', // Minimum width to prevent rendering issues and a sausage-like logs panel. minWidth: theme.spacing(35), }), @@ -534,10 +539,16 @@ function getStyles( }; } -function handleScrollToEvent(event: ScrollToLogsEvent, logsCount: number, list: VariableSizeList | null) { +function handleScrollToEvent(event: ScrollToLogsEvent, logs: LogListModel[], list: VariableSizeList | null) { if (event.payload.scrollTo === 'top') { list?.scrollTo(0); + } else if (event.payload.scrollTo === 'bottom') { + list?.scrollToItem(logs.length - 1); } else { - list?.scrollToItem(logsCount - 1); + // uid + const index = logs.findIndex((log) => log.uid === event.payload.scrollTo); + if (index >= 0) { + list?.scrollToItem(index, 'center'); + } } } diff --git a/public/app/features/logs/components/panel/virtualization.ts b/public/app/features/logs/components/panel/virtualization.ts index bf84f5fe3ff..6207085d1a5 100644 --- a/public/app/features/logs/components/panel/virtualization.ts +++ b/public/app/features/logs/components/panel/virtualization.ts @@ -370,7 +370,7 @@ export function getScrollbarWidth() { } export interface ScrollToLogsEventPayload { - scrollTo: 'top' | 'bottom'; + scrollTo: 'top' | 'bottom' | string; } export class ScrollToLogsEvent extends BusEventWithPayload { diff --git a/public/app/plugins/panel/logs/LogsPanel.tsx b/public/app/plugins/panel/logs/LogsPanel.tsx index ca44d725502..73ee2c3604d 100644 --- a/public/app/plugins/panel/logs/LogsPanel.tsx +++ b/public/app/plugins/panel/logs/LogsPanel.tsx @@ -37,6 +37,7 @@ import { getFieldLinksForExplore } from 'app/features/explore/utils/links'; import { ControlledLogRows } from 'app/features/logs/components/ControlledLogRows'; import { InfiniteScroll } from 'app/features/logs/components/InfiniteScroll'; import { LogRowContextModal } from 'app/features/logs/components/log-context/LogRowContextModal'; +import { LogLineContext } from 'app/features/logs/components/panel/LogLineContext'; import { LogList } from 'app/features/logs/components/panel/LogList'; import { PanelDataErrorView } from 'app/features/panel/components/PanelDataErrorView'; import { combineResponses } from 'app/plugins/datasource/loki/mergeResponses'; @@ -531,7 +532,7 @@ export const LogsPanel = ({ return ( <> - {contextRow && ( + {(!config.featureToggles.newLogsPanel || !config.featureToggles.newLogContext) && contextRow && ( )} + {config.featureToggles.newLogsPanel && config.featureToggles.newLogContext && getLogRowContext && contextRow && ( + getLogRowContext(row, contextRow, options)} + getLogRowContextUi={getLogRowContextUi} + logOptionsStorageKey={controlsStorageKey} + timeZone={timeZone} + displayedFields={displayedFields} + onClickShowField={showField} + onClickHideField={hideField} + /> + )} {config.featureToggles.newLogsPanel && (
({ display: 'flex', flex: 1, flexDirection: 'column', + overflow: 'hidden', }), controlledLogsContainer: css({ height: '100%', diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index c0061d4b664..339cb81d0d1 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -9362,6 +9362,15 @@ "show-more": "show more", "tooltip-error": "Error: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "Center matched line", + "newer-logs": "newer", + "no-more-logs-available": "No more logs available.", + "older-logs": "older", + "open-in-split-view": "Open in split view", + "title-log-context": "Log context", + "title-log-line": "Referenced log line" + }, "log-line-details": { "clear-search": "Clear", "close": "Close log details", From 63093dfb261bca650890379c86b0510cac589332 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 12:34:32 +0100 Subject: [PATCH 15/89] Update dependency @types/eslint-scope to v8 (#109034) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index cc339866f02..eb94c9eb369 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,7 @@ "@types/d3-scale-chromatic": "3.1.0", "@types/debounce-promise": "3.1.9", "@types/eslint": "9.6.1", - "@types/eslint-scope": "^3.7.7", + "@types/eslint-scope": "^8.0.0", "@types/file-saver": "2.0.7", "@types/glob": "^8.0.0", "@types/google.analytics": "^0.0.46", diff --git a/yarn.lock b/yarn.lock index a9cb48e452e..e3c9d0fdd0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9357,6 +9357,16 @@ __metadata: languageName: node linkType: hard +"@types/eslint-scope@npm:^8.0.0": + version: 8.3.1 + resolution: "@types/eslint-scope@npm:8.3.1" + dependencies: + "@types/eslint": "npm:*" + "@types/estree": "npm:*" + checksum: 10/54404a6473928b513b9ab3de9de34a52ed3b0524d010b0b068023539bd834617073b74e3052fc51d3c9bff2093d6b85c0af61de55e47c83d6685d4fa0d363d2b + languageName: node + linkType: hard + "@types/eslint@npm:*, @types/eslint@npm:9.6.1": version: 9.6.1 resolution: "@types/eslint@npm:9.6.1" @@ -18309,7 +18319,7 @@ __metadata: "@types/d3-scale-chromatic": "npm:3.1.0" "@types/debounce-promise": "npm:3.1.9" "@types/eslint": "npm:9.6.1" - "@types/eslint-scope": "npm:^3.7.7" + "@types/eslint-scope": "npm:^8.0.0" "@types/file-saver": "npm:2.0.7" "@types/glob": "npm:^8.0.0" "@types/google.analytics": "npm:^0.0.46" From d96cd46272ff9212f00d130876bcac01efc41d2f Mon Sep 17 00:00:00 2001 From: Levente Balogh Date: Fri, 1 Aug 2025 13:42:07 +0200 Subject: [PATCH 16/89] Plugin Extensions: Support core plugins (#108685) * feat(extensions): allow core plugins to use core grafana extension points * fix: don't validate the plugin.json for core plugins --- .../extensions/usePluginComponents.test.tsx | 77 +++++++++++++++++- .../extensions/usePluginComponents.tsx | 13 +++- .../plugins/extensions/usePluginFunctions.tsx | 13 +++- .../extensions/usePluginLinks.test.tsx | 78 ++++++++++++++++++- .../plugins/extensions/usePluginLinks.tsx | 13 +++- .../plugins/extensions/validators.test.tsx | 14 ++++ .../features/plugins/extensions/validators.ts | 4 +- 7 files changed, 203 insertions(+), 9 deletions(-) diff --git a/public/app/features/plugins/extensions/usePluginComponents.test.tsx b/public/app/features/plugins/extensions/usePluginComponents.test.tsx index f40955c3f54..255a8a6161c 100644 --- a/public/app/features/plugins/extensions/usePluginComponents.test.tsx +++ b/public/app/features/plugins/extensions/usePluginComponents.test.tsx @@ -1,7 +1,13 @@ import { act, render, renderHook, screen } from '@testing-library/react'; import React from 'react'; -import { PluginContextProvider, PluginExtensionPoints, PluginMeta, PluginType } from '@grafana/data'; +import { + PluginContextProvider, + PluginExtensionPoints, + PluginLoadingStrategy, + PluginMeta, + PluginType, +} from '@grafana/data'; import { config } from '@grafana/runtime'; import { ExtensionRegistriesProvider } from './ExtensionRegistriesContext'; @@ -105,6 +111,32 @@ describe('usePluginComponents()', () => { }, }; + config.apps[pluginId] = { + id: pluginId, + path: '', + version: '', + preload: false, + angular: { + detected: false, + hideDeprecation: false, + }, + loadingStrategy: PluginLoadingStrategy.fetch, + dependencies: { + grafanaVersion: '8.0.0', + plugins: [], + extensions: { + exposedComponents: [], + }, + }, + extensions: { + addedLinks: [], + addedComponents: [], + addedFunctions: [], + exposedComponents: [], + extensionPoints: [], + }, + }; + wrapper = ({ children }: { children: React.ReactNode }) => ( {children} @@ -459,6 +491,49 @@ describe('usePluginComponents()', () => { expect(log.error).not.toHaveBeenCalled(); }); + // It can happen that core Grafana plugins (e.g. traces) reuse core components which implement extension points. + it('should not validate the extension point meta-info for core plugins', () => { + jest.mocked(isGrafanaDevMode).mockReturnValue(true); + + const componentConfig = { + targets: extensionPointId, + title: '1', + description: '1', + component: () =>
Component
, + }; + + // The `AddedComponentsRegistry` is validating if the link is registered in the plugin metadata (config.apps). + config.apps[pluginId].extensions.addedComponents = [componentConfig]; + + wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + + ); + + registries.addedComponentsRegistry.register({ + pluginId, + configs: [componentConfig], + }); + + // Trying to render an extension point that is not defined in the plugin meta + // (No restrictions due to being a core plugin) + let { result } = renderHook(() => usePluginComponents({ extensionPointId }), { wrapper }); + expect(result.current.components.length).toBe(1); + expect(log.error).not.toHaveBeenCalled(); + }); + it('should not validate the extension point id in production mode', () => { // Empty list of extension points in the plugin meta (from plugin.json) wrapper = ({ children }: { children: React.ReactNode }) => ( diff --git a/public/app/features/plugins/extensions/usePluginComponents.tsx b/public/app/features/plugins/extensions/usePluginComponents.tsx index 6f37f3bdbba..d07a2e5ac07 100644 --- a/public/app/features/plugins/extensions/usePluginComponents.tsx +++ b/public/app/features/plugins/extensions/usePluginComponents.tsx @@ -29,6 +29,7 @@ export function usePluginComponents({ return useMemo(() => { const isInsidePlugin = Boolean(pluginContext); + const isCoreGrafanaPlugin = pluginContext?.meta.module.startsWith('core:') ?? false; const components: Array> = []; const extensionsByPlugin: Record = {}; const pluginId = pluginContext?.meta.id ?? ''; @@ -38,7 +39,10 @@ export function usePluginComponents({ }); // Don't show extensions if the extension-point id is invalid in DEV mode - if (isGrafanaDevMode() && !isExtensionPointIdValid({ extensionPointId, pluginId, isInsidePlugin, log: pointLog })) { + if ( + isGrafanaDevMode() && + !isExtensionPointIdValid({ extensionPointId, pluginId, isInsidePlugin, isCoreGrafanaPlugin, log: pointLog }) + ) { return { isLoading: false, components: [], @@ -46,7 +50,12 @@ export function usePluginComponents({ } // Don't show extensions if the extension-point misses meta info (plugin.json) in DEV mode - if (isGrafanaDevMode() && pluginContext && isExtensionPointMetaInfoMissing(extensionPointId, pluginContext)) { + if ( + isGrafanaDevMode() && + !isCoreGrafanaPlugin && + pluginContext && + isExtensionPointMetaInfoMissing(extensionPointId, pluginContext) + ) { pointLog.error(errors.EXTENSION_POINT_META_INFO_MISSING); return { isLoading: false, diff --git a/public/app/features/plugins/extensions/usePluginFunctions.tsx b/public/app/features/plugins/extensions/usePluginFunctions.tsx index 18a8abd7aef..8f8c989e316 100644 --- a/public/app/features/plugins/extensions/usePluginFunctions.tsx +++ b/public/app/features/plugins/extensions/usePluginFunctions.tsx @@ -24,6 +24,7 @@ export function usePluginFunctions({ return useMemo(() => { const isInsidePlugin = Boolean(pluginContext); + const isCoreGrafanaPlugin = pluginContext?.meta.module.startsWith('core:') ?? false; const results: Array> = []; const extensionsByPlugin: Record = {}; const pluginId = pluginContext?.meta.id ?? ''; @@ -32,14 +33,22 @@ export function usePluginFunctions({ extensionPointId, }); - if (isGrafanaDevMode() && !isExtensionPointIdValid({ extensionPointId, pluginId, isInsidePlugin, log: pointLog })) { + if ( + isGrafanaDevMode() && + !isExtensionPointIdValid({ extensionPointId, pluginId, isInsidePlugin, isCoreGrafanaPlugin, log: pointLog }) + ) { return { isLoading: false, functions: [], }; } - if (isGrafanaDevMode() && pluginContext && isExtensionPointMetaInfoMissing(extensionPointId, pluginContext)) { + if ( + isGrafanaDevMode() && + !isCoreGrafanaPlugin && + pluginContext && + isExtensionPointMetaInfoMissing(extensionPointId, pluginContext) + ) { pointLog.error(errors.EXTENSION_POINT_META_INFO_MISSING); return { isLoading: false, diff --git a/public/app/features/plugins/extensions/usePluginLinks.test.tsx b/public/app/features/plugins/extensions/usePluginLinks.test.tsx index b5d984b165c..697c9dfd91f 100644 --- a/public/app/features/plugins/extensions/usePluginLinks.test.tsx +++ b/public/app/features/plugins/extensions/usePluginLinks.test.tsx @@ -1,6 +1,13 @@ import { act, renderHook } from '@testing-library/react'; -import { PluginContextProvider, PluginExtensionPoints, PluginMeta, PluginType } from '@grafana/data'; +import { + PluginContextProvider, + PluginExtensionPoints, + PluginLoadingStrategy, + PluginMeta, + PluginType, +} from '@grafana/data'; +import { config } from '@grafana/runtime'; import { ExtensionRegistriesProvider } from './ExtensionRegistriesContext'; import { log } from './logs/log'; @@ -98,6 +105,32 @@ describe('usePluginLinks()', () => { }, }; + config.apps[pluginId] = { + id: pluginId, + path: '', + version: '', + preload: false, + angular: { + detected: false, + hideDeprecation: false, + }, + loadingStrategy: PluginLoadingStrategy.fetch, + dependencies: { + grafanaVersion: '8.0.0', + plugins: [], + extensions: { + exposedComponents: [], + }, + }, + extensions: { + addedLinks: [], + addedComponents: [], + addedFunctions: [], + exposedComponents: [], + extensionPoints: [], + }, + }; + wrapper = ({ children }: { children: React.ReactNode }) => ( {children} @@ -219,6 +252,49 @@ describe('usePluginLinks()', () => { expect(log.warning).not.toHaveBeenCalled(); }); + // It can happen that core Grafana plugins (e.g. traces) reuse core components which implement extension points. + it('should not validate the extension point meta-info for core plugins', () => { + jest.mocked(isGrafanaDevMode).mockReturnValue(true); + + const linkConfig = { + targets: extensionPointId, + title: '1', + description: '1', + path: `/a/${pluginId}/2`, + }; + + // The `AddedLinksRegistry` is validating if the link is registered in the plugin metadata (config.apps). + config.apps[pluginId].extensions.addedLinks = [linkConfig]; + + wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + + ); + + registries.addedLinksRegistry.register({ + pluginId, + configs: [linkConfig], + }); + + // Trying to render an extension point that is not defined in the plugin meta + // (No restrictions due to being a core plugin) + let { result } = renderHook(() => usePluginLinks({ extensionPointId }), { wrapper }); + expect(result.current.links.length).toBe(1); + expect(log.warning).not.toHaveBeenCalled(); + }); + it('should not validate the extension point id in production mode', () => { // Empty list of extension points in the plugin meta (from plugin.json) wrapper = ({ children }: { children: React.ReactNode }) => ( diff --git a/public/app/features/plugins/extensions/usePluginLinks.tsx b/public/app/features/plugins/extensions/usePluginLinks.tsx index adec8114582..5d2b193a77c 100644 --- a/public/app/features/plugins/extensions/usePluginLinks.tsx +++ b/public/app/features/plugins/extensions/usePluginLinks.tsx @@ -34,19 +34,28 @@ export function usePluginLinks({ return useMemo(() => { const isInsidePlugin = Boolean(pluginContext); const pluginId = pluginContext?.meta.id ?? ''; + const isCoreGrafanaPlugin = pluginContext?.meta.module.startsWith('core:') ?? false; const pointLog = log.child({ pluginId, extensionPointId, }); - if (isGrafanaDevMode() && !isExtensionPointIdValid({ extensionPointId, pluginId, isInsidePlugin, log: pointLog })) { + if ( + isGrafanaDevMode() && + !isExtensionPointIdValid({ extensionPointId, pluginId, isInsidePlugin, isCoreGrafanaPlugin, log: pointLog }) + ) { return { isLoading: false, links: [], }; } - if (isGrafanaDevMode() && pluginContext && isExtensionPointMetaInfoMissing(extensionPointId, pluginContext)) { + if ( + isGrafanaDevMode() && + !isCoreGrafanaPlugin && + pluginContext && + isExtensionPointMetaInfoMissing(extensionPointId, pluginContext) + ) { pointLog.error(errors.EXTENSION_POINT_META_INFO_MISSING); return { isLoading: false, diff --git a/public/app/features/plugins/extensions/validators.test.tsx b/public/app/features/plugins/extensions/validators.test.tsx index 1b7e71eba7b..2f1713d3f34 100644 --- a/public/app/features/plugins/extensions/validators.test.tsx +++ b/public/app/features/plugins/extensions/validators.test.tsx @@ -217,6 +217,7 @@ describe('Plugin Extension Validators', () => { extensionPointId, pluginId, isInsidePlugin: pluginId !== 'grafana' && pluginId !== '', + isCoreGrafanaPlugin: false, log: createLogMock(), }) ).toBe(true); @@ -244,10 +245,23 @@ describe('Plugin Extension Validators', () => { extensionPointId, pluginId, isInsidePlugin: pluginId !== 'grafana' && pluginId !== '', + isCoreGrafanaPlugin: false, log: createLogMock(), }) ).toBe(false); }); + + it('should return FALSE true if the extension point id is set by a core plugin', () => { + expect( + isExtensionPointIdValid({ + extensionPointId: 'traces', + pluginId: 'traces', + isInsidePlugin: true, + isCoreGrafanaPlugin: true, + log: createLogMock(), + }) + ).toBe(true); + }); }); describe('isAddedLinkMetaInfoMissing()', () => { diff --git a/public/app/features/plugins/extensions/validators.ts b/public/app/features/plugins/extensions/validators.ts index 081ac98fbab..df808a34576 100644 --- a/public/app/features/plugins/extensions/validators.ts +++ b/public/app/features/plugins/extensions/validators.ts @@ -69,17 +69,19 @@ export function isExtensionPointIdValid({ extensionPointId, pluginId, isInsidePlugin, + isCoreGrafanaPlugin, log, }: { extensionPointId: string; pluginId: string; isInsidePlugin: boolean; + isCoreGrafanaPlugin: boolean; log: ExtensionsLog; }) { const startsWithPluginId = extensionPointId.startsWith(`${pluginId}/`) || extensionPointId.startsWith(`plugins/${pluginId}/`); - if (isInsidePlugin && !startsWithPluginId) { + if (isInsidePlugin && !isCoreGrafanaPlugin && !startsWithPluginId) { log.error(errors.INVALID_EXTENSION_POINT_ID_PLUGIN(pluginId, extensionPointId)); return false; } From 7374df7945dbc5661f82ac77e1ec85159c5f615a Mon Sep 17 00:00:00 2001 From: Matheus Macabu Date: Fri, 1 Aug 2025 13:57:51 +0200 Subject: [PATCH 17/89] Secrets: Add inline secure value create method (#108987) --- .../secret/service/inline_secure_value.go | 64 ++++++++- .../service/inline_secure_value_test.go | 127 ++++++++++++++++++ .../apis/secret/testutils/testutils.go | 32 ++++- .../secret/metadata/secure_value_test.go | 4 +- 4 files changed, 223 insertions(+), 4 deletions(-) diff --git a/pkg/registry/apis/secret/service/inline_secure_value.go b/pkg/registry/apis/secret/service/inline_secure_value.go index 062f601ba6e..c2a6b97e451 100644 --- a/pkg/registry/apis/secret/service/inline_secure_value.go +++ b/pkg/registry/apis/secret/service/inline_secure_value.go @@ -5,9 +5,11 @@ import ( "errors" "fmt" + "github.com/grafana/authlib/authn" authlib "github.com/grafana/authlib/types" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1" @@ -15,6 +17,7 @@ import ( "github.com/grafana/grafana/pkg/apimachinery/utils" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" + "github.com/grafana/grafana/pkg/util" ) type inlineSecureValueService struct { @@ -158,7 +161,66 @@ func (s *inlineSecureValueService) canIdentityReadSecureValue(ctx context.Contex } func (s *inlineSecureValueService) CreateInline(ctx context.Context, owner common.ObjectReference, value common.RawSecureValue) (string, error) { - return "", fmt.Errorf("not implemented yet") + ctx, span := s.tracer.Start(ctx, "InlineSecureValueService.CreateInline", trace.WithAttributes( + attribute.String("owner.namespace", owner.Namespace), + attribute.String("owner.apiGroup", owner.APIGroup), + attribute.String("owner.apiVersion", owner.APIVersion), + attribute.String("owner.kind", owner.Kind), + attribute.String("owner.name", owner.Name), + )) + defer span.End() + + authInfo, ok := authlib.AuthInfoFrom(ctx) + if !ok { + return "", fmt.Errorf("missing auth info in context") + } + + if authInfo.GetIdentityType() != authlib.TypeUser && authInfo.GetIdentityType() != authlib.TypeServiceAccount { + return "", fmt.Errorf("identity type %s not allowed, expected either %s or %s", authInfo.GetIdentityType(), authlib.TypeUser, authlib.TypeServiceAccount) + } + + serviceIdentityList, ok := authInfo.GetExtra()[authn.ServiceIdentityKey] + if !ok || len(serviceIdentityList) != 1 { + return "", fmt.Errorf("expected exactly one service identity, found %d", len(serviceIdentityList)) + } + serviceIdentity := serviceIdentityList[0] + + if owner.Namespace == "" || !authlib.NamespaceMatches(authInfo.GetNamespace(), owner.Namespace) { + return "", fmt.Errorf("owner namespace %s does not match auth info namespace %s", owner.Namespace, authInfo.GetNamespace()) + } + + if owner.APIGroup == "" || owner.APIVersion == "" || owner.Kind == "" || owner.Name == "" { + return "", fmt.Errorf("owner reference must have a valid API group, API version, kind and name") + } + + if value.IsZero() { + return "", fmt.Errorf("trying to create an inline secure value with empty value") + } + + // TODO(2025-07-31): when we migrate to using the common type, we don't need this conversion. + secret := secretv1beta1.ExposedSecureValue(value) + + spec := &secretv1beta1.SecureValue{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sv-" + util.GenerateShortUID(), + Namespace: owner.Namespace, + OwnerReferences: []metav1.OwnerReference{owner.ToOwnerReference()}, + }, + Spec: secretv1beta1.SecureValueSpec{ + Description: fmt.Sprintf("Inline secure value for %s/%s in %s/%s", owner.Kind, owner.Name, owner.APIVersion, owner.APIVersion), + Value: &secret, + Decrypters: []string{ + serviceIdentity, + }, + }, + } + + createdSv, err := s.secureValueService.Create(ctx, spec, authInfo.GetUID()) + if err != nil { + return "", fmt.Errorf("error creating secure value %s for owner %v: %w", spec.Name, owner, err) + } + + return createdSv.GetName(), nil } func (s *inlineSecureValueService) DeleteWhenOwnedByResource(ctx context.Context, owner common.ObjectReference, name string) error { diff --git a/pkg/registry/apis/secret/service/inline_secure_value_test.go b/pkg/registry/apis/secret/service/inline_secure_value_test.go index a358ff13cbd..fe486df5a9b 100644 --- a/pkg/registry/apis/secret/service/inline_secure_value_test.go +++ b/pkg/registry/apis/secret/service/inline_secure_value_test.go @@ -292,3 +292,130 @@ func TestIntegration_InlineSecureValue_CanReference(t *testing.T) { require.Error(t, err) }) } + +func TestIntegration_InlineSecureValue_CreateInline(t *testing.T) { + t.Parallel() + + tracer := noop.NewTracerProvider().Tracer("test") + + defaultNs := "org-1234" + owner := common.ObjectReference{ + APIGroup: "prometheus.datasource.grafana.app", + APIVersion: "v1alpha1", + Kind: "DataSourceConfig", + Name: "test-datasource", + Namespace: defaultNs, + } + + t.Run("happy path creates an inline secure value", func(t *testing.T) { + t.Parallel() + + tu := testutils.Setup(t) + + secret := common.NewSecretValue("test-value") + + serviceIdentity := "service-identity" + + createAuthCtx := testutils.CreateOBOAuthContext(t.Context(), serviceIdentity, owner.Namespace, nil, nil) + + svc := service.ProvideInlineSecureValueService(tracer, tu.SecureValueService, nil) + + createdName, err := svc.CreateInline(createAuthCtx, owner, secret) + require.NoError(t, err) + require.NotEmpty(t, createdName) + + decryptAuthCtx := testutils.CreateServiceAuthContext(t.Context(), serviceIdentity, owner.Namespace, []string{"secret.grafana.app/securevalues:decrypt"}) + + decryptedValues, err := tu.DecryptService.Decrypt(decryptAuthCtx, owner.Namespace, createdName) + require.NoError(t, err) + + decryptedResult, ok := decryptedValues[createdName] + require.True(t, ok) + require.Equal(t, decryptedResult.Value().DangerouslyExposeAndConsumeValue(), secret.DangerouslyExposeAndConsumeValue()) + }) + + t.Run("when the auth info is missing it returns an error", func(t *testing.T) { + t.Parallel() + + svc := service.ProvideInlineSecureValueService(tracer, nil, nil) + _, err := svc.CreateInline(t.Context(), common.ObjectReference{}, "") + require.Error(t, err) + }) + + t.Run("when the request identity is not a user nor a service account, it returns an error", func(t *testing.T) { + t.Parallel() + + svc := service.ProvideInlineSecureValueService(tracer, nil, nil) + + createAuthCtx := testutils.CreateServiceAuthContext(t.Context(), "service-identity", defaultNs, nil) + + _, err := svc.CreateInline(createAuthCtx, common.ObjectReference{}, "") + require.Error(t, err) + }) + + t.Run("when the owner namespace does not match auth info namespace it returns an error", func(t *testing.T) { + t.Parallel() + + svc := service.ProvideInlineSecureValueService(tracer, nil, nil) + + reqNs := "org-2345" + createAuthCtx := testutils.CreateOBOAuthContext(t.Context(), "service-identity", reqNs, nil, nil) + + _, err := svc.CreateInline(createAuthCtx, owner, "") + require.Error(t, err) + }) + + t.Run("when the owner namespace is empty it returns an error", func(t *testing.T) { + t.Parallel() + + svc := service.ProvideInlineSecureValueService(tracer, nil, nil) + + createAuthCtx := testutils.CreateOBOAuthContext(t.Context(), "service-identity", defaultNs, nil, nil) + + _, err := svc.CreateInline(createAuthCtx, common.ObjectReference{}, "") + require.Error(t, err) + }) + + t.Run("when the owner reference has empty fields it returns an error", func(t *testing.T) { + t.Parallel() + + svc := service.ProvideInlineSecureValueService(tracer, nil, nil) + + owner := common.ObjectReference{ + Namespace: defaultNs, + } + + createAuthCtx := testutils.CreateOBOAuthContext(t.Context(), "service-identity", defaultNs, nil, nil) + + _, err := svc.CreateInline(createAuthCtx, owner, "") + require.Error(t, err) + + owner.APIGroup = "prometheus.datasource.grafana.app" + _, err = svc.CreateInline(createAuthCtx, owner, "") + require.Error(t, err) + + owner.APIVersion = "v1alpha1" + _, err = svc.CreateInline(createAuthCtx, owner, "") + require.Error(t, err) + + owner.Kind = "DataSourceConfig" + _, err = svc.CreateInline(createAuthCtx, owner, "") + require.Error(t, err) + owner.Kind = "" + + owner.Name = "test-datasource" + _, err = svc.CreateInline(createAuthCtx, owner, "") + require.Error(t, err) + }) + + t.Run("when an empty secret is provided it returns an error", func(t *testing.T) { + t.Parallel() + + svc := service.ProvideInlineSecureValueService(tracer, nil, nil) + + createAuthCtx := testutils.CreateOBOAuthContext(t.Context(), "service-identity", defaultNs, nil, nil) + + _, err := svc.CreateInline(createAuthCtx, owner, "") + require.Error(t, err) + }) +} diff --git a/pkg/registry/apis/secret/testutils/testutils.go b/pkg/registry/apis/secret/testutils/testutils.go index ebe8b109b81..3e742439bb0 100644 --- a/pkg/registry/apis/secret/testutils/testutils.go +++ b/pkg/registry/apis/secret/testutils/testutils.go @@ -244,8 +244,9 @@ func CreateUserAuthContext(ctx context.Context, namespace string, permissions ma return types.WithAuthInfo(ctx, requester) } -func CreateServiceAuthContext(ctx context.Context, serviceIdentity string, permissions []string) context.Context { +func CreateServiceAuthContext(ctx context.Context, serviceIdentity string, namespace string, permissions []string) context.Context { requester := &identity.StaticRequester{ + Namespace: namespace, AccessTokenClaims: &authn.Claims[authn.AccessTokenClaims]{ Rest: authn.AccessTokenClaims{ Permissions: permissions, @@ -256,3 +257,32 @@ func CreateServiceAuthContext(ctx context.Context, serviceIdentity string, permi return types.WithAuthInfo(ctx, requester) } + +// CreateOBOAuthContext emulates a context where the request is made on-behalf-of (OBO) a user, with an access token. +func CreateOBOAuthContext( + ctx context.Context, + serviceIdentity string, + namespace string, + userPermissions map[string][]string, + delegatedPermissions []string, +) context.Context { + requester := &identity.StaticRequester{ + Namespace: namespace, + Type: types.TypeUser, + UserID: 1, + Permissions: map[int64]map[string][]string{ + 1: userPermissions, + }, + AccessTokenClaims: &authn.Claims[authn.AccessTokenClaims]{ + Rest: authn.AccessTokenClaims{ + ServiceIdentity: serviceIdentity, + DelegatedPermissions: delegatedPermissions, + Actor: &authn.ActorClaims{ + Subject: "user:1", + }, + }, + }, + } + + return types.WithAuthInfo(ctx, requester) +} diff --git a/pkg/storage/secret/metadata/secure_value_test.go b/pkg/storage/secret/metadata/secure_value_test.go index 9400735cdd1..ce1513d95cf 100644 --- a/pkg/storage/secret/metadata/secure_value_test.go +++ b/pkg/storage/secret/metadata/secure_value_test.go @@ -403,7 +403,7 @@ func TestStateMachine(t *testing.T) { }, "decrypt": func(t *rapid.T) { input := decryptGen.Draw(t, "decryptInput") - authCtx := testutils.CreateServiceAuthContext(t.Context(), input.decrypter, []string{fmt.Sprintf("secret.grafana.app/securevalues/%+v:decrypt", input.name)}) + authCtx := testutils.CreateServiceAuthContext(t.Context(), input.decrypter, input.namespace, []string{fmt.Sprintf("secret.grafana.app/securevalues/%+v:decrypt", input.name)}) modelResult, modelErr := model.decrypt(input.decrypter, input.namespace, input.name) result, err := sut.DecryptService.Decrypt(authCtx, input.namespace, input.name) if err != nil || modelErr != nil { @@ -440,7 +440,7 @@ func TestSecureValueServiceExampleBased(t *testing.T) { require.NoError(t, err) require.Equal(t, sv.Status.Version, deletedSv.Status.Version) - authCtx := testutils.CreateServiceAuthContext(t.Context(), sv.Spec.Decrypters[0], []string{fmt.Sprintf("secret.grafana.app/securevalues/%+v:decrypt", sv.Name)}) + authCtx := testutils.CreateServiceAuthContext(t.Context(), sv.Spec.Decrypters[0], sv.Namespace, []string{fmt.Sprintf("secret.grafana.app/securevalues/%+v:decrypt", sv.Name)}) result, err := sut.DecryptService.Decrypt(authCtx, sv.Namespace, sv.Name) require.NoError(t, err) require.Equal(t, 1, len(result)) From 988439e0b8fba04643aac137fd32645094667cbe Mon Sep 17 00:00:00 2001 From: Matheus Macabu Date: Fri, 1 Aug 2025 14:00:01 +0200 Subject: [PATCH 18/89] Secrets: Simplify CanReference interface to only pass secure value names (#109030) --- pkg/registry/apis/secret/contracts/inline.go | 4 +- .../secret/service/inline_secure_value.go | 27 ++--- .../service/inline_secure_value_test.go | 102 +++--------------- 3 files changed, 27 insertions(+), 106 deletions(-) diff --git a/pkg/registry/apis/secret/contracts/inline.go b/pkg/registry/apis/secret/contracts/inline.go index 4f677fa5c79..f2f3de71568 100644 --- a/pkg/registry/apis/secret/contracts/inline.go +++ b/pkg/registry/apis/secret/contracts/inline.go @@ -7,8 +7,8 @@ import ( ) type InlineSecureValueSupport interface { - // Check that the request user can reference a secret in the context of a given resource (owner) - CanReference(ctx context.Context, owner common.ObjectReference, values common.InlineSecureValues) error + // Check that the request user can reference secure value names in the context of a given resource (owner) + CanReference(ctx context.Context, owner common.ObjectReference, names ...string) error // CreateInline creates a secret that is owned by the referenced object // returns the name of the created secret or an error diff --git a/pkg/registry/apis/secret/service/inline_secure_value.go b/pkg/registry/apis/secret/service/inline_secure_value.go index c2a6b97e451..9e0cb9fce41 100644 --- a/pkg/registry/apis/secret/service/inline_secure_value.go +++ b/pkg/registry/apis/secret/service/inline_secure_value.go @@ -38,13 +38,14 @@ func ProvideInlineSecureValueService( } } -func (s *inlineSecureValueService) CanReference(ctx context.Context, owner common.ObjectReference, values common.InlineSecureValues) error { +func (s *inlineSecureValueService) CanReference(ctx context.Context, owner common.ObjectReference, names ...string) error { ctx, span := s.tracer.Start(ctx, "InlineSecureValueService.CanReference", trace.WithAttributes( attribute.String("owner.namespace", owner.Namespace), attribute.String("owner.apiGroup", owner.APIGroup), attribute.String("owner.apiVersion", owner.APIVersion), attribute.String("owner.kind", owner.Kind), attribute.String("owner.name", owner.Name), + attribute.StringSlice("secureValueNames", names), )) defer span.End() @@ -61,31 +62,23 @@ func (s *inlineSecureValueService) CanReference(ctx context.Context, owner commo return fmt.Errorf("owner reference must have a valid API group, API version, kind and name") } - if len(values) == 0 { + if len(names) == 0 { return fmt.Errorf("no inline secure values provided") } - for field, value := range values { - if value.Name == "" { - return fmt.Errorf("field %s has an empty secure value name", field) + for _, name := range names { + if name == "" { + return fmt.Errorf("empty secure value name") } - if !value.Create.IsZero() { - return fmt.Errorf("field %s has 'create' set, which is not allowed", field) - } - - if value.Remove { - return fmt.Errorf("field %s has 'remove' set, which is not allowed", field) - } - - owned, err := s.isSecureValueOwnedByResource(ctx, owner, value.Name) + owned, err := s.isSecureValueOwnedByResource(ctx, owner, name) if err != nil { - return fmt.Errorf("field %s had an error checking secure value ownership: %w", field, err) + return err } if !owned { - if err := s.canIdentityReadSecureValue(ctx, xkube.Namespace(owner.Namespace), value.Name); err != nil { - return fmt.Errorf("field %s: identity cannot read secure value %s: %w", field, value.Name, err) + if err := s.canIdentityReadSecureValue(ctx, xkube.Namespace(owner.Namespace), name); err != nil { + return err } } } diff --git a/pkg/registry/apis/secret/service/inline_secure_value_test.go b/pkg/registry/apis/secret/service/inline_secure_value_test.go index fe486df5a9b..d108ce8f047 100644 --- a/pkg/registry/apis/secret/service/inline_secure_value_test.go +++ b/pkg/registry/apis/secret/service/inline_secure_value_test.go @@ -48,18 +48,13 @@ func TestIntegration_InlineSecureValue_CanReference(t *testing.T) { require.NoError(t, err) require.NotNil(t, createdSv2) - values := common.InlineSecureValues{ - "fieldA": {Name: sv1}, - "fieldB": {Name: sv2}, - } - ctx := testutils.CreateUserAuthContext(t.Context(), defaultNs, map[string][]string{ "securevalues:read": {"securevalues:uid:" + sv2}, }) svc := service.ProvideInlineSecureValueService(tracer, tu.SecureValueService, tu.AccessClient) - err = svc.CanReference(ctx, owner, values) + err = svc.CanReference(ctx, owner, sv1, sv2) require.NoError(t, err) }) @@ -67,7 +62,7 @@ func TestIntegration_InlineSecureValue_CanReference(t *testing.T) { t.Parallel() svc := service.ProvideInlineSecureValueService(tracer, nil, nil) - err := svc.CanReference(t.Context(), common.ObjectReference{}, common.InlineSecureValues{}) + err := svc.CanReference(t.Context(), common.ObjectReference{}) require.Error(t, err) }) @@ -79,7 +74,7 @@ func TestIntegration_InlineSecureValue_CanReference(t *testing.T) { reqNs := "org-2345" ctx := testutils.CreateUserAuthContext(t.Context(), reqNs, map[string][]string{}) - err := svc.CanReference(ctx, owner, common.InlineSecureValues{}) + err := svc.CanReference(ctx, owner) require.Error(t, err) }) @@ -90,7 +85,7 @@ func TestIntegration_InlineSecureValue_CanReference(t *testing.T) { ctx := testutils.CreateUserAuthContext(t.Context(), defaultNs, map[string][]string{}) - err := svc.CanReference(ctx, common.ObjectReference{}, common.InlineSecureValues{}) + err := svc.CanReference(ctx, common.ObjectReference{}) require.Error(t, err) }) @@ -105,23 +100,23 @@ func TestIntegration_InlineSecureValue_CanReference(t *testing.T) { ctx := testutils.CreateUserAuthContext(t.Context(), defaultNs, map[string][]string{}) - err := svc.CanReference(ctx, owner, common.InlineSecureValues{}) + err := svc.CanReference(ctx, owner) require.Error(t, err) owner.APIGroup = "prometheus.datasource.grafana.app" - require.Error(t, svc.CanReference(ctx, owner, common.InlineSecureValues{})) + require.Error(t, svc.CanReference(ctx, owner)) owner.APIGroup = "" owner.APIVersion = "v1alpha1" - require.Error(t, svc.CanReference(ctx, owner, common.InlineSecureValues{})) + require.Error(t, svc.CanReference(ctx, owner)) owner.APIVersion = "" owner.Kind = "DataSourceConfig" - require.Error(t, svc.CanReference(ctx, owner, common.InlineSecureValues{})) + require.Error(t, svc.CanReference(ctx, owner)) owner.Kind = "" owner.Name = "test-datasource" - require.Error(t, svc.CanReference(ctx, owner, common.InlineSecureValues{})) + require.Error(t, svc.CanReference(ctx, owner)) owner.Name = "" }) @@ -132,58 +127,7 @@ func TestIntegration_InlineSecureValue_CanReference(t *testing.T) { ctx := testutils.CreateUserAuthContext(t.Context(), defaultNs, map[string][]string{}) - err := svc.CanReference(ctx, owner, common.InlineSecureValues{}) - require.Error(t, err) - }) - - t.Run("when one of the secure values does not have a `name`, it returns an error", func(t *testing.T) { - t.Parallel() - - svc := service.ProvideInlineSecureValueService(tracer, nil, nil) - - values := common.InlineSecureValues{ - "fieldA": {Name: ""}, - } - - ctx := testutils.CreateUserAuthContext(t.Context(), defaultNs, map[string][]string{}) - - err := svc.CanReference(ctx, owner, values) - require.Error(t, err) - }) - - t.Run("when one of the secure values has `create` field set, it returns an error", func(t *testing.T) { - t.Parallel() - - svc := service.ProvideInlineSecureValueService(tracer, nil, nil) - - values := common.InlineSecureValues{ - "fieldA": { - Name: "test-sv", - Create: common.NewSecretValue("test"), - }, - } - - ctx := testutils.CreateUserAuthContext(t.Context(), defaultNs, map[string][]string{}) - - err := svc.CanReference(ctx, owner, values) - require.Error(t, err) - }) - - t.Run("when one of the secure values has `remove` field set, it returns an error", func(t *testing.T) { - t.Parallel() - - svc := service.ProvideInlineSecureValueService(tracer, nil, nil) - - values := common.InlineSecureValues{ - "fieldA": { - Name: "test-sv", - Remove: true, - }, - } - - ctx := testutils.CreateUserAuthContext(t.Context(), defaultNs, map[string][]string{}) - - err := svc.CanReference(ctx, owner, values) + err := svc.CanReference(ctx, owner) require.Error(t, err) }) @@ -193,13 +137,9 @@ func TestIntegration_InlineSecureValue_CanReference(t *testing.T) { tu := testutils.Setup(t) svc := service.ProvideInlineSecureValueService(tracer, tu.SecureValueService, nil) - values := common.InlineSecureValues{ - "fieldA": {Name: "non-existent-sv"}, - } - ctx := testutils.CreateUserAuthContext(t.Context(), defaultNs, map[string][]string{}) - err := svc.CanReference(ctx, owner, values) + err := svc.CanReference(ctx, owner, "non-existent-sv") require.Error(t, err) }) @@ -225,15 +165,11 @@ func TestIntegration_InlineSecureValue_CanReference(t *testing.T) { require.NoError(t, err) require.NotNil(t, createdSv1) - values := common.InlineSecureValues{ - "fieldA": {Name: sv1}, - } - ctx := testutils.CreateUserAuthContext(t.Context(), defaultNs, map[string][]string{}) svc := service.ProvideInlineSecureValueService(tracer, tu.SecureValueService, nil) - err = svc.CanReference(ctx, owner, values) + err = svc.CanReference(ctx, owner, sv1) require.Error(t, err) }) @@ -249,15 +185,11 @@ func TestIntegration_InlineSecureValue_CanReference(t *testing.T) { }) require.NoError(t, err) - values := common.InlineSecureValues{ - "fieldA": {Name: sv1}, - } - ctx := identity.WithServiceIdentityContext(t.Context(), 1234) svc := service.ProvideInlineSecureValueService(tracer, tu.SecureValueService, nil) - err = svc.CanReference(ctx, owner, values) + err = svc.CanReference(ctx, owner, sv1) require.Error(t, err) }) @@ -273,22 +205,18 @@ func TestIntegration_InlineSecureValue_CanReference(t *testing.T) { }) require.NoError(t, err) - values := common.InlineSecureValues{ - "fieldA": {Name: sv1}, - } - svc := service.ProvideInlineSecureValueService(tracer, tu.SecureValueService, tu.AccessClient) ctx := testutils.CreateUserAuthContext(t.Context(), defaultNs, map[string][]string{ "securevalues:read": {"securevalues:uid:another-sv"}, // can read, but another resource! }) - err = svc.CanReference(ctx, owner, values) + err = svc.CanReference(ctx, owner, sv1) require.Error(t, err) ctx = testutils.CreateUserAuthContext(t.Context(), defaultNs, nil) - err = svc.CanReference(ctx, owner, values) + err = svc.CanReference(ctx, owner, sv1) require.Error(t, err) }) } From 1130f69ef779217b42f0a5b12616869a39bf54c0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 12:00:34 +0000 Subject: [PATCH 19/89] Update dependency @types/glob to v9 (#109043) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 47 +++++++++++++++++++++++------------------------ 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index eb94c9eb369..2728eafd9a0 100644 --- a/package.json +++ b/package.json @@ -123,7 +123,7 @@ "@types/eslint": "9.6.1", "@types/eslint-scope": "^8.0.0", "@types/file-saver": "2.0.7", - "@types/glob": "^8.0.0", + "@types/glob": "^9.0.0", "@types/google.analytics": "^0.0.46", "@types/gtag.js": "^0.0.20", "@types/history": "4.7.11", diff --git a/yarn.lock b/yarn.lock index e3c9d0fdd0e..a78abcf6911 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9458,13 +9458,12 @@ __metadata: languageName: node linkType: hard -"@types/glob@npm:^8.0.0": - version: 8.1.0 - resolution: "@types/glob@npm:8.1.0" +"@types/glob@npm:^9.0.0": + version: 9.0.0 + resolution: "@types/glob@npm:9.0.0" dependencies: - "@types/minimatch": "npm:^5.1.2" - "@types/node": "npm:*" - checksum: 10/9101f3a9061e40137190f70626aa0e202369b5ec4012c3fabe6f5d229cce04772db9a94fa5a0eb39655e2e4ad105c38afbb4af56a56c0996a8c7d4fc72350e3d + glob: "npm:*" + checksum: 10/a9ea3afe1eafbc8fb303d2d39cd786084aece75fd8eeae1bad8febbf6e0323b429145f31e779a3d68fa693b2a53648ec2c639ee4858fb29132f801c74678051c languageName: node linkType: hard @@ -9714,7 +9713,7 @@ __metadata: languageName: node linkType: hard -"@types/minimatch@npm:*, @types/minimatch@npm:^5.1.2": +"@types/minimatch@npm:*": version: 5.1.2 resolution: "@types/minimatch@npm:5.1.2" checksum: 10/94db5060d20df2b80d77b74dd384df3115f01889b5b6c40fa2dfa27cfc03a68fb0ff7c1f2a0366070263eb2e9d6bfd8c87111d4bc3ae93c3f291297c1bf56c85 @@ -17974,22 +17973,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:10.4.1, glob@npm:^10.2.2, glob@npm:^10.3.10": - version: 10.4.1 - resolution: "glob@npm:10.4.1" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^3.1.2" - minimatch: "npm:^9.0.4" - minipass: "npm:^7.1.2" - path-scurry: "npm:^1.11.1" - bin: - glob: dist/esm/bin.mjs - checksum: 10/d7bb49d2b413f77bdd59fea4ca86dcc12450deee221af0ca93e09534b81b9ef68fe341345751d8ff0c5b54bad422307e0e44266ff8ad7fbbd0c200e8ec258b16 - languageName: node - linkType: hard - -"glob@npm:11.0.3, glob@npm:^11.0.0": +"glob@npm:*, glob@npm:11.0.3, glob@npm:^11.0.0": version: 11.0.3 resolution: "glob@npm:11.0.3" dependencies: @@ -18005,6 +17989,21 @@ __metadata: languageName: node linkType: hard +"glob@npm:10.4.1, glob@npm:^10.2.2, glob@npm:^10.3.10": + version: 10.4.1 + resolution: "glob@npm:10.4.1" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + path-scurry: "npm:^1.11.1" + bin: + glob: dist/esm/bin.mjs + checksum: 10/d7bb49d2b413f77bdd59fea4ca86dcc12450deee221af0ca93e09534b81b9ef68fe341345751d8ff0c5b54bad422307e0e44266ff8ad7fbbd0c200e8ec258b16 + languageName: node + linkType: hard + "glob@npm:^7.0.3, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6": version: 7.2.3 resolution: "glob@npm:7.2.3" @@ -18321,7 +18320,7 @@ __metadata: "@types/eslint": "npm:9.6.1" "@types/eslint-scope": "npm:^8.0.0" "@types/file-saver": "npm:2.0.7" - "@types/glob": "npm:^8.0.0" + "@types/glob": "npm:^9.0.0" "@types/google.analytics": "npm:^0.0.46" "@types/gtag.js": "npm:^0.0.20" "@types/history": "npm:4.7.11" From 4f30a3b62ba28769990d87c8b7d3ecaa571685b0 Mon Sep 17 00:00:00 2001 From: Tom Ratcliffe Date: Fri, 1 Aug 2025 13:34:33 +0100 Subject: [PATCH 20/89] Folders: Use app platform search endpoint and update tests (#108814) * Update test utils package with mock folder + search endpoints * Add dashboards v0alpha1 api client * Update hook to use app platform search API * Update tests and fixtures --- .../src/fixtures/folders.ts | 130 +++++++++++++++ .../src/handlers/all-handlers.ts | 4 +- .../src/handlers/api/folders/handlers.ts | 52 ++++++ .../v0alpha1/handlers.ts | 52 ++++++ .../src/types/browse-dashboards.ts | 58 +++++++ packages/grafana-test-utils/src/unstable.ts | 3 + .../api/clients/dashboard/v0alpha1/baseAPI.ts | 14 ++ .../dashboard/v0alpha1/endpoints.gen.ts | 53 +++++++ .../api/clients/dashboard/v0alpha1/index.ts | 27 ++++ .../NestedFolderPicker.test.tsx | 149 ++++++------------ .../useFoldersQuery.test.tsx | 118 +++++--------- .../useFoldersQueryAppPlatform.ts | 26 +-- public/app/core/reducers/root.ts | 2 + .../BrowseDashboardsPage.test.tsx | 33 +--- .../BrowseFolderLibraryPanelsPage.test.tsx | 33 ++-- .../BrowseActions/MoveModal.test.tsx | 82 ++-------- .../components/BrowseView.test.tsx | 5 +- .../fixtures/dashboardsTreeItem.fixture.ts | 58 +------ public/app/store/configureStore.ts | 2 + scripts/generate-rtk-apis.ts | 11 ++ 20 files changed, 539 insertions(+), 373 deletions(-) create mode 100644 packages/grafana-test-utils/src/fixtures/folders.ts create mode 100644 packages/grafana-test-utils/src/handlers/api/folders/handlers.ts create mode 100644 packages/grafana-test-utils/src/handlers/apis/dashboard.grafana.app/v0alpha1/handlers.ts create mode 100644 packages/grafana-test-utils/src/types/browse-dashboards.ts create mode 100644 public/app/api/clients/dashboard/v0alpha1/baseAPI.ts create mode 100644 public/app/api/clients/dashboard/v0alpha1/endpoints.gen.ts create mode 100644 public/app/api/clients/dashboard/v0alpha1/index.ts diff --git a/packages/grafana-test-utils/src/fixtures/folders.ts b/packages/grafana-test-utils/src/fixtures/folders.ts new file mode 100644 index 00000000000..7fc9bed9e20 --- /dev/null +++ b/packages/grafana-test-utils/src/fixtures/folders.ts @@ -0,0 +1,130 @@ +import { Chance } from 'chance'; + +import { DashboardsTreeItem, DashboardViewItem, UIDashboardViewItem } from '../types/browse-dashboards'; + +function wellFormedEmptyFolder( + seed = 1, + partial?: Partial> +): DashboardsTreeItem { + const random = Chance(seed); + + return { + item: { + kind: 'ui', + uiKind: 'empty-folder', + uid: random.guid(), + }, + level: 0, + isOpen: false, + ...partial, + }; +} + +function wellFormedDashboard( + seed = 1, + partial?: Partial>, + itemPartial?: Partial +): DashboardsTreeItem { + const random = Chance(seed); + + return { + item: { + kind: 'dashboard', + title: random.sentence({ words: 3 }), + uid: random.guid(), + tags: [random.word()], + ...itemPartial, + }, + level: 0, + isOpen: false, + ...partial, + }; +} + +function wellFormedFolder( + seed = 1, + partial?: Partial>, + itemPartial?: Partial +): DashboardsTreeItem { + const random = Chance(seed); + const uid = random.guid(); + + return { + item: { + kind: 'folder', + title: random.sentence({ words: 3 }), + uid, + url: `/dashboards/f/${uid}`, + ...itemPartial, + }, + level: 0, + isOpen: false, + ...partial, + }; +} + +export function treeViewersCanEdit() { + const [, { folderA, folderC }] = wellFormedTree(); + + return [ + [folderA, folderC], + { + folderA, + folderC, + }, + ] as const; +} + +export function wellFormedTree() { + let seed = 1; + + const folderA = wellFormedFolder(seed++); + const folderA_folderA = wellFormedFolder(seed++, { level: 1 }, { parentUID: folderA.item.uid }); + const folderA_folderB = wellFormedFolder(seed++, { level: 1 }, { parentUID: folderA.item.uid }); + const folderA_folderB_dashbdA = wellFormedDashboard(seed++, { level: 2 }, { parentUID: folderA_folderB.item.uid }); + const folderA_folderB_dashbdB = wellFormedDashboard(seed++, { level: 2 }, { parentUID: folderA_folderB.item.uid }); + const folderA_folderC = wellFormedFolder(seed++, { level: 1 }, { parentUID: folderA.item.uid }); + const folderA_folderC_dashbdA = wellFormedDashboard(seed++, { level: 2 }, { parentUID: folderA_folderC.item.uid }); + const folderA_folderC_dashbdB = wellFormedDashboard(seed++, { level: 2 }, { parentUID: folderA_folderC.item.uid }); + const folderA_dashbdD = wellFormedDashboard(seed++, { level: 1 }, { parentUID: folderA.item.uid }); + const folderB = wellFormedFolder(seed++); + const folderB_empty = wellFormedEmptyFolder(seed++); + const folderC = wellFormedFolder(seed++); + const dashbdD = wellFormedDashboard(seed++); + const dashbdE = wellFormedDashboard(seed++); + + return [ + [ + folderA, + folderA_folderA, + folderA_folderB, + folderA_folderB_dashbdA, + folderA_folderB_dashbdB, + folderA_folderC, + folderA_folderC_dashbdA, + folderA_folderC_dashbdB, + folderA_dashbdD, + folderB, + folderB_empty, + folderC, + dashbdD, + dashbdE, + ], + { + folderA, + folderA_folderA, + folderA_folderB, + folderA_folderB_dashbdA, + folderA_folderB_dashbdB, + folderA_folderC, + folderA_folderC_dashbdA, + folderA_folderC_dashbdB, + folderA_dashbdD, + folderB, + folderB_empty, + folderC, + dashbdD, + dashbdE, + }, + ] as const; +} diff --git a/packages/grafana-test-utils/src/handlers/all-handlers.ts b/packages/grafana-test-utils/src/handlers/all-handlers.ts index edf4c592ef2..3e626ba021b 100644 --- a/packages/grafana-test-utils/src/handlers/all-handlers.ts +++ b/packages/grafana-test-utils/src/handlers/all-handlers.ts @@ -1,7 +1,9 @@ import { HttpHandler } from 'msw'; +import folderHandlers from './api/folders/handlers'; import teamsHandlers from './api/teams/handlers'; +import appPlatformFolderHandlers from './apis/dashboard.grafana.app/v0alpha1/handlers'; -const allHandlers: HttpHandler[] = [...teamsHandlers]; +const allHandlers: HttpHandler[] = [...teamsHandlers, ...folderHandlers, ...appPlatformFolderHandlers]; export default allHandlers; diff --git a/packages/grafana-test-utils/src/handlers/api/folders/handlers.ts b/packages/grafana-test-utils/src/handlers/api/folders/handlers.ts new file mode 100644 index 00000000000..103b816ce3a --- /dev/null +++ b/packages/grafana-test-utils/src/handlers/api/folders/handlers.ts @@ -0,0 +1,52 @@ +import { HttpResponse, http } from 'msw'; + +import { treeViewersCanEdit, wellFormedTree } from '../../../fixtures/folders'; + +const [mockTree] = wellFormedTree(); +const [mockTreeThatViewersCanEdit] = treeViewersCanEdit(); +const collator = new Intl.Collator(); + +const listFoldersHandler = () => + http.get('/api/folders', ({ request }) => { + const url = new URL(request.url); + const parentUid = url.searchParams.get('parentUid') ?? undefined; + const permission = url.searchParams.get('permission'); + + const limit = parseInt(url.searchParams.get('limit') ?? '1000', 10); + const page = parseInt(url.searchParams.get('page') ?? '1', 10); + + const tree = permission === 'Edit' ? mockTreeThatViewersCanEdit : mockTree; + + // reconstruct a folder API response from the flat tree fixture + const folders = tree + .filter((v) => v.item.kind === 'folder' && v.item.parentUID === parentUid) + .map((folder) => { + return { + uid: folder.item.uid, + title: folder.item.kind === 'folder' ? folder.item.title : "invalid - this shouldn't happen", + }; + }) + .sort((a, b) => collator.compare(a.title, b.title)) // API always sorts by title + .slice(limit * (page - 1), limit * page); + + return HttpResponse.json(folders); + }); + +const getFolderHandler = () => + http.get('/api/folders/:uid', ({ params }) => { + const { uid } = params; + + const folder = mockTree.find((v) => v.item.uid === uid); + if (!folder) { + return HttpResponse.json({ message: 'folder not found', status: 'not-found' }, { status: 404 }); + } + + return HttpResponse.json({ + title: folder?.item.title, + uid: folder?.item.uid, + }); + }); + +const handlers = [listFoldersHandler(), getFolderHandler()]; + +export default handlers; diff --git a/packages/grafana-test-utils/src/handlers/apis/dashboard.grafana.app/v0alpha1/handlers.ts b/packages/grafana-test-utils/src/handlers/apis/dashboard.grafana.app/v0alpha1/handlers.ts new file mode 100644 index 00000000000..43813d6f4f8 --- /dev/null +++ b/packages/grafana-test-utils/src/handlers/apis/dashboard.grafana.app/v0alpha1/handlers.ts @@ -0,0 +1,52 @@ +import { Chance } from 'chance'; +import { HttpResponse, http } from 'msw'; + +import { wellFormedTree } from '../../../../fixtures/folders'; + +const [mockTree] = wellFormedTree(); + +type FilterArray = Array<(v: (typeof mockTree)[number]) => boolean>; + +const getSearchHandler = () => + http.get('/apis/dashboard.grafana.app/v0alpha1/namespaces/default/search', ({ request }) => { + const folderFilter = new URL(request.url).searchParams.get('folder') || null; + const typeFilter = new URL(request.url).searchParams.get('type') || null; + const response = mockTree + .filter((filterItem) => { + const filters: FilterArray = []; + if (folderFilter && folderFilter !== 'general') { + filters.push(({ item }) => item.kind === 'folder' && item.parentUID === folderFilter); + } + + if (folderFilter === 'general') { + filters.push(({ item }) => item.kind === 'folder' && item.parentUID === undefined); + } + + if (typeFilter) { + filters.push(({ item }) => item.kind === typeFilter); + } + + return filters.every((filterPredicate) => filterPredicate(filterItem)); + }) + + .map(({ item }) => { + const random = Chance(item.uid); + return { + resource: 'folders', + name: item.uid, + title: item.title, + field: { + // Generate mock deprecated IDs only in the mock handlers - not generating in + // mock data as it would require updating/tracking in the types as well + 'grafana.app/deprecatedInternalID': random.integer({ min: 1, max: 1000 }), + }, + }; + }); + + return HttpResponse.json({ + totalHits: response.length, + hits: response, + }); + }); + +export default [getSearchHandler()]; diff --git a/packages/grafana-test-utils/src/types/browse-dashboards.ts b/packages/grafana-test-utils/src/types/browse-dashboards.ts new file mode 100644 index 00000000000..5757b4a2ec0 --- /dev/null +++ b/packages/grafana-test-utils/src/types/browse-dashboards.ts @@ -0,0 +1,58 @@ +// FIXME: This file is a duplication of types within the core code +// Where should these live long term? +// @grafana/schema? +// New package @grafana/core? @grafana/types? + +enum ManagerKind { + Repo = 'repo', + Terraform = 'terraform', + Kubectl = 'kubectl', + Plugin = 'plugin', +} + +type DashboardViewItemKind = 'folder' | 'dashboard' | 'panel'; + +type DashboardViewItemWithUIItems = DashboardViewItem | UIDashboardViewItem; + +export interface DashboardsTreeItem { + item: T; + level: number; + isOpen: boolean; + parentUID?: string; +} + +export interface UIDashboardViewItem { + kind: 'ui'; + uiKind: 'empty-folder' | 'pagination-placeholder' | 'divider'; + uid: string; + // Optional title to make mock data easier to work with + title?: string; +} + +/** + * Type used in the folder view components + */ +export interface DashboardViewItem { + kind: DashboardViewItemKind; + uid: string; + title: string; + url?: string; + tags?: string[]; + + icon?: string; + + parentUID?: string; + /** @deprecated Not used in new Browse UI */ + parentTitle?: string; + /** @deprecated Not used in new Browse UI */ + parentKind?: string; + + // Used only for psuedo-folders, such as Starred or Recent + /** @deprecated Not used in new Browse UI */ + itemsUIDs?: string[]; + + // For enterprise sort options + sortMeta?: number | string; // value sorted by + sortMetaName?: string; // name of the value being sorted e.g. 'Views' + managedBy?: ManagerKind; +} diff --git a/packages/grafana-test-utils/src/unstable.ts b/packages/grafana-test-utils/src/unstable.ts index 5b60f83479c..8758e294464 100644 --- a/packages/grafana-test-utils/src/unstable.ts +++ b/packages/grafana-test-utils/src/unstable.ts @@ -1 +1,4 @@ +import { wellFormedTree } from './fixtures/folders'; + +export const getFolderFixtures = wellFormedTree; export { MOCK_TEAMS } from './fixtures/teams'; diff --git a/public/app/api/clients/dashboard/v0alpha1/baseAPI.ts b/public/app/api/clients/dashboard/v0alpha1/baseAPI.ts new file mode 100644 index 00000000000..dca53563fa0 --- /dev/null +++ b/public/app/api/clients/dashboard/v0alpha1/baseAPI.ts @@ -0,0 +1,14 @@ +import { createApi } from '@reduxjs/toolkit/query/react'; + +import { createBaseQuery } from 'app/api/createBaseQuery'; +import { getAPIBaseURL } from 'app/api/utils'; + +export const BASE_URL = getAPIBaseURL('dashboard.grafana.app', 'v0alpha1'); + +export const api = createApi({ + reducerPath: 'dashboardAPIv0alpha1', + baseQuery: createBaseQuery({ + baseURL: BASE_URL, + }), + endpoints: () => ({}), +}); diff --git a/public/app/api/clients/dashboard/v0alpha1/endpoints.gen.ts b/public/app/api/clients/dashboard/v0alpha1/endpoints.gen.ts new file mode 100644 index 00000000000..8730157dedf --- /dev/null +++ b/public/app/api/clients/dashboard/v0alpha1/endpoints.gen.ts @@ -0,0 +1,53 @@ +import { api } from './baseAPI'; +export const addTagTypes = ['Search'] as const; +const injectedRtkApi = api + .enhanceEndpoints({ + addTagTypes, + }) + .injectEndpoints({ + endpoints: (build) => ({ + getSearch: build.query({ + query: (queryArg) => ({ + url: `/search`, + params: { + query: queryArg.query, + folder: queryArg.folder, + sort: queryArg.sort, + }, + }), + providesTags: ['Search'], + }), + }), + overrideExisting: false, + }); +export { injectedRtkApi as generatedAPI }; +export type GetSearchApiResponse = /** status 200 undefined */ { + /** APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources */ + apiVersion?: string; + /** Facet results */ + facets?: { + [key: string]: any; + }; + /** The dashboard body (unstructured for now) */ + hits: any[]; + /** Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds */ + kind?: string; + /** Max score */ + maxScore?: number; + /** Where the query started from */ + offset?: number; + /** Cost of running the query */ + queryCost?: number; + /** How are the results sorted */ + sortBy?: any; + /** The number of matching results */ + totalHits: number; +}; +export type GetSearchApiArg = { + /** user query string */ + query?: string; + /** search/list within a folder (not recursive) */ + folder?: string; + /** sortable field */ + sort?: string; +}; diff --git a/public/app/api/clients/dashboard/v0alpha1/index.ts b/public/app/api/clients/dashboard/v0alpha1/index.ts new file mode 100644 index 00000000000..f61b46bc1f9 --- /dev/null +++ b/public/app/api/clients/dashboard/v0alpha1/index.ts @@ -0,0 +1,27 @@ +import { generatedAPI, GetSearchApiArg } from './endpoints.gen'; + +type OverrideGetSearchRequestOptions = GetSearchApiArg & { + type: string; +}; + +export const dashboardAPIv0alpha1 = generatedAPI.enhanceEndpoints({ + addTagTypes: ['Folder', 'Dashboard'], + endpoints: { + getSearch: (endpointDefinition) => { + const originalQuery = endpointDefinition.query; + endpointDefinition.providesTags = ['Search', 'Folder', 'Dashboard']; + if (originalQuery) { + // TODO: Remove once API spec is updated with `type` + endpointDefinition.query = (requestOptions: OverrideGetSearchRequestOptions) => ({ + ...originalQuery(requestOptions), + params: { + ...requestOptions, + type: requestOptions.type, + }, + }); + } + }, + }, +}); + +export const { useGetSearchQuery } = dashboardAPIv0alpha1; diff --git a/public/app/core/components/NestedFolderPicker/NestedFolderPicker.test.tsx b/public/app/core/components/NestedFolderPicker/NestedFolderPicker.test.tsx index 226583c54e1..38674034a0d 100644 --- a/public/app/core/components/NestedFolderPicker/NestedFolderPicker.test.tsx +++ b/public/app/core/components/NestedFolderPicker/NestedFolderPicker.test.tsx @@ -1,89 +1,31 @@ -import { fireEvent, render as rtlRender, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { HttpResponse, http } from 'msw'; -import { SetupServer, setupServer } from 'msw/node'; -import { TestProvider } from 'test/helpers/TestProvider'; +import { fireEvent, render, screen } from 'test/test-utils'; -import { config } from '@grafana/runtime'; +import { config, setBackendSrv } from '@grafana/runtime'; +import { setupMockServer } from '@grafana/test-utils/server'; +import { getFolderFixtures } from '@grafana/test-utils/unstable'; import { backendSrv } from 'app/core/services/backend_srv'; -import { - treeViewersCanEdit, - wellFormedTree, -} from '../../../features/browse-dashboards/fixtures/dashboardsTreeItem.fixture'; - import { NestedFolderPicker } from './NestedFolderPicker'; -const [mockTree, { folderA, folderB, folderC, folderA_folderA, folderA_folderB }] = wellFormedTree(); -const [mockTreeThatViewersCanEdit /* shares folders with wellFormedTree */] = treeViewersCanEdit(); +const [_, { folderA, folderB, folderC, folderA_folderA, folderA_folderB, folderA_folderC }] = getFolderFixtures(); -jest.mock('@grafana/runtime', () => ({ - ...jest.requireActual('@grafana/runtime'), - getBackendSrv: () => backendSrv, -})); - -function render(...[ui, options]: Parameters) { - rtlRender({ui}, options); -} +setupMockServer(); +setBackendSrv(backendSrv); describe('NestedFolderPicker', () => { const mockOnChange = jest.fn(); const originalScrollIntoView = window.HTMLElement.prototype.scrollIntoView; - let server: SetupServer; beforeAll(() => { window.HTMLElement.prototype.scrollIntoView = function () {}; - - server = setupServer( - http.get('/api/folders/:uid', () => { - return HttpResponse.json({ - title: folderA.item.title, - uid: folderA.item.uid, - }); - }), - - http.get('/apis/provisioning.grafana.app/v0alpha1/namespaces/default/settings', () => { - return HttpResponse.json({ - items: [], - }); - }), - - http.get('/api/folders', ({ request }) => { - const url = new URL(request.url); - const parentUid = url.searchParams.get('parentUid') ?? undefined; - const permission = url.searchParams.get('permission'); - - const limit = parseInt(url.searchParams.get('limit') ?? '1000', 10); - const page = parseInt(url.searchParams.get('page') ?? '1', 10); - - const tree = permission === 'Edit' ? mockTreeThatViewersCanEdit : mockTree; - - // reconstruct a folder API response from the flat tree fixture - const folders = tree - .filter((v) => v.item.kind === 'folder' && v.item.parentUID === parentUid) - .map((folder) => { - return { - uid: folder.item.uid, - title: folder.item.kind === 'folder' ? folder.item.title : "invalid - this shouldn't happen", - }; - }) - .slice(limit * (page - 1), limit * page); - - return HttpResponse.json(folders); - }) - ); - - server.listen(); }); afterAll(() => { - server.close(); window.HTMLElement.prototype.scrollIntoView = originalScrollIntoView; }); afterEach(() => { jest.resetAllMocks(); - server.resetHandlers(); }); it('renders a button with the correct label when no folder is selected', async () => { @@ -92,18 +34,18 @@ describe('NestedFolderPicker', () => { }); it('renders a button with the correct label when a folder is selected', async () => { - render(); + render(); expect( await screen.findByRole('button', { name: `Select folder: ${folderA.item.title} currently selected` }) ).toBeInTheDocument(); }); it('clicking the button opens the folder picker', async () => { - render(); + const { user } = render(); // Open the picker and wait for children to load const button = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(button); + await user.click(button); await screen.findByLabelText(folderA.item.title); // Select folder button is no longer visible @@ -118,73 +60,73 @@ describe('NestedFolderPicker', () => { }); it('can select a folder from the picker', async () => { - render(); + const { user } = render(); // Open the picker and wait for children to load const button = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(button); + await user.click(button); await screen.findByLabelText(folderA.item.title); - await userEvent.click(screen.getByLabelText(folderA.item.title)); + await user.click(screen.getByLabelText(folderA.item.title)); expect(mockOnChange).toHaveBeenCalledWith(folderA.item.uid, folderA.item.title); }); it('can clear a selection if clearable is specified', async () => { - render(); + const { user } = render(); - await userEvent.click(await screen.findByRole('button', { name: 'Clear selection' })); + await user.click(await screen.findByRole('button', { name: 'Clear selection' })); expect(mockOnChange).toHaveBeenCalledWith(undefined, undefined); }); it('can select a folder from the picker with the keyboard', async () => { - render(); + const { user } = render(); const button = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(button); + await user.click(button); - await userEvent.keyboard('{ArrowDown}{ArrowDown}{Enter}'); - expect(mockOnChange).toHaveBeenCalledWith(folderA.item.uid, folderA.item.title); + await user.keyboard('{ArrowDown}{ArrowDown}{Enter}'); + expect(mockOnChange).toHaveBeenCalledWith(folderC.item.uid, folderC.item.title); }); it('shows the root folder by default', async () => { - render(); + const { user } = render(); // Open the picker and wait for children to load const button = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(button); + await user.click(button); await screen.findByLabelText(folderA.item.title); - await userEvent.click(screen.getByLabelText('Dashboards')); + await user.click(screen.getByLabelText('Dashboards')); expect(mockOnChange).toHaveBeenCalledWith('', 'Dashboards'); }); it('hides the root folder if the prop says so', async () => { - render(); + const { user } = render(); // Open the picker and wait for children to load const button = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(button); + await user.click(button); await screen.findByLabelText(folderA.item.title); expect(screen.queryByLabelText('Dashboards')).not.toBeInTheDocument(); }); it('hides folders specififed by UID', async () => { - render(); + const { user } = render(); // Open the picker and wait for children to load const button = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(button); + await user.click(button); await screen.findByLabelText(folderA.item.title); expect(screen.queryByLabelText(folderC.item.title)).not.toBeInTheDocument(); }); it('by default only shows items the user can edit', async () => { - render(); + const { user } = render(); const button = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(button); + await user.click(button); await screen.findByLabelText(folderA.item.title); expect(screen.queryByLabelText(folderB.item.title)).not.toBeInTheDocument(); // folderB is not editable @@ -192,10 +134,10 @@ describe('NestedFolderPicker', () => { }); it('shows items the user can view, with the prop', async () => { - render(); + const { user } = render(); const button = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(button); + await user.click(button); await screen.findByLabelText(folderA.item.title); expect(screen.getByLabelText(folderB.item.title)).toBeInTheDocument(); @@ -214,11 +156,11 @@ describe('NestedFolderPicker', () => { }); it('can expand and collapse a folder to show its children', async () => { - render(); + const { user } = render(); // Open the picker and wait for children to load const button = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(button); + await user.click(button); await screen.findByLabelText(folderA.item.title); // Expand Folder A @@ -240,34 +182,35 @@ describe('NestedFolderPicker', () => { fireEvent.mouseDown(screen.getByRole('button', { name: `Expand folder ${folderA.item.title}` })); // Select the first child - await userEvent.click(screen.getByLabelText(folderA_folderA.item.title)); + await user.click(screen.getByLabelText(folderA_folderA.item.title)); expect(mockOnChange).toHaveBeenCalledWith(folderA_folderA.item.uid, folderA_folderA.item.title); }); it('can expand and collapse a folder to show its children with the keyboard', async () => { - render(); + const { user } = render(); const button = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(button); + await user.click(button); // Expand Folder A - await userEvent.keyboard('{ArrowDown}{ArrowDown}{ArrowRight}'); + await user.keyboard('{ArrowDown}{ArrowDown}{ArrowDown}{ArrowDown}{ArrowRight}'); // Folder A's children are visible expect(await screen.findByLabelText(folderA_folderA.item.title)).toBeInTheDocument(); expect(await screen.findByLabelText(folderA_folderB.item.title)).toBeInTheDocument(); + expect(await screen.findByLabelText(folderA_folderC.item.title)).toBeInTheDocument(); // Collapse Folder A - await userEvent.keyboard('{ArrowLeft}'); + await user.keyboard('{ArrowLeft}'); expect(screen.queryByLabelText(folderA_folderA.item.title)).not.toBeInTheDocument(); expect(screen.queryByLabelText(folderA_folderB.item.title)).not.toBeInTheDocument(); // Expand Folder A again - await userEvent.keyboard('{ArrowRight}'); + await user.keyboard('{ArrowRight}'); // Select the first child - await userEvent.keyboard('{ArrowDown}{Enter}'); - expect(mockOnChange).toHaveBeenCalledWith(folderA_folderA.item.uid, folderA_folderA.item.title); + await user.keyboard('{ArrowDown}{Enter}'); + expect(mockOnChange).toHaveBeenCalledWith(folderA_folderC.item.uid, folderA_folderC.item.title); }); }); @@ -283,11 +226,11 @@ describe('NestedFolderPicker', () => { }); it('does not show an expand button', async () => { - render(); + const { user } = render(); // Open the picker and wait for children to load const button = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(button); + await user.click(button); await screen.findByLabelText(folderA.item.title); // There should be no expand button @@ -296,13 +239,13 @@ describe('NestedFolderPicker', () => { }); it('does not expand a folder with the keyboard', async () => { - render(); + const { user } = render(); const button = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(button); + await user.click(button); // try to expand Folder A - await userEvent.keyboard('{ArrowDown}{ArrowDown}{ArrowRight}'); + await user.keyboard('{ArrowDown}{ArrowDown}{ArrowRight}'); // Folder A's children are not visible expect(screen.queryByLabelText(folderA_folderA.item.title)).not.toBeInTheDocument(); diff --git a/public/app/core/components/NestedFolderPicker/useFoldersQuery.test.tsx b/public/app/core/components/NestedFolderPicker/useFoldersQuery.test.tsx index 18d83068b5e..cf0f0f67af1 100644 --- a/public/app/core/components/NestedFolderPicker/useFoldersQuery.test.tsx +++ b/public/app/core/components/NestedFolderPicker/useFoldersQuery.test.tsx @@ -1,82 +1,26 @@ -import { act, renderHook } from '@testing-library/react'; +import { ReactNode } from 'react'; +import { act, getWrapper, renderHook, waitFor } from 'test/test-utils'; import { GrafanaConfig } from '@grafana/data'; import * as runtime from '@grafana/runtime'; -import { DashboardsTreeItem } from 'app/features/browse-dashboards/types'; +import { setupMockServer } from '@grafana/test-utils/server'; +import { getFolderFixtures } from '@grafana/test-utils/unstable'; +import { backendSrv } from 'app/core/services/backend_srv'; import { DashboardViewItem } from '../../../features/search/types'; import { useFoldersQuery } from './useFoldersQuery'; import { getRootFolderItem } from './utils'; -const PAGE_SIZE = 10; +const [_, { folderA, folderB, folderC }] = getFolderFixtures(); -const legacyResponse = { - status: 'fulfilled', - originalArgs: { parentUid: undefined, page: 1, limit: PAGE_SIZE, permission: 'Edit' }, - data: [{ title: 'Legacy Folder', uid: 'legacy1', managedBy: undefined }], +runtime.setBackendSrv(backendSrv); +setupMockServer(); + +const wrapper = ({ children }: { children: ReactNode }) => { + const ProviderWrapper = getWrapper({ renderWithRouter: true }); + return {children}; }; -// Mock the legacy API client -jest.mock('app/features/browse-dashboards/api/browseDashboardsAPI', () => { - const PAGE_SIZE = 10; - return { - PAGE_SIZE, - browseDashboardsAPI: { - endpoints: { - listFolders: { - select: jest.fn(() => () => legacyResponse), - initiate: jest.fn(() => ({ - arg: { parentUid: undefined, page: 1, limit: PAGE_SIZE, permission: 'Edit' }, - unsubscribe: jest.fn(), - })), - }, - }, - }, - }; -}); - -const appPlatfromResponse = { - status: 'fulfilled', - originalArgs: { name: 'general' }, - data: { - items: [ - { - metadata: { name: 'app1', annotations: {} }, - spec: { title: 'AppPlatform Folder' }, - }, - ], - }, -}; - -// Mock the appPlatform API client -jest.mock('app/api/clients/folder/v1beta1', () => ({ - folderAPIv1beta1: { - endpoints: { - getFolderChildren: { - select: jest.fn(() => () => appPlatfromResponse), - initiate: jest.fn((arg: unknown) => ({ - arg, - unsubscribe: jest.fn(), - })), - }, - }, - }, -})); - -// Mock getPaginationPlaceholders to return empty array for simplicity -jest.mock('app/features/browse-dashboards/state/utils', () => ({ - getPaginationPlaceholders: jest.fn((): DashboardsTreeItem[] => []), -})); - -// Mock useDispatch and useSelector to just pass through -jest.mock('app/types/store', () => { - const mod = jest.requireActual('app/types/store'); - return { - ...mod, - useDispatch: () => (val: unknown) => val, - useSelector: (selector: Function) => selector(), - }; -}); describe('useFoldersQuery', () => { let configBackup: GrafanaConfig; @@ -89,28 +33,40 @@ describe('useFoldersQuery', () => { runtime.config.featureToggles = configBackup.featureToggles; }); - it('returns data using legacy api', () => { - runtime.config.featureToggles.foldersAppPlatformAPI = false; - const items = testFn(); - expect((items[1].item as DashboardViewItem).title).toBe('Legacy Folder'); - }); + describe.each([ + // foldersAppPlatformAPI enabled + true, + // foldersAppPlatformAPI disabled + false, + ])('foldersAppPlatformAPI feature toggle set to %s', (featureToggleState) => { + it('returns data using legacy api', async () => { + runtime.config.featureToggles.foldersAppPlatformAPI = featureToggleState; + const [_dashboardsContainer, ...items] = await testFn(); - it('returns appPlatform hook result when foldersAppPlatformAPI is on', () => { - runtime.config.featureToggles.foldersAppPlatformAPI = true; - const items = testFn(); - expect((items[1].item as DashboardViewItem).title).toBe('AppPlatform Folder'); + const sortedItemTitles = items.map((item) => (item.item as DashboardViewItem).title).sort(); + const expectedTitles = [folderA.item.title, folderB.item.title, folderC.item.title].sort(); + + expect(sortedItemTitles).toEqual(expectedTitles); + }); }); }); -function testFn() { - const { result } = renderHook(() => useFoldersQuery(true, {})); +async function testFn() { + const { result } = renderHook(() => useFoldersQuery(true, {}), { wrapper }); - expect(result.current.items).toEqual([getRootFolderItem()]); + expect(result.current.items[0]).toEqual(getRootFolderItem()); expect(result.current.isLoading).toBe(false); + act(() => { result.current.requestNextPage(undefined); }); - expect(result.current.items.length).toBe(2); + expect(result.current.isLoading).toBe(true); + + await waitFor(() => { + const withoutPaginationPlaceholders = result.current.items.filter((item) => item.item.kind !== 'ui'); + return expect(withoutPaginationPlaceholders.length).toBeGreaterThan(1); + }); + return result.current.items; } diff --git a/public/app/core/components/NestedFolderPicker/useFoldersQueryAppPlatform.ts b/public/app/core/components/NestedFolderPicker/useFoldersQueryAppPlatform.ts index 4828417c10c..b877c69aba0 100644 --- a/public/app/core/components/NestedFolderPicker/useFoldersQueryAppPlatform.ts +++ b/public/app/core/components/NestedFolderPicker/useFoldersQueryAppPlatform.ts @@ -2,7 +2,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { QueryStatus } from '@reduxjs/toolkit/query'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { folderAPIv1beta1 } from 'app/api/clients/folder/v1beta1'; +import { dashboardAPIv0alpha1 } from 'app/api/clients/dashboard/v0alpha1'; import { DashboardViewItemWithUIItems, DashboardsTreeItem } from 'app/features/browse-dashboards/types'; import { useDispatch, useSelector } from 'app/types/store'; @@ -12,7 +12,7 @@ import { getPaginationPlaceholders } from '../../../features/browse-dashboards/s import { getRootFolderItem } from './utils'; -type GetFolderChildrenQuery = ReturnType>; +type GetFolderChildrenQuery = ReturnType>; type GetFolderChildrenRequest = { unsubscribe: () => void; }; @@ -32,9 +32,9 @@ export function useFoldersQueryAppPlatform(isBrowsing: boolean, openFolders: Rec const requestsRef = useRef([]); // Keep a list of selectors for dynamic state selection - const [selectors, setSelectors] = useState< - Array> - >([]); + const [selectors, setSelectors] = useState>>( + [] + ); // This is an aggregated dynamic selector of all the selectors for all the request issued while loading the folder // tree and returns the whole tree that was loaded so far. @@ -50,7 +50,7 @@ export function useFoldersQueryAppPlatform(isBrowsing: boolean, openFolders: Rec isLoading = true; } - const parentName = response.originalArgs?.name; + const parentName = response.originalArgs?.folder; if (parentName) { responseByParent[parentName] = response; } @@ -77,13 +77,13 @@ export function useFoldersQueryAppPlatform(isBrowsing: boolean, openFolders: Rec return; } - const args = { name: finalParentUid }; + const args = { folder: finalParentUid, type: 'folder' }; // Make a request - const subscription = dispatch(folderAPIv1beta1.endpoints.getFolderChildren.initiate(args)); + const subscription = dispatch(dashboardAPIv0alpha1.endpoints.getSearch.initiate(args)); // Add selector for the response to the list so we can then have an aggregated selector for all the folders - const selector = folderAPIv1beta1.endpoints.getFolderChildren.select(args); + const selector = dashboardAPIv0alpha1.endpoints.getSearch.select(args); setSelectors((selectors) => selectors.concat(selector)); // the subscriptions are saved in a ref so they can be unsubscribed on unmount @@ -113,18 +113,18 @@ export function useFoldersQueryAppPlatform(isBrowsing: boolean, openFolders: Rec response: GetFolderChildrenQuery | undefined, level: number ): Array> { - let folders = response?.data?.items ? [...response.data.items] : []; - folders.sort((a, b) => collator.compare(a.spec.title, b.spec.title)); + let folders = response?.data?.hits ? [...response.data.hits] : []; + folders.sort((a, b) => collator.compare(a.title, b.title)); const list = folders.flatMap((item) => { - const name = item.metadata.name!; + const name = item.name; const folderIsOpen = openFolders[name]; const flatItem: DashboardsTreeItem = { isOpen: Boolean(folderIsOpen), level: level, item: { kind: 'folder' as const, - title: item.spec.title, + title: item.title, // We use resource name as UID because well, not sure what metadata.uid would be used for now as you cannot // query by it. uid: name, diff --git a/public/app/core/reducers/root.ts b/public/app/core/reducers/root.ts index 67078fdbd27..bc296ee14b6 100644 --- a/public/app/core/reducers/root.ts +++ b/public/app/core/reducers/root.ts @@ -2,6 +2,7 @@ import { ReducersMapObject } from '@reduxjs/toolkit'; import { AnyAction, combineReducers } from 'redux'; import { alertingAPI as alertingPackageAPI } from '@grafana/alerting/unstable'; +import { dashboardAPIv0alpha1 } from 'app/api/clients/dashboard/v0alpha1'; import sharedReducers from 'app/core/reducers'; import ldapReducers from 'app/features/admin/state/reducers'; import alertingReducers from 'app/features/alerting/state/reducers'; @@ -71,6 +72,7 @@ const rootReducers = { [provisioningAPIv0alpha1.reducerPath]: provisioningAPIv0alpha1.reducer, [folderAPIv1beta1.reducerPath]: folderAPIv1beta1.reducer, [advisorAPIv0alpha1.reducerPath]: advisorAPIv0alpha1.reducer, + [dashboardAPIv0alpha1.reducerPath]: dashboardAPIv0alpha1.reducer, // PLOP_INJECT_REDUCER // Used by the API client generator }; diff --git a/public/app/features/browse-dashboards/BrowseDashboardsPage.test.tsx b/public/app/features/browse-dashboards/BrowseDashboardsPage.test.tsx index 4a2c9f4a82b..a9a0dda6274 100644 --- a/public/app/features/browse-dashboards/BrowseDashboardsPage.test.tsx +++ b/public/app/features/browse-dashboards/BrowseDashboardsPage.test.tsx @@ -1,7 +1,6 @@ import { render as rtlRender, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { HttpResponse, http } from 'msw'; -import { setupServer, SetupServer } from 'msw/node'; import { ComponentProps } from 'react'; import * as React from 'react'; import { useParams } from 'react-router-dom-v5-compat'; @@ -9,13 +8,16 @@ import AutoSizer from 'react-virtualized-auto-sizer'; import { TestProvider } from 'test/helpers/TestProvider'; import { selectors } from '@grafana/e2e-selectors'; +import server, { setupMockServer } from '@grafana/test-utils/server'; +import { getFolderFixtures } from '@grafana/test-utils/unstable'; import { contextSrv } from 'app/core/core'; import { backendSrv } from 'app/core/services/backend_srv'; import BrowseDashboardsPage from './BrowseDashboardsPage'; -import { wellFormedTree } from './fixtures/dashboardsTreeItem.fixture'; import * as permissions from './permissions'; -const [mockTree, { dashbdD, folderA, folderA_folderA }] = wellFormedTree(); + +setupMockServer(); +const [mockTree, { dashbdD, folderA, folderA_folderA }] = getFolderFixtures(); jest.mock('@grafana/runtime', () => ({ ...jest.requireActual('@grafana/runtime'), @@ -111,7 +113,6 @@ jest.mock('app/features/browse-dashboards/api/services', () => { }); describe('browse-dashboards BrowseDashboardsPage', () => { - let server: SetupServer; const mockPermissions = { canCreateDashboards: true, canEditDashboards: true, @@ -123,33 +124,14 @@ describe('browse-dashboards BrowseDashboardsPage', () => { canDeleteDashboards: true, }; - beforeAll(() => { - server = setupServer( - http.get('/api/folders/:uid', () => { - return HttpResponse.json({ - title: folderA.item.title, - uid: folderA.item.uid, - }); - }), - http.get('/api/search', () => { - return HttpResponse.json({}); - }), + beforeEach(() => { + server.use( http.get('/api/search/sorting', () => { return HttpResponse.json({ sortOptions: [], }); - }), - http.get('/apis/provisioning.grafana.app/v0alpha1/namespaces/default/settings', () => { - return HttpResponse.json({ - items: [], - }); }) ); - server.listen(); - }); - - afterAll(() => { - server.close(); }); beforeEach(() => { @@ -170,7 +152,6 @@ describe('browse-dashboards BrowseDashboardsPage', () => { canDeleteDashboards: true, }); jest.restoreAllMocks(); - server.resetHandlers(); }); describe('at the root level', () => { diff --git a/public/app/features/browse-dashboards/BrowseFolderLibraryPanelsPage.test.tsx b/public/app/features/browse-dashboards/BrowseFolderLibraryPanelsPage.test.tsx index c60a8a8de56..9b96316add6 100644 --- a/public/app/features/browse-dashboards/BrowseFolderLibraryPanelsPage.test.tsx +++ b/public/app/features/browse-dashboards/BrowseFolderLibraryPanelsPage.test.tsx @@ -1,9 +1,9 @@ -import { render as rtlRender, screen } from '@testing-library/react'; import { http, HttpResponse } from 'msw'; -import { SetupServer, setupServer } from 'msw/node'; import { useParams } from 'react-router-dom-v5-compat'; -import { TestProvider } from 'test/helpers/TestProvider'; +import { render, screen } from 'test/test-utils'; +import server, { setupMockServer } from '@grafana/test-utils/server'; +import { getFolderFixtures } from '@grafana/test-utils/unstable'; import { contextSrv } from 'app/core/core'; import { backendSrv } from 'app/core/services/backend_srv'; @@ -11,10 +11,7 @@ import BrowseFolderLibraryPanelsPage from './BrowseFolderLibraryPanelsPage'; import { getLibraryElementsResponse } from './fixtures/libraryElements.fixture'; import * as permissions from './permissions'; -function render(...[ui, options]: Parameters) { - rtlRender({ui}, options); -} - +setupMockServer(); jest.mock('@grafana/runtime', () => ({ ...jest.requireActual('@grafana/runtime'), getBackendSrv: () => backendSrv, @@ -28,15 +25,15 @@ jest.mock('react-router-dom-v5-compat', () => ({ useParams: jest.fn(), })); -const mockFolderName = 'myFolder'; -const mockFolderUid = '12345'; +const [_, { folderA }] = getFolderFixtures(); +const mockFolderName = folderA.item.title; +const mockFolderUid = folderA.item.uid; const mockLibraryElementsResponse = getLibraryElementsResponse(1, { folderUid: mockFolderUid, }); describe('browse-dashboards BrowseFolderLibraryPanelsPage', () => { (useParams as jest.Mock).mockReturnValue({ uid: mockFolderUid }); - let server: SetupServer; const mockPermissions = { canCreateDashboards: true, canEditDashboards: true, @@ -48,14 +45,8 @@ describe('browse-dashboards BrowseFolderLibraryPanelsPage', () => { canDeleteDashboards: true, }; - beforeAll(() => { - server = setupServer( - http.get('/api/folders/:uid', () => { - return HttpResponse.json({ - title: mockFolderName, - uid: mockFolderUid, - }); - }), + beforeEach(() => { + server.use( http.get('/api/library-elements', () => { return HttpResponse.json({ result: mockLibraryElementsResponse, @@ -65,11 +56,6 @@ describe('browse-dashboards BrowseFolderLibraryPanelsPage', () => { return HttpResponse.json({}); }) ); - server.listen(); - }); - - afterAll(() => { - server.close(); }); beforeEach(() => { @@ -79,7 +65,6 @@ describe('browse-dashboards BrowseFolderLibraryPanelsPage', () => { afterEach(() => { jest.restoreAllMocks(); - server.resetHandlers(); }); it('displays the folder title', async () => { diff --git a/public/app/features/browse-dashboards/components/BrowseActions/MoveModal.test.tsx b/public/app/features/browse-dashboards/components/BrowseActions/MoveModal.test.tsx index fb1a160d8b1..c941cd76150 100644 --- a/public/app/features/browse-dashboards/components/BrowseActions/MoveModal.test.tsx +++ b/public/app/features/browse-dashboards/components/BrowseActions/MoveModal.test.tsx @@ -1,38 +1,26 @@ -import userEvent from '@testing-library/user-event'; import { HttpResponse, http } from 'msw'; -import { SetupServer, setupServer } from 'msw/node'; import { render, screen } from 'test/test-utils'; +import { setBackendSrv } from '@grafana/runtime'; +import server, { setupMockServer } from '@grafana/test-utils/server'; +import { getFolderFixtures } from '@grafana/test-utils/unstable'; import { backendSrv } from 'app/core/services/backend_srv'; -import { treeViewersCanEdit, wellFormedTree } from '../../fixtures/dashboardsTreeItem.fixture'; - import { MoveModal, Props } from './MoveModal'; -const [mockTree, { folderA }] = wellFormedTree(); -const [mockTreeThatViewersCanEdit /* shares folders with wellFormedTree */] = treeViewersCanEdit(); +const [_, { folderA }] = getFolderFixtures(); -jest.mock('@grafana/runtime', () => ({ - ...jest.requireActual('@grafana/runtime'), - getBackendSrv: () => backendSrv, -})); +setBackendSrv(backendSrv); +setupMockServer(); describe('browse-dashboards MoveModal', () => { const mockOnDismiss = jest.fn(); const mockOnConfirm = jest.fn(); let props: Props; - let server: SetupServer; window.HTMLElement.prototype.scrollIntoView = () => {}; - beforeAll(() => { - server = setupServer( - http.get('/api/folders/:uid', () => { - return HttpResponse.json({ - title: folderA.item.title, - uid: folderA.item.uid, - }); - }), - + beforeEach(() => { + server.use( http.get('/api/folders/:uid/counts', () => { return HttpResponse.json({ folder: 1, @@ -40,43 +28,9 @@ describe('browse-dashboards MoveModal', () => { librarypanel: 3, alertrule: 4, }); - }), - - http.get('/apis/provisioning.grafana.app/v0alpha1/namespaces/default/settings', () => { - return HttpResponse.json({ - items: [], - }); - }), - - http.get('/api/folders', ({ request }) => { - const url = new URL(request.url); - const parentUid = url.searchParams.get('parentUid') ?? undefined; - const permission = url.searchParams.get('permission'); - - const limit = parseInt(url.searchParams.get('limit') ?? '1000', 10); - const page = parseInt(url.searchParams.get('page') ?? '1', 10); - - const tree = permission === 'Edit' ? mockTreeThatViewersCanEdit : mockTree; - - // reconstruct a folder API response from the flat tree fixture - const folders = tree - .filter((v) => v.item.kind === 'folder' && v.item.parentUID === parentUid) - .map((folder) => { - return { - uid: folder.item.uid, - title: folder.item.kind === 'folder' ? folder.item.title : "invalid - this shouldn't happen", - }; - }) - .slice(limit * (page - 1), limit * page); - - return HttpResponse.json(folders); }) ); - server.listen(); - }); - - beforeEach(() => { props = { isOpen: true, onConfirm: mockOnConfirm, @@ -90,10 +44,6 @@ describe('browse-dashboards MoveModal', () => { }; }); - afterAll(() => { - server.close(); - }); - it('renders a dialog with the correct title', async () => { render(); @@ -130,36 +80,36 @@ describe('browse-dashboards MoveModal', () => { }); it('enables the `Move` button once a folder is selected', async () => { - render(); + const { user } = render(); expect(await screen.findByRole('button', { name: 'Move' })).toBeDisabled(); // Open the picker and wait for children to load const folderPicker = await screen.findByRole('button', { name: 'Select folder' }); - await userEvent.click(folderPicker); + await user.click(folderPicker); await screen.findByLabelText(folderA.item.title); // Select the folder - await userEvent.click(screen.getByLabelText(folderA.item.title)); + await user.click(screen.getByLabelText(folderA.item.title)); const moveButton = await screen.findByRole('button', { name: 'Move' }); expect(moveButton).toBeEnabled(); - await userEvent.click(moveButton); + await user.click(moveButton); expect(mockOnConfirm).toHaveBeenCalledWith(folderA.item.uid); }); it('calls onDismiss when clicking the `Cancel` button', async () => { - render(); + const { user } = render(); - await userEvent.click(await screen.findByRole('button', { name: 'Cancel' })); + await user.click(await screen.findByRole('button', { name: 'Cancel' })); expect(mockOnDismiss).toHaveBeenCalled(); }); it('calls onDismiss when clicking the X', async () => { - render(); + const { user } = render(); - await userEvent.click(await screen.findByRole('button', { name: 'Close' })); + await user.click(await screen.findByRole('button', { name: 'Close' })); expect(mockOnDismiss).toHaveBeenCalled(); }); }); diff --git a/public/app/features/browse-dashboards/components/BrowseView.test.tsx b/public/app/features/browse-dashboards/components/BrowseView.test.tsx index 1a19d2b5b61..929f5bbf53c 100644 --- a/public/app/features/browse-dashboards/components/BrowseView.test.tsx +++ b/public/app/features/browse-dashboards/components/BrowseView.test.tsx @@ -3,14 +3,13 @@ import userEvent from '@testing-library/user-event'; import { TestProvider } from 'test/helpers/TestProvider'; import { selectors } from '@grafana/e2e-selectors'; +import { getFolderFixtures } from '@grafana/test-utils/unstable'; import { DashboardViewItem } from 'app/features/search/types'; -import { wellFormedTree } from '../fixtures/dashboardsTreeItem.fixture'; - import { BrowseView } from './BrowseView'; const [mockTree, { folderA, folderA_folderA, folderA_folderB, folderA_folderB_dashbdB, dashbdD, folderB_empty }] = - wellFormedTree(); + getFolderFixtures(); function render(...[ui, options]: Parameters) { rtlRender({ui}, options); diff --git a/public/app/features/browse-dashboards/fixtures/dashboardsTreeItem.fixture.ts b/public/app/features/browse-dashboards/fixtures/dashboardsTreeItem.fixture.ts index 4ac6515c726..7b5d17a2825 100644 --- a/public/app/features/browse-dashboards/fixtures/dashboardsTreeItem.fixture.ts +++ b/public/app/features/browse-dashboards/fixtures/dashboardsTreeItem.fixture.ts @@ -1,5 +1,6 @@ import { Chance } from 'chance'; +import { getFolderFixtures } from '@grafana/test-utils/unstable'; import { DashboardViewItem } from 'app/features/search/types'; import { DashboardsTreeItem, UIDashboardViewItem } from '../types'; @@ -74,7 +75,7 @@ export function sharedWithMeFolder(seed = 1): DashboardsTreeItem) { provisioningAPIv0alpha1.middleware, folderAPIv1beta1.middleware, advisorAPIv0alpha1.middleware, + dashboardAPIv0alpha1.middleware, // PLOP_INJECT_MIDDLEWARE // Used by the API client generator ...extraMiddleware diff --git a/scripts/generate-rtk-apis.ts b/scripts/generate-rtk-apis.ts index 792594a91e1..2082e222156 100644 --- a/scripts/generate-rtk-apis.ts +++ b/scripts/generate-rtk-apis.ts @@ -79,6 +79,17 @@ const config: ConfigFile = { filterEndpoints: ['listPlaylist', 'getPlaylist', 'createPlaylist', 'deletePlaylist', 'replacePlaylist'], tag: true, }, + '../public/app/api/clients/dashboard/v0alpha1/endpoints.gen.ts': { + apiFile: '../public/app/api/clients/dashboard/v0alpha1/baseAPI.ts', + schemaFile: '../data/openapi/dashboard.grafana.app-v0alpha1.json', + filterEndpoints: [ + // Do not use any other endpoints from this version + // If other endpoints are required, they must be used from a newer version of the dashboard API + 'getSearch', + ], + tag: true, + }, + // PLOP_INJECT_API_CLIENT - Used by the API client generator }, }; From 491c74b6886f9dc57b48fdcf3423b7bf9f13b539 Mon Sep 17 00:00:00 2001 From: Matheus Macabu Date: Fri, 1 Aug 2025 14:45:44 +0200 Subject: [PATCH 21/89] Secrets: Add inline secure value delete when owned method (#108993) --- .../secret/service/inline_secure_value.go | 37 +++- .../service/inline_secure_value_test.go | 163 ++++++++++++++++++ 2 files changed, 199 insertions(+), 1 deletion(-) diff --git a/pkg/registry/apis/secret/service/inline_secure_value.go b/pkg/registry/apis/secret/service/inline_secure_value.go index 9e0cb9fce41..665bc622f54 100644 --- a/pkg/registry/apis/secret/service/inline_secure_value.go +++ b/pkg/registry/apis/secret/service/inline_secure_value.go @@ -217,5 +217,40 @@ func (s *inlineSecureValueService) CreateInline(ctx context.Context, owner commo } func (s *inlineSecureValueService) DeleteWhenOwnedByResource(ctx context.Context, owner common.ObjectReference, name string) error { - return fmt.Errorf("not implemented yet") + ctx, span := s.tracer.Start(ctx, "InlineSecureValueService.DeleteWhenOwnedByResource", trace.WithAttributes( + attribute.String("owner.namespace", owner.Namespace), + attribute.String("owner.apiGroup", owner.APIGroup), + attribute.String("owner.apiVersion", owner.APIVersion), + attribute.String("owner.kind", owner.Kind), + attribute.String("owner.name", owner.Name), + attribute.String("secureValue.name", name), + )) + defer span.End() + + authInfo, ok := authlib.AuthInfoFrom(ctx) + if !ok { + return fmt.Errorf("missing auth info in context") + } + + if owner.Namespace == "" || !authlib.NamespaceMatches(authInfo.GetNamespace(), owner.Namespace) { + return fmt.Errorf("owner namespace %s does not match auth info namespace %s", owner.Namespace, authInfo.GetNamespace()) + } + + if owner.APIGroup == "" || owner.APIVersion == "" || owner.Kind == "" || owner.Name == "" { + return fmt.Errorf("owner reference must have a valid API group, API version, kind and name") + } + + owned, err := s.isSecureValueOwnedByResource(ctx, owner, name) + if err != nil { + return fmt.Errorf("error checking if secure value %s is owned by %v: %w", name, owner, err) + } + + if owned { + if _, err := s.secureValueService.Delete(ctx, xkube.Namespace(owner.Namespace), name); err != nil { + return fmt.Errorf("error deleting secure value %s for owner %v: %w", name, owner, err) + } + } + + // if it is not owned, this is a no-op + return nil } diff --git a/pkg/registry/apis/secret/service/inline_secure_value_test.go b/pkg/registry/apis/secret/service/inline_secure_value_test.go index d108ce8f047..3c8742bffb3 100644 --- a/pkg/registry/apis/secret/service/inline_secure_value_test.go +++ b/pkg/registry/apis/secret/service/inline_secure_value_test.go @@ -5,8 +5,10 @@ import ( common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/identity" + "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/registry/apis/secret/service" "github.com/grafana/grafana/pkg/registry/apis/secret/testutils" + "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -347,3 +349,164 @@ func TestIntegration_InlineSecureValue_CreateInline(t *testing.T) { require.Error(t, err) }) } + +func TestIntegration_InlineSecureValue_DeleteWhenOwnedByResource(t *testing.T) { + t.Parallel() + + tracer := noop.NewTracerProvider().Tracer("test") + + defaultNs := "org-1234" + owner := common.ObjectReference{ + APIGroup: "prometheus.datasource.grafana.app", + APIVersion: "v1alpha1", + Kind: "DataSourceConfig", + Name: "test-datasource", + Namespace: defaultNs, + } + + t.Run("happy path deletes an owned secure value", func(t *testing.T) { + t.Parallel() + + tu := testutils.Setup(t) + + sv1 := "test-secure-value-1" + createdSv1, err := tu.CreateSv(t.Context(), func(cfg *testutils.CreateSvConfig) { + cfg.Sv.Name = sv1 + cfg.Sv.Namespace = defaultNs + cfg.Sv.OwnerReferences = []metav1.OwnerReference{owner.ToOwnerReference()} + }) + require.NoError(t, err) + require.NotNil(t, createdSv1) + + svc := service.ProvideInlineSecureValueService(tracer, tu.SecureValueService, nil) + + ctx := testutils.CreateServiceAuthContext(t.Context(), "", defaultNs, nil) + + err = svc.DeleteWhenOwnedByResource(ctx, owner, sv1) + require.NoError(t, err) + + // make sure it got deleted + sv, err := tu.SecureValueService.Read(ctx, xkube.Namespace(owner.Namespace), sv1) + require.ErrorIs(t, err, contracts.ErrSecureValueNotFound) + require.Nil(t, sv) + }) + + t.Run("when the auth info is missing it returns an error", func(t *testing.T) { + t.Parallel() + + svc := service.ProvideInlineSecureValueService(tracer, nil, nil) + err := svc.DeleteWhenOwnedByResource(t.Context(), common.ObjectReference{}, "") + require.Error(t, err) + }) + + t.Run("when the owner namespace does not match auth info namespace it returns an error", func(t *testing.T) { + t.Parallel() + + svc := service.ProvideInlineSecureValueService(tracer, nil, nil) + + reqNs := "org-2345" + ctx := testutils.CreateUserAuthContext(t.Context(), reqNs, map[string][]string{}) + + err := svc.DeleteWhenOwnedByResource(ctx, owner, "") + require.Error(t, err) + }) + + t.Run("when the owner namespace is empty it returns an error", func(t *testing.T) { + t.Parallel() + + svc := service.ProvideInlineSecureValueService(tracer, nil, nil) + + ctx := testutils.CreateUserAuthContext(t.Context(), defaultNs, map[string][]string{}) + + err := svc.DeleteWhenOwnedByResource(ctx, common.ObjectReference{}, "") + require.Error(t, err) + }) + + t.Run("when the owner reference has empty fields it returns an error", func(t *testing.T) { + t.Parallel() + + svc := service.ProvideInlineSecureValueService(tracer, nil, nil) + + owner := common.ObjectReference{ + Namespace: defaultNs, + } + + createAuthCtx := testutils.CreateOBOAuthContext(t.Context(), "service-identity", defaultNs, nil, nil) + + require.Error(t, svc.DeleteWhenOwnedByResource(createAuthCtx, owner, "")) + + owner.APIGroup = "prometheus.datasource.grafana.app" + require.Error(t, svc.DeleteWhenOwnedByResource(createAuthCtx, owner, "")) + + owner.APIVersion = "v1alpha1" + require.Error(t, svc.DeleteWhenOwnedByResource(createAuthCtx, owner, "")) + + owner.Kind = "DataSourceConfig" + require.Error(t, svc.DeleteWhenOwnedByResource(createAuthCtx, owner, "")) + owner.Kind = "" + + owner.Name = "test-datasource" + require.Error(t, svc.DeleteWhenOwnedByResource(createAuthCtx, owner, "")) + }) + + t.Run("when the secure value exists but the owner does not match, it returns an error", func(t *testing.T) { + t.Parallel() + + tu := testutils.Setup(t) + + sv1 := "test-secure-value-1" + createdSv1, err := tu.CreateSv(t.Context(), func(cfg *testutils.CreateSvConfig) { + cfg.Sv.Name = sv1 + cfg.Sv.Namespace = defaultNs + cfg.Sv.OwnerReferences = []metav1.OwnerReference{ + { + APIVersion: "another.example.com/v0alpha1", + Kind: "another-kind", + Name: "another-name", + }, + } + }) + require.NoError(t, err) + require.NotNil(t, createdSv1) + + svc := service.ProvideInlineSecureValueService(tracer, tu.SecureValueService, nil) + + ctx := testutils.CreateServiceAuthContext(t.Context(), "", defaultNs, nil) + + err = svc.DeleteWhenOwnedByResource(ctx, owner, sv1) + require.Error(t, err) + + // make sure it still exists + sv, err := tu.SecureValueService.Read(ctx, xkube.Namespace(owner.Namespace), sv1) + require.NoError(t, err) + require.NotNil(t, sv) + require.Equal(t, sv1, sv.GetName()) + }) + + t.Run("when the secure value exists but it is shared (no owner), it does not return an error (noop)", func(t *testing.T) { + t.Parallel() + + tu := testutils.Setup(t) + + sv1 := "test-secure-value-1" + createdSv1, err := tu.CreateSv(t.Context(), func(cfg *testutils.CreateSvConfig) { + cfg.Sv.Name = sv1 + cfg.Sv.Namespace = defaultNs + }) + require.NoError(t, err) + require.NotNil(t, createdSv1) + + svc := service.ProvideInlineSecureValueService(tracer, tu.SecureValueService, nil) + + ctx := testutils.CreateServiceAuthContext(t.Context(), "", defaultNs, nil) + + err = svc.DeleteWhenOwnedByResource(ctx, owner, sv1) + require.NoError(t, err) + + // make sure it still exists + sv, err := tu.SecureValueService.Read(ctx, xkube.Namespace(owner.Namespace), sv1) + require.NoError(t, err) + require.NotNil(t, sv) + require.Equal(t, sv1, sv.GetName()) + }) +} From 7b5288c28ac89523c68cfc5d8c521754aea8af21 Mon Sep 17 00:00:00 2001 From: Gareth Date: Fri, 1 Aug 2025 13:56:31 +0100 Subject: [PATCH 22/89] Fix: Preserve Jaeger base path when constructing search request (#109045) * fix url construction * consistency * update error response * error source * add test case --- pkg/tsdb/jaeger/client.go | 12 ++++++++---- pkg/tsdb/jaeger/client_test.go | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/pkg/tsdb/jaeger/client.go b/pkg/tsdb/jaeger/client.go index 653c0463892..d858aa48f56 100644 --- a/pkg/tsdb/jaeger/client.go +++ b/pkg/tsdb/jaeger/client.go @@ -115,11 +115,15 @@ func (j *JaegerClient) Operations(s string) ([]string, error) { } func (j *JaegerClient) Search(query *JaegerQuery, start, end int64) ([]TraceResponse, error) { - jaegerURL, err := url.Parse(j.url) + u, err := url.JoinPath(j.url, "/api/traces") if err != nil { - return []TraceResponse{}, fmt.Errorf("failed to parse Jaeger URL: %w", err) + return []TraceResponse{}, backend.DownstreamError(fmt.Errorf("failed to join url path: %w", err)) + } + + jaegerURL, err := url.Parse(u) + if err != nil { + return []TraceResponse{}, backend.DownstreamError(fmt.Errorf("failed to parse Jaeger URL: %w", err)) } - jaegerURL.Path = "/api/traces" var queryTags string if query.Tags != "" { @@ -135,7 +139,7 @@ func (j *JaegerClient) Search(query *JaegerQuery, start, end int64) ([]TraceResp marshaledTags, err := json.Marshal(tagMap) if err != nil { - return []TraceResponse{}, fmt.Errorf("failed to convert tags to JSON: %w", err) + return []TraceResponse{}, backend.DownstreamError(fmt.Errorf("failed to convert tags to JSON: %w", err)) } queryTags = string(marshaledTags) diff --git a/pkg/tsdb/jaeger/client_test.go b/pkg/tsdb/jaeger/client_test.go index afabdc4bccc..eceb103ab82 100644 --- a/pkg/tsdb/jaeger/client_test.go +++ b/pkg/tsdb/jaeger/client_test.go @@ -186,6 +186,19 @@ func TestJaegerClient_Search(t *testing.T) { expectError bool expectedError error }{ + { + name: "Preserves base path in Jaeger URL", + query: &JaegerQuery{ + Service: "test-service", + }, + start: 1735689600000000, + end: 1738368000000000, + mockResponse: `{"data":[{"traceID":"test-trace-id"}]}`, + mockStatusCode: http.StatusOK, + expectedURL: "/abc/api/traces?end=1738368000000000&service=test-service&start=1735689600000000", + expectError: false, + expectedError: nil, + }, { name: "Successful search with all parameters", query: &JaegerQuery{ @@ -245,6 +258,11 @@ func TestJaegerClient_Search(t *testing.T) { settings := backend.DataSourceInstanceSettings{ URL: server.URL, } + + if tt.name == "Preserves base path in Jaeger URL" { + settings.URL = server.URL + "/abc" + } + client, err := New(server.Client(), log.NewNullLogger(), settings) assert.NoError(t, err) traces, err := client.Search(tt.query, tt.start, tt.end) From b1cdd45ca4b258a57ddb3a23266e501cc8704425 Mon Sep 17 00:00:00 2001 From: Konrad Lalik Date: Fri, 1 Aug 2025 15:36:46 +0200 Subject: [PATCH 23/89] Alerting: List V2 - datasource icons for rules (#109033) Add datasource icons to the rule list item components --- .../unified/rule-list/GrafanaRuleListItem.tsx | 1 + .../components/AlertRuleListItem.tsx | 72 +++++++++++++++++-- .../unified/rule-list/components/ListItem.tsx | 4 +- 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/public/app/features/alerting/unified/rule-list/GrafanaRuleListItem.tsx b/public/app/features/alerting/unified/rule-list/GrafanaRuleListItem.tsx index 5667069082b..ed90116bcaa 100644 --- a/public/app/features/alerting/unified/rule-list/GrafanaRuleListItem.tsx +++ b/public/app/features/alerting/unified/rule-list/GrafanaRuleListItem.tsx @@ -53,6 +53,7 @@ export function GrafanaRuleListItem({ isPaused: rule?.isPaused, application: 'grafana' as const, actions: , + querySourceUIDs: rule?.queriedDatasourceUIDs, }; if (prometheusRuleType.grafana.alertingRule(rule)) { diff --git a/public/app/features/alerting/unified/rule-list/components/AlertRuleListItem.tsx b/public/app/features/alerting/unified/rule-list/components/AlertRuleListItem.tsx index 5117a8516bd..2694bfc580d 100644 --- a/public/app/features/alerting/unified/rule-list/components/AlertRuleListItem.tsx +++ b/public/app/features/alerting/unified/rule-list/components/AlertRuleListItem.tsx @@ -1,8 +1,8 @@ -import { css } from '@emotion/css'; +import { css, cx } from '@emotion/css'; import pluralize from 'pluralize'; -import { ReactNode, useEffect, useId } from 'react'; +import { ReactNode, forwardRef, memo, useEffect, useId } from 'react'; -import { GrafanaTheme2 } from '@grafana/data'; +import { DataSourceInstanceSettings, GrafanaTheme2 } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; import { Alert, Stack, Text, TextLink, Tooltip, useStyles2 } from '@grafana/ui'; import { Rule, RuleGroupIdentifierV2, RuleHealth, RulesSourceIdentifier } from 'app/types/unified-alerting'; @@ -13,7 +13,7 @@ import { AlertLabels } from '../../components/AlertLabels'; import { MetaText } from '../../components/MetaText'; import { ProvisioningBadge } from '../../components/Provisioning'; import { PluginOriginBadge } from '../../plugins/PluginOriginBadge'; -import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource'; +import { GRAFANA_RULES_SOURCE_NAME, getDataSourceByUid } from '../../utils/datasource'; import { getGroupOriginName } from '../../utils/groupIdentifier'; import { labelsSize } from '../../utils/labels'; import { createContactPointSearchLink } from '../../utils/misc'; @@ -49,6 +49,7 @@ export interface AlertRuleListItemProps { operation?: RuleOperation; // the grouped view doesn't need to show the location again – it's redundant showLocation?: boolean; + querySourceUIDs?: string[]; } export const AlertRuleListItem = (props: AlertRuleListItemProps) => { @@ -75,6 +76,7 @@ export const AlertRuleListItem = (props: AlertRuleListItemProps) => { actions = null, operation, showLocation = true, + querySourceUIDs = [], } = props; const listItemAriaId = useId(); @@ -94,6 +96,10 @@ export const AlertRuleListItem = (props: AlertRuleListItemProps) => { ); } + if (querySourceUIDs.length > 0) { + metadata.push(); + } + if (!isPaused) { if (lastEvaluation && evaluationInterval) { metadata.push( @@ -179,6 +185,7 @@ export function RecordingRuleListItem({ origin, actions, showLocation = true, + querySourceUIDs = [], }: RecordingRuleListItemProps) { const metadata: ReactNode[] = []; if (namespace && group && showLocation) { @@ -195,6 +202,10 @@ export function RecordingRuleListItem({ ); } + if (querySourceUIDs.length > 0) { + metadata.push(); + } + return ( ds !== undefined); + + return ( + + {dataSources.map((dataSource) => { + return ( + + + + ); + })} + + ); +}); + function RuleLabels({ labels }: { labels: Labels }) { const styles = useStyles2(getStyles); @@ -417,3 +451,33 @@ export type RuleListItemCommonProps = Pick< AlertRuleListItemProps, Extract >; + +interface DataSourceLogoProps { + dataSource: DataSourceInstanceSettings; +} + +const DataSourceLogo = forwardRef(({ dataSource }, ref) => { + const styles = useStyles2(dataSourceLogoStyles); + + return ( + {`${dataSource.meta.name} + ); +}); + +const dataSourceLogoStyles = (theme: GrafanaTheme2) => ({ + logo: css({ + height: '14px', + width: '14px', + borderRadius: theme.shape.radius.default, + }), + filter: css({ + filter: `invert(${theme.isLight ? 1 : 0})`, + }), +}); diff --git a/public/app/features/alerting/unified/rule-list/components/ListItem.tsx b/public/app/features/alerting/unified/rule-list/components/ListItem.tsx index ce3ea7f6fb6..0e15e5fb696 100644 --- a/public/app/features/alerting/unified/rule-list/components/ListItem.tsx +++ b/public/app/features/alerting/unified/rule-list/components/ListItem.tsx @@ -39,7 +39,7 @@ export const ListItem = (props: ListItemProps) => { {/* metadata */} - + {meta?.map((item, index) => ( {index > 0 && } @@ -72,7 +72,7 @@ export const SkeletonListItem = () => { const Separator = () => ( - {'·'} + {'|'} ); From 772f647210cfe3c4ac95002e21888db9c0ed9f5d Mon Sep 17 00:00:00 2001 From: Serge Zaitsev Date: Fri, 1 Aug 2025 16:01:13 +0200 Subject: [PATCH 24/89] Chore: Use proper database type from env in testinfra integration tests (#108845) use database type from env in testinfra --- pkg/services/sqlstore/sqlutil/sqlutil.go | 15 ++++++++++ .../apis/provisioning/provisioning_test.go | 29 ++++++++++++------- pkg/tests/testinfra/testinfra.go | 15 ++++++++++ 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/pkg/services/sqlstore/sqlutil/sqlutil.go b/pkg/services/sqlstore/sqlutil/sqlutil.go index 8506acdab79..7d3d09a5ff3 100644 --- a/pkg/services/sqlstore/sqlutil/sqlutil.go +++ b/pkg/services/sqlstore/sqlutil/sqlutil.go @@ -22,6 +22,11 @@ type TestDB struct { DriverName string ConnStr string Path string + Host string + Port string + User string + Password string + Database string Cleanup func() } @@ -132,6 +137,11 @@ func mySQLTestDB() (*TestDB, error) { return &TestDB{ DriverName: "mysql", ConnStr: conn_str, + Host: host, + Port: port, + User: "grafana", + Password: "password", + Database: "grafana_tests", Cleanup: func() {}, }, nil } @@ -149,6 +159,11 @@ func postgresTestDB() (*TestDB, error) { return &TestDB{ DriverName: "postgres", ConnStr: connStr, + Host: host, + Port: port, + User: "grafanatest", + Password: "grafanatest", + Database: "grafanatest", Cleanup: func() {}, }, nil } diff --git a/pkg/tests/apis/provisioning/provisioning_test.go b/pkg/tests/apis/provisioning/provisioning_test.go index e04406787fe..f9a5c40a14e 100644 --- a/pkg/tests/apis/provisioning/provisioning_test.go +++ b/pkg/tests/apis/provisioning/provisioning_test.go @@ -161,14 +161,21 @@ func TestIntegrationProvisioning_CreatingAndGetting(t *testing.T) { // Viewer can see settings listing t.Run("viewer has access to list", func(t *testing.T) { settings := &provisioning.RepositoryViewList{} - rsp := helper.ViewerREST.Get(). - Namespace("default"). - Suffix("settings"). - Do(context.Background()) - require.NoError(t, rsp.Error()) - err := rsp.Into(settings) - require.NoError(t, err) - require.Len(t, settings.Items, len(inputFiles)) + // Wait for unified storage to make the data available + require.Eventually(t, func() bool { + rsp := helper.ViewerREST.Get(). + Namespace("default"). + Suffix("settings"). + Do(context.Background()) + if rsp.Error() != nil { + return false + } + err := rsp.Into(settings) + if err != nil { + return false + } + return len(settings.Items) == len(inputFiles) + }, time.Second*10, time.Millisecond*100, "Expected settings to have len(inputFiles) items") // FIXME: this should be an enterprise integration test if extensions.IsEnterprise { @@ -1825,8 +1832,10 @@ func TestIntegrationProvisioning_MoveResources(t *testing.T) { // Verify dashboard still exists in Grafana with same content but may have updated path references helper.SyncAndWait(t, repo, nil) - _, err = helper.DashboardsV1.Resource.Get(ctx, allPanelsUID, metav1.GetOptions{}) - require.NoError(t, err, "dashboard should still exist in Grafana after move") + require.Eventually(t, func() bool { + _, err = helper.DashboardsV1.Resource.Get(ctx, allPanelsUID, metav1.GetOptions{}) + return err == nil + }, 10*time.Second, 100*time.Millisecond, "dashboard should still exist in Grafana after move") // Using Eventually to account for potential delays in dashboards APIs. }) t.Run("move file to nested path without ref", func(t *testing.T) { diff --git a/pkg/tests/testinfra/testinfra.go b/pkg/tests/testinfra/testinfra.go index eb9b460c6b8..56f9f3000e2 100644 --- a/pkg/tests/testinfra/testinfra.go +++ b/pkg/tests/testinfra/testinfra.go @@ -13,6 +13,7 @@ import ( "time" "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/services/sqlstore/sqlutil" "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -85,6 +86,20 @@ func StartGrafanaEnv(t *testing.T, grafDir, cfgPath string) (string, *server.Tes err = featuremgmt.InitOpenFeatureWithCfg(cfg) require.NoError(t, err) + + // Use proper database type based on the environment variable GRAFANA_TEST_DB in tests + testDB, err := sqlutil.GetTestDB(sqlutil.GetTestDBType()) + require.NoError(t, err) + t.Cleanup(testDB.Cleanup) + + dbCfg := cfg.Raw.Section("database") + dbCfg.Key("type").SetValue(testDB.DriverName) + dbCfg.Key("host").SetValue(testDB.Host) + dbCfg.Key("port").SetValue(testDB.Port) + dbCfg.Key("user").SetValue(testDB.User) + dbCfg.Key("password").SetValue(testDB.Password) + dbCfg.Key("name").SetValue(testDB.Database) + env, err := server.InitializeForTest(t, t, cfg, serverOpts, apiServerOpts) require.NoError(t, err) From 1831953f7fd114c1db235fe35b87986f17def271 Mon Sep 17 00:00:00 2001 From: Todd Treece <360020+toddtreece@users.noreply.github.com> Date: Fri, 1 Aug 2025 10:02:01 -0400 Subject: [PATCH 25/89] K8s: Add API Enablement for apps (#109019) --- pkg/registry/apps/playlist/register.go | 8 ----- .../apiserver/appinstaller/installer.go | 19 +++++------ .../apiserver/appinstaller/resourceconfig.go | 32 +++++++++++++++++++ pkg/services/apiserver/appinstaller/server.go | 8 +++++ pkg/services/apiserver/config.go | 7 ++++ pkg/services/apiserver/options/options.go | 3 ++ pkg/services/apiserver/service.go | 9 ++++++ 7 files changed, 67 insertions(+), 19 deletions(-) create mode 100644 pkg/services/apiserver/appinstaller/resourceconfig.go diff --git a/pkg/registry/apps/playlist/register.go b/pkg/registry/apps/playlist/register.go index 4374c0265dd..123974c2dcc 100644 --- a/pkg/registry/apps/playlist/register.go +++ b/pkg/registry/apps/playlist/register.go @@ -26,7 +26,6 @@ import ( var ( _ appsdkapiserver.AppInstaller = (*PlaylistAppInstaller)(nil) _ appinstaller.LegacyStorageProvider = (*PlaylistAppInstaller)(nil) - _ appinstaller.APIEnablementProvider = (*PlaylistAppInstaller)(nil) ) type PlaylistAppInstaller struct { @@ -102,10 +101,3 @@ func (p *PlaylistAppInstaller) GetLegacyStorage(requested schema.GroupVersionRes ) return legacyStore } - -// GetAllowedV0Alpha1Resources returns the list of resources that are allowed to be accessed in v0alpha1. -func (p *PlaylistAppInstaller) GetAllowedV0Alpha1Resources() []string { - return []string{ - playlistv0alpha1.PlaylistKind().Plural(), - } -} diff --git a/pkg/services/apiserver/appinstaller/installer.go b/pkg/services/apiserver/appinstaller/installer.go index fb5427b761f..9817f7513bc 100644 --- a/pkg/services/apiserver/appinstaller/installer.go +++ b/pkg/services/apiserver/appinstaller/installer.go @@ -8,17 +8,19 @@ import ( appsdkapiserver "github.com/grafana/grafana-app-sdk/k8s/apiserver" "github.com/grafana/grafana-app-sdk/logging" - grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" - "github.com/grafana/grafana/pkg/services/apiserver/builder" - "github.com/grafana/grafana/pkg/services/apiserver/endpoints/request" - grafanaapiserveroptions "github.com/grafana/grafana/pkg/services/apiserver/options" "github.com/grafana/grafana/pkg/storage/legacysql/dualwrite" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/registry/generic" genericapiserver "k8s.io/apiserver/pkg/server" + serverstore "k8s.io/apiserver/pkg/server/storage" "k8s.io/kube-openapi/pkg/common" + + grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" + "github.com/grafana/grafana/pkg/services/apiserver/builder" + "github.com/grafana/grafana/pkg/services/apiserver/endpoints/request" + grafanaapiserveroptions "github.com/grafana/grafana/pkg/services/apiserver/options" ) type LegacyStorageGetterFunc func(schema.GroupVersionResource) grafanarest.Storage @@ -31,13 +33,6 @@ type AuthorizerProvider interface { GetAuthorizer() authorizer.Authorizer } -type APIEnablementProvider interface { - // Do not implement this unless you have special circumstances! This is a list of resources that are allowed to be accessed in v0alpha1, - // to prevent accidental exposure of experimental APIs. While developing, use the feature flag `grafanaAPIServerWithExperimentalAPIs`. - // And then, when you're ready to expose this to the end user, go to v1beta1 instead. - GetAllowedV0Alpha1Resources() []string -} - type AppInstallerConfig struct { CustomConfig any AllowedV0Alpha1Resources []string @@ -132,6 +127,7 @@ func InstallAPIs( dualWriteService dualwrite.Service, dualWriterMetrics *grafanarest.DualWriterMetrics, builderMetrics *builder.BuilderMetrics, + apiResourceConfig *serverstore.ResourceConfig, ) error { logger := logging.FromContext(ctx) for _, installer := range appInstallers { @@ -148,6 +144,7 @@ func InstallAPIs( dualWriteService: dualWriteService, dualWriterMetrics: dualWriterMetrics, builderMetrics: builderMetrics, + apiResourceConfig: apiResourceConfig, } if err := installer.InstallAPIs(wrapper, restOpsGetter); err != nil { return fmt.Errorf("failed to install APIs for app %s: %w", installer.ManifestData().AppName, err) diff --git a/pkg/services/apiserver/appinstaller/resourceconfig.go b/pkg/services/apiserver/appinstaller/resourceconfig.go new file mode 100644 index 00000000000..c2e45eb74e9 --- /dev/null +++ b/pkg/services/apiserver/appinstaller/resourceconfig.go @@ -0,0 +1,32 @@ +package appinstaller + +import ( + appsdkapiserver "github.com/grafana/grafana-app-sdk/k8s/apiserver" + "k8s.io/apimachinery/pkg/runtime/schema" + serverstorage "k8s.io/apiserver/pkg/server/storage" +) + +func NewAPIResourceConfig(installers []appsdkapiserver.AppInstaller) *serverstorage.ResourceConfig { + ret := serverstorage.NewResourceConfig() + enable := []schema.GroupVersion{} + disable := []schema.GroupVersion{} + + for _, installer := range installers { + for _, version := range installer.ManifestData().Versions { + gv := schema.GroupVersion{ + Group: installer.ManifestData().Group, + Version: version.Name, + } + if version.Served { + enable = append(enable, gv) + } else { + disable = append(disable, gv) + } + } + } + + ret.EnableVersions(enable...) + ret.DisableVersions(disable...) + + return ret +} diff --git a/pkg/services/apiserver/appinstaller/server.go b/pkg/services/apiserver/appinstaller/server.go index ea9b88e031e..20792eeab0d 100644 --- a/pkg/services/apiserver/appinstaller/server.go +++ b/pkg/services/apiserver/appinstaller/server.go @@ -10,6 +10,7 @@ import ( genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" genericrest "k8s.io/apiserver/pkg/registry/rest" genericapiserver "k8s.io/apiserver/pkg/server" + serverstorage "k8s.io/apiserver/pkg/server/storage" appsdkapiserver "github.com/grafana/grafana-app-sdk/k8s/apiserver" "github.com/grafana/grafana-app-sdk/logging" @@ -35,6 +36,7 @@ type serverWrapper struct { dualWriteService dualwrite.Service dualWriterMetrics *grafanarest.DualWriterMetrics builderMetrics *builder.BuilderMetrics + apiResourceConfig *serverstorage.ResourceConfig } func (s *serverWrapper) InstallAPIGroup(apiGroupInfo *genericapiserver.APIGroupInfo) error { @@ -50,6 +52,12 @@ func (s *serverWrapper) InstallAPIGroup(apiGroupInfo *genericapiserver.APIGroupI Group: s.installer.ManifestData().Group, Resource: resource, } + gvr := gr.WithVersion(v) + if s.apiResourceConfig != nil && !s.apiResourceConfig.ResourceEnabled(gvr) { + log.Debug("Skipping storage for disabled resource", "gvr", gvr.String(), "storagePath", storagePath) + delete(apiGroupInfo.VersionedResourcesStorageMap[v], storagePath) + continue + } storage := s.configureStorage(gr, dualWriteSupported, restStorage) if unifiedStorage, ok := storage.(grafanarest.Storage); ok && dualWriteSupported { log.Debug("Configuring dual writer for storage", "resource", gr.String(), "version", v, "storagePath", storagePath) diff --git a/pkg/services/apiserver/config.go b/pkg/services/apiserver/config.go index 8cf5789c777..dc2234e6e56 100644 --- a/pkg/services/apiserver/config.go +++ b/pkg/services/apiserver/config.go @@ -39,6 +39,13 @@ func applyGrafanaConfig(cfg *setting.Cfg, features featuremgmt.FeatureToggles, o apiserverCfg := cfg.SectionWithEnvOverrides("grafana-apiserver") + runtimeConfig := apiserverCfg.Key("runtime_config").String() + if runtimeConfig != "" { + if err := o.APIEnablementOptions.RuntimeConfig.Set(runtimeConfig); err != nil { + return fmt.Errorf("failed to set runtime config: %w", err) + } + } + o.RecommendedOptions.Etcd.StorageConfig.Transport.ServerList = apiserverCfg.Key("etcd_servers").Strings(",") o.RecommendedOptions.SecureServing.BindAddress = ip diff --git a/pkg/services/apiserver/options/options.go b/pkg/services/apiserver/options/options.go index a9209cdbc00..721f1ce570b 100644 --- a/pkg/services/apiserver/options/options.go +++ b/pkg/services/apiserver/options/options.go @@ -21,6 +21,7 @@ const defaultEtcdPathPrefix = "/registry/grafana.app" type Options struct { RecommendedOptions *genericoptions.RecommendedOptions + APIEnablementOptions *genericoptions.APIEnablementOptions GrafanaAggregatorOptions *GrafanaAggregatorOptions StorageOptions *StorageOptions ExtraOptions *ExtraOptions @@ -30,6 +31,7 @@ type Options struct { func NewOptions(codec runtime.Codec) *Options { return &Options{ RecommendedOptions: NewRecommendedOptions(codec), + APIEnablementOptions: genericoptions.NewAPIEnablementOptions(), GrafanaAggregatorOptions: NewGrafanaAggregatorOptions(), StorageOptions: NewStorageOptions(), ExtraOptions: NewExtraOptions(), @@ -38,6 +40,7 @@ func NewOptions(codec runtime.Codec) *Options { func (o *Options) AddFlags(fs *pflag.FlagSet) { o.RecommendedOptions.AddFlags(fs) + o.APIEnablementOptions.AddFlags(fs) o.GrafanaAggregatorOptions.AddFlags(fs) o.StorageOptions.AddFlags(fs) o.ExtraOptions.AddFlags(fs) diff --git a/pkg/services/apiserver/service.go b/pkg/services/apiserver/service.go index 58bf5ad4ac7..be580025823 100644 --- a/pkg/services/apiserver/service.go +++ b/pkg/services/apiserver/service.go @@ -304,11 +304,19 @@ func (s *service) start(ctx context.Context) error { return errs[0] } + if errs := o.APIEnablementOptions.Validate(s.scheme); len(errs) != 0 { + return errs[0] + } + serverConfig := genericapiserver.NewRecommendedConfig(s.codecs) if err := o.ApplyTo(serverConfig); err != nil { return err } + if err := o.APIEnablementOptions.ApplyTo(&serverConfig.Config, appinstaller.NewAPIResourceConfig(s.appInstallers), s.scheme); err != nil { + return err + } + serverConfig.Authorization.Authorizer = s.authorizer serverConfig.Authentication.Authenticator = authenticator.NewAuthenticator(serverConfig.Authentication.Authenticator) serverConfig.TracerProvider = s.tracing.GetTracerProvider() @@ -395,6 +403,7 @@ func (s *service) start(ctx context.Context) error { s.storageStatus, s.dualWriterMetrics, s.builderMetrics, + serverConfig.MergedResourceConfig, ); err != nil { return err } From cc63af204cbfcc5d7816195a15ada0904bab8e7d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 15:10:30 +0100 Subject: [PATCH 26/89] Update dependency babel-loader to v10 (#109047) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 92 ++++------------------------------------------------ 2 files changed, 8 insertions(+), 86 deletions(-) diff --git a/package.json b/package.json index 2728eafd9a0..6fdf6a22a28 100644 --- a/package.json +++ b/package.json @@ -167,7 +167,7 @@ "@typescript-eslint/eslint-plugin": "8.38.0", "@typescript-eslint/parser": "8.38.0", "autoprefixer": "10.4.21", - "babel-loader": "9.2.1", + "babel-loader": "10.0.0", "blob-polyfill": "9.0.20240710", "browserslist": "^4.21.4", "chance": "^1.1.13", diff --git a/yarn.lock b/yarn.lock index a78abcf6911..e09a9406eac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11817,16 +11817,15 @@ __metadata: languageName: node linkType: hard -"babel-loader@npm:9.2.1": - version: 9.2.1 - resolution: "babel-loader@npm:9.2.1" +"babel-loader@npm:10.0.0": + version: 10.0.0 + resolution: "babel-loader@npm:10.0.0" dependencies: - find-cache-dir: "npm:^4.0.0" - schema-utils: "npm:^4.0.0" + find-up: "npm:^5.0.0" peerDependencies: "@babel/core": ^7.12.0 - webpack: ">=5" - checksum: 10/f1f24ae3c22d488630629240b0eba9c935545f82ff843c214e8f8df66e266492b7a3d4cb34ef9c9721fb174ca222e900799951c3fd82199473bc6bac52ec03a3 + webpack: ">=5.61.0" + checksum: 10/f22dc803e38a6b29cc61fbc3482f1f42a8787df2a43706dc937d328103ba6b947a223f67706b07af765d415664ad56e9fed00f85b524fe223f3ac3f00b03770b languageName: node linkType: hard @@ -13391,13 +13390,6 @@ __metadata: languageName: node linkType: hard -"common-path-prefix@npm:^3.0.0": - version: 3.0.0 - resolution: "common-path-prefix@npm:3.0.0" - checksum: 10/09c180e8d8495d42990d617f4d4b7522b5da20f6b236afe310192d401d1da8147a7835ae1ea37797ba0c2238ef3d06f3492151591451df34539fdb4b2630f2b3 - languageName: node - linkType: hard - "common-tags@npm:1.8.2, common-tags@npm:^1.8.0": version: 1.8.2 resolution: "common-tags@npm:1.8.2" @@ -17103,16 +17095,6 @@ __metadata: languageName: node linkType: hard -"find-cache-dir@npm:^4.0.0": - version: 4.0.0 - resolution: "find-cache-dir@npm:4.0.0" - dependencies: - common-path-prefix: "npm:^3.0.0" - pkg-dir: "npm:^7.0.0" - checksum: 10/52a456a80deeb27daa3af6e06059b63bdb9cc4af4d845fc6d6229887e505ba913cd56000349caa60bc3aa59dacdb5b4c37903d4ba34c75102d83cab330b70d2f - languageName: node - linkType: hard - "find-file-up@npm:^0.1.2": version: 0.1.3 resolution: "find-file-up@npm:0.1.3" @@ -17181,16 +17163,6 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^6.3.0": - version: 6.3.0 - resolution: "find-up@npm:6.3.0" - dependencies: - locate-path: "npm:^7.1.0" - path-exists: "npm:^5.0.0" - checksum: 10/4f3bdc30d41778c647e53f4923e72de5e5fb055157031f34501c5b36c2eb59f77b997edf9cb00165c6060cda7eaa2e3da82cb6be2e61d68ad3e07c4bc4cce67e - languageName: node - linkType: hard - "findup-sync@npm:^5.0.0": version: 5.0.0 resolution: "findup-sync@npm:5.0.0" @@ -18371,7 +18343,7 @@ __metadata: "@welldone-software/why-did-you-render": "npm:8.0.3" ansicolor: "npm:2.0.3" autoprefixer: "npm:10.4.21" - babel-loader: "npm:9.2.1" + babel-loader: "npm:10.0.0" baron: "npm:3.0.3" blob-polyfill: "npm:9.0.20240710" brace: "npm:0.11.1" @@ -22132,15 +22104,6 @@ __metadata: languageName: node linkType: hard -"locate-path@npm:^7.1.0": - version: 7.2.0 - resolution: "locate-path@npm:7.2.0" - dependencies: - p-locate: "npm:^6.0.0" - checksum: 10/1c6d269d4efec555937081be964e8a9b4a136319c79ca1d45ac6382212a8466113c75bd89e44521ca8ecd1c47fb08523b56eee5c0712bc7d14fec5f729deeb42 - languageName: node - linkType: hard - "lockfile@npm:^1.0.4": version: 1.0.4 resolution: "lockfile@npm:1.0.4" @@ -24661,15 +24624,6 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^4.0.0": - version: 4.0.0 - resolution: "p-limit@npm:4.0.0" - dependencies: - yocto-queue: "npm:^1.0.0" - checksum: 10/01d9d70695187788f984226e16c903475ec6a947ee7b21948d6f597bed788e3112cc7ec2e171c1d37125057a5f45f3da21d8653e04a3a793589e12e9e80e756b - languageName: node - linkType: hard - "p-locate@npm:^2.0.0": version: 2.0.0 resolution: "p-locate@npm:2.0.0" @@ -24697,15 +24651,6 @@ __metadata: languageName: node linkType: hard -"p-locate@npm:^6.0.0": - version: 6.0.0 - resolution: "p-locate@npm:6.0.0" - dependencies: - p-limit: "npm:^4.0.0" - checksum: 10/2bfe5234efa5e7a4e74b30a5479a193fdd9236f8f6b4d2f3f69e3d286d9a7d7ab0c118a2a50142efcf4e41625def635bd9332d6cbf9cc65d85eb0718c579ab38 - languageName: node - linkType: hard - "p-map-series@npm:2.1.0": version: 2.1.0 resolution: "p-map-series@npm:2.1.0" @@ -25206,13 +25151,6 @@ __metadata: languageName: node linkType: hard -"path-exists@npm:^5.0.0": - version: 5.0.0 - resolution: "path-exists@npm:5.0.0" - checksum: 10/8ca842868cab09423994596eb2c5ec2a971c17d1a3cb36dbf060592c730c725cd524b9067d7d2a1e031fef9ba7bd2ac6dc5ec9fb92aa693265f7be3987045254 - languageName: node - linkType: hard - "path-is-absolute@npm:^1.0.0": version: 1.0.1 resolution: "path-is-absolute@npm:1.0.1" @@ -25485,15 +25423,6 @@ __metadata: languageName: node linkType: hard -"pkg-dir@npm:^7.0.0": - version: 7.0.0 - resolution: "pkg-dir@npm:7.0.0" - dependencies: - find-up: "npm:^6.3.0" - checksum: 10/94298b20a446bfbbd66604474de8a0cdd3b8d251225170970f15d9646f633e056c80520dd5b4c1d1050c9fed8f6a9e5054b141c93806439452efe72e57562c03 - languageName: node - linkType: hard - "playwright-core@npm:1.54.1, playwright-core@npm:>=1.2.0": version: 1.54.1 resolution: "playwright-core@npm:1.54.1" @@ -33274,13 +33203,6 @@ __metadata: languageName: node linkType: hard -"yocto-queue@npm:^1.0.0": - version: 1.0.0 - resolution: "yocto-queue@npm:1.0.0" - checksum: 10/2cac84540f65c64ccc1683c267edce396b26b1e931aa429660aefac8fbe0188167b7aee815a3c22fa59a28a58d898d1a2b1825048f834d8d629f4c2a5d443801 - languageName: node - linkType: hard - "yoctocolors-cjs@npm:^2.1.2": version: 2.1.2 resolution: "yoctocolors-cjs@npm:2.1.2" From 953afbd7841a07263871ca62754aedd5c8b64b47 Mon Sep 17 00:00:00 2001 From: Konrad Lalik Date: Fri, 1 Aug 2025 16:29:08 +0200 Subject: [PATCH 27/89] Alerting: List V2 - Fix free form filter (#109050) Use whole free form words for fuzzy search in rule names --- .../alerting/unified/rule-list/hooks/filters.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/public/app/features/alerting/unified/rule-list/hooks/filters.ts b/public/app/features/alerting/unified/rule-list/hooks/filters.ts index 3602081e7c0..2e9535dd97f 100644 --- a/public/app/features/alerting/unified/rule-list/hooks/filters.ts +++ b/public/app/features/alerting/unified/rule-list/hooks/filters.ts @@ -22,12 +22,10 @@ export function groupFilter( const { name, file } = group; const { namespace, groupName } = filterState; - // Use fuzzy search for namespace if (namespace && !fuzzyMatches(file, namespace)) { return false; } - // Use fuzzy search for group name if (groupName && !fuzzyMatches(name, groupName)) { return false; } @@ -41,17 +39,17 @@ export function groupFilter( export function ruleFilter(rule: PromRuleDTO, filterState: RulesFilter) { const { name, labels = {}, health, type } = rule; - // Free form words filter (uses fuzzy matching for each word) - if (filterState.freeFormWords.length > 0 && !filterState.freeFormWords.some((word) => fuzzyMatches(name, word))) { - return false; + if (filterState.freeFormWords.length > 0) { + const nameMatches = fuzzyMatches(name, filterState.freeFormWords.join(' ')); + if (!nameMatches) { + return false; + } } - // Rule name filter (uses fuzzy matching) if (filterState.ruleName && !fuzzyMatches(name, filterState.ruleName)) { return false; } - // Labels filter if (filterState.labels.length > 0) { const matchers = compact(filterState.labels.map(looseParseMatcher)); const doRuleLabelsMatchQuery = matchers.length > 0 && labelsMatchMatchers(labels, matchers); @@ -68,12 +66,10 @@ export function ruleFilter(rule: PromRuleDTO, filterState: RulesFilter) { } } - // Rule type filter if (filterState.ruleType && type !== filterState.ruleType) { return false; } - // Rule state filter (for alerting rules only) if (filterState.ruleState) { if (!prometheusRuleType.alertingRule(rule)) { return false; @@ -83,7 +79,6 @@ export function ruleFilter(rule: PromRuleDTO, filterState: RulesFilter) { } } - // Rule health filter if (filterState.ruleHealth && health !== filterState.ruleHealth) { return false; } @@ -102,7 +97,6 @@ export function ruleFilter(rule: PromRuleDTO, filterState: RulesFilter) { } } - // Dashboard UID filter if (filterState.dashboardUid) { if (!prometheusRuleType.alertingRule(rule)) { return false; From b333b67aeaeb81b383281ecd7980b152a5744f3d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 15:29:06 +0000 Subject: [PATCH 28/89] Update dependency copy-webpack-plugin to v13 (#109053) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- packages/grafana-plugin-configs/package.json | 2 +- yarn.lock | 54 ++++---------------- 3 files changed, 11 insertions(+), 47 deletions(-) diff --git a/package.json b/package.json index 6fdf6a22a28..7626f9f04b1 100644 --- a/package.json +++ b/package.json @@ -174,7 +174,7 @@ "chrome-remote-interface": "0.33.3", "codeowners": "^5.1.1", "confusing-browser-globals": "^1.0.11", - "copy-webpack-plugin": "12.0.2", + "copy-webpack-plugin": "13.0.0", "core-js": "3.44.0", "crashme": "0.0.15", "css-loader": "7.1.2", diff --git a/packages/grafana-plugin-configs/package.json b/packages/grafana-plugin-configs/package.json index 7d068121b19..c22258285c0 100644 --- a/packages/grafana-plugin-configs/package.json +++ b/packages/grafana-plugin-configs/package.json @@ -14,7 +14,7 @@ "@swc/jest": "^0.2.26", "@types/eslint": "9.6.1", "@types/webpack-bundle-analyzer": "^4.7.0", - "copy-webpack-plugin": "12.0.2", + "copy-webpack-plugin": "13.0.0", "eslint": "9.32.0", "eslint-webpack-plugin": "4.2.0", "fork-ts-checker-webpack-plugin": "9.1.0", diff --git a/yarn.lock b/yarn.lock index e09a9406eac..dae3c03c7d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3415,7 +3415,7 @@ __metadata: "@swc/jest": "npm:^0.2.26" "@types/eslint": "npm:9.6.1" "@types/webpack-bundle-analyzer": "npm:^4.7.0" - copy-webpack-plugin: "npm:12.0.2" + copy-webpack-plugin: "npm:13.0.0" eslint: "npm:9.32.0" eslint-webpack-plugin: "npm:4.2.0" fork-ts-checker-webpack-plugin: "npm:9.1.0" @@ -7355,13 +7355,6 @@ __metadata: languageName: node linkType: hard -"@sindresorhus/merge-streams@npm:^2.1.0": - version: 2.3.0 - resolution: "@sindresorhus/merge-streams@npm:2.3.0" - checksum: 10/798bcb53cd1ace9df84fcdd1ba86afdc9e0cd84f5758d26ae9b1eefd8e8887e5fc30051132b9e74daf01bb41fa5a2faf1369361f83d76a3b3d7ee938058fd71c - languageName: node - linkType: hard - "@sinonjs/commons@npm:^3.0.0": version: 3.0.0 resolution: "@sinonjs/commons@npm:3.0.0" @@ -13644,19 +13637,18 @@ __metadata: languageName: node linkType: hard -"copy-webpack-plugin@npm:12.0.2": - version: 12.0.2 - resolution: "copy-webpack-plugin@npm:12.0.2" +"copy-webpack-plugin@npm:13.0.0": + version: 13.0.0 + resolution: "copy-webpack-plugin@npm:13.0.0" dependencies: - fast-glob: "npm:^3.3.2" glob-parent: "npm:^6.0.1" - globby: "npm:^14.0.0" normalize-path: "npm:^3.0.0" schema-utils: "npm:^4.2.0" serialize-javascript: "npm:^6.0.2" + tinyglobby: "npm:^0.2.12" peerDependencies: webpack: ^5.1.0 - checksum: 10/674725d4d9556b7b9a32bb85393532ef2bb75ffce785d942681b3575a86d900751f67cebbb089ddd050757f58c84edc18732e17880f12c45c9775ca94328526c + checksum: 10/209051dd3c0bc7ab97170309cdb1826e642044d2d53e0adc35bb227123c89ae1296a504409325e9b955d7b2d1a505b063f0023e924151d382dbcc92cb9325e6a languageName: node linkType: hard @@ -18144,20 +18136,6 @@ __metadata: languageName: node linkType: hard -"globby@npm:^14.0.0": - version: 14.0.1 - resolution: "globby@npm:14.0.1" - dependencies: - "@sindresorhus/merge-streams": "npm:^2.1.0" - fast-glob: "npm:^3.3.2" - ignore: "npm:^5.2.4" - path-type: "npm:^5.0.0" - slash: "npm:^5.1.0" - unicorn-magic: "npm:^0.1.0" - checksum: 10/b36f57afc45a857a884d82657603c7e1663b1e6f3f9afbeb53d12e42230469fc5b26a7e14a01e51086f3f25c138f58a7002036fcc8f3ca054097b6dd7c71d639 - languageName: node - linkType: hard - "globby@npm:~6.1.0": version: 6.1.0 resolution: "globby@npm:6.1.0" @@ -18357,7 +18335,7 @@ __metadata: comlink: "npm:4.4.2" common-tags: "npm:1.8.2" confusing-browser-globals: "npm:^1.0.11" - copy-webpack-plugin: "npm:12.0.2" + copy-webpack-plugin: "npm:13.0.0" core-js: "npm:3.44.0" crashme: "npm:0.0.15" croner: "npm:^9.0.0" @@ -25254,13 +25232,6 @@ __metadata: languageName: node linkType: hard -"path-type@npm:^5.0.0": - version: 5.0.0 - resolution: "path-type@npm:5.0.0" - checksum: 10/15ec24050e8932c2c98d085b72cfa0d6b4eeb4cbde151a0a05726d8afae85784fc5544f733d8dfc68536587d5143d29c0bd793623fad03d7e61cc00067291cd5 - languageName: node - linkType: hard - "pathe@npm:^2.0.2": version: 2.0.2 resolution: "pathe@npm:2.0.2" @@ -29173,7 +29144,7 @@ __metadata: languageName: node linkType: hard -"slash@npm:^5.0.0, slash@npm:^5.1.0": +"slash@npm:^5.0.0": version: 5.1.0 resolution: "slash@npm:5.1.0" checksum: 10/2c41ec6fb1414cd9bba0fa6b1dd00e8be739e3fe85d079c69d4b09ca5f2f86eafd18d9ce611c0c0f686428638a36c272a6ac14799146a8295f259c10cc45cde4 @@ -30772,7 +30743,7 @@ __metadata: languageName: node linkType: hard -"tinyglobby@npm:^0.2.13": +"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.13": version: 0.2.14 resolution: "tinyglobby@npm:0.2.14" dependencies: @@ -31680,13 +31651,6 @@ __metadata: languageName: node linkType: hard -"unicorn-magic@npm:^0.1.0": - version: 0.1.0 - resolution: "unicorn-magic@npm:0.1.0" - checksum: 10/9b4d0e9809807823dc91d0920a4a4c0cff2de3ebc54ee87ac1ee9bc75eafd609b09d1f14495e0173aef26e01118706196b6ab06a75fe0841028b3983a8af313f - languageName: node - linkType: hard - "union@npm:~0.5.0": version: 0.5.0 resolution: "union@npm:0.5.0" From 428773411422a08af08b19adc3e448fd7b56bcff Mon Sep 17 00:00:00 2001 From: Timur Olzhabayev Date: Fri, 1 Aug 2025 17:46:29 +0200 Subject: [PATCH 29/89] Fix: Adding sparse checkout to issue triage workflow (#109060) * adding sparse checkout * adding checkout step if we want to run triage --- .github/workflows/issue-opened.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/issue-opened.yml b/.github/workflows/issue-opened.yml index b54bb968b7f..2ca46dd1db2 100644 --- a/.github/workflows/issue-opened.yml +++ b/.github/workflows/issue-opened.yml @@ -88,7 +88,6 @@ jobs: private-key: ${{ env.GITHUB_APP_PRIVATE_KEY }} permission-members: read permission-issues: write - - name: Check if member of grafana org id: check-if-grafana-org-member continue-on-error: true @@ -96,6 +95,13 @@ jobs: env: GH_TOKEN: ${{ steps.generate_token.outputs.token }} ACTOR: ${{ github.actor }} + - name: Checkout + if: steps.check-if-grafana-org-member.outputs.is_grafana_org_member != 'true' && github.event.issue.author_association != 'MEMBER' && github.event.issue.author_association != 'OWNER' + uses: actions/checkout@v4 # v4.2.2 + with: + persist-credentials: false + sparse-checkout: | + .github/workflows/auto-triager - name: Send issue to the auto triager action id: auto_triage if: steps.check-if-grafana-org-member.outputs.is_grafana_org_member != 'true' && github.event.issue.author_association != 'MEMBER' && github.event.issue.author_association != 'OWNER' From 0faa03edbe73cc9974462e1be0acd3b3b5d053ed Mon Sep 17 00:00:00 2001 From: Jack Baldry Date: Fri, 1 Aug 2025 16:57:18 +0100 Subject: [PATCH 30/89] Add snippets for 'Create log alert rules with Grafana Alerting' learning journey (#109059) --- .../alerting-rules/link-alert-rules-to-panels.md | 4 ++++ docs/sources/alerting/best-practices/_index.md | 4 ++++ .../fundamentals/alert-rule-evaluation/_index.md | 14 ++++++++++++-- .../fundamentals/alert-rules/annotation-label.md | 8 ++++++++ .../alerting/fundamentals/notifications/_index.md | 4 ++++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/sources/alerting/alerting-rules/link-alert-rules-to-panels.md b/docs/sources/alerting/alerting-rules/link-alert-rules-to-panels.md index 052770cc058..8be72c73270 100644 --- a/docs/sources/alerting/alerting-rules/link-alert-rules-to-panels.md +++ b/docs/sources/alerting/alerting-rules/link-alert-rules-to-panels.md @@ -67,6 +67,8 @@ By default, notification messages include a link to the dashboard panel. Additio ## Create alert rules from panels +{{< shared id="create-alert-from-panel" >}} + To streamline alert creation, you can create an alert rule directly from a panel. 1. Navigate to a dashboard in the **Dashboards** section. @@ -77,6 +79,8 @@ To streamline alert creation, you can create an alert rule directly from a panel - Sets the alert rule query using the panel query. 1. Complete the alert rule configuration and click **Save rule** to initiate the alert rule. +{{< /shared >}} + You can then [view the alert state on the panel](ref:view-alert-state-on-panels). By default, notification messages include a link to the dashboard panel. Additionally, you can [enable displaying panel screenshots in notifications](ref:images-in-notifications). diff --git a/docs/sources/alerting/best-practices/_index.md b/docs/sources/alerting/best-practices/_index.md index 18bcf13121a..41251a25994 100644 --- a/docs/sources/alerting/best-practices/_index.md +++ b/docs/sources/alerting/best-practices/_index.md @@ -21,6 +21,8 @@ This section provides a set of guides and examples of best practices for Grafana Designing and configuring an alert management set up that works takes time. Here are some additional tips on how to create an effective alert management set up: +{{< shared id="alert-planning-fundamentals" >}} + **Which are the key metrics for your business that you want to monitor and alert on?** - Find events that are important to know about and not so trivial or frequent that recipients ignore them. @@ -44,3 +46,5 @@ Designing and configuring an alert management set up that works takes time. Here - Avoid noisy, unnecessary alerts by using silences, mute timings, or pausing alert rule evaluation. - Continually tune your alert rules to review effectiveness. Remove alert rules to avoid duplication or ineffective alerts. - Continually review your thresholds and evaluation rules. + +{{< /shared >}} diff --git a/docs/sources/alerting/fundamentals/alert-rule-evaluation/_index.md b/docs/sources/alerting/fundamentals/alert-rule-evaluation/_index.md index 80a58728bc1..7ff256ac103 100644 --- a/docs/sources/alerting/fundamentals/alert-rule-evaluation/_index.md +++ b/docs/sources/alerting/fundamentals/alert-rule-evaluation/_index.md @@ -81,30 +81,40 @@ Alert instances are routed for [notifications](ref:notifications) in two scenari ## Evaluation group -Every alert rule and recording rule is assigned to an evaluation group. +{{< shared id="evaluation-group-basics" >}} -Each evaluation group contains an **evaluation interval** that determines how frequently the rule is checked. For instance, the evaluation may occur every `10s`, `30s`, `1m`, `10m`, etc. +Every alert rule and recording rule is assigned to an evaluation group. Each evaluation group contains an **evaluation interval** that determines how frequently the rule is checked. For instance, the evaluation may occur every `10s`, `30s`, `1m`, `10m`, etc. + +{{< /shared >}} Rules can be evaluated concurrently or sequentially. For details, see [How rules are evaluated within a group](ref:evaluation-within-a-group). ## Pending period +{{< shared id="pending-period-basics" >}} + You can set a **Pending period** to prevent unnecessary notifications caused by temporary issues. When the alert condition is met, the alert instance enters the **Pending** state. It remains in this state until the condition has been continuously true for the entire **Pending period**. This ensures the condition breach is stable before the alert transitions to the **Alerting** state and routed for notification. +{{< /shared >}} + - **Normal** -> **Pending** -> **Alerting**\* You can also set the **Pending period** to zero to skip the **Pending** state entirely and transition to **Alerting** immediately. ## Keep firing for +{{< shared id="keep-firing-for" >}} + You can set a **Keep firing for** period to avoid repeated firing-resolving-firing notifications caused by flapping conditions. When the alert condition is no longer met during the **Alerting** state, the alert instance enters the **Recovering** state. +{{< /shared >}} + - **Alerting** → **Recovering** → **Normal (Resolved)**\* - After the **Keep firing for** period elapses, the alert transitions to the **Normal** state and is marked as **Resolved**. - If the alert condition is met again, the alert transitions back to the **Alerting** state, and no new notifications are sent. diff --git a/docs/sources/alerting/fundamentals/alert-rules/annotation-label.md b/docs/sources/alerting/fundamentals/alert-rules/annotation-label.md index 8d0aca31034..27ae61e3cb9 100644 --- a/docs/sources/alerting/fundamentals/alert-rules/annotation-label.md +++ b/docs/sources/alerting/fundamentals/alert-rules/annotation-label.md @@ -62,10 +62,14 @@ Labels and annotations add additional information about an alert using key/value ## Labels +{{< shared id="labels-basics" >}} + **Labels** are unique identifiers of an [alert instance](ref:alert-instances). You can use them for searching, silencing, and routing notifications. Examples of labels are `server=server1` or `team=backend`. Each alert rule can have more than one label and the complete set of labels for an alert rule is called its label set. It is this label set that identifies the alert. +{{< /shared >}} + For example, an alert instance might have the label set `{alertname="High CPU usage",server="server1"}` while another alert instance might have the label set `{alertname="High CPU usage",server="server2"}`. These are two separate alert instances because although their `alertname` labels are the same, their `server` labels are different. {{< figure alt="Image shows an example of an alert instance and the labels used on the alert instance." src="/static/img/docs/alerting/unified/multi-dimensional-alert.png" >}} @@ -134,6 +138,8 @@ If multiple label keys are sanitized to the same value, the duplicates have a sh ## Annotations +{{< shared id="annotations-basics" >}} + Annotations add additional information to alert instances, helping responders identify and address potential issues. Create clear and self-explanatory annotations so that first responders can investigate without needing deeper knowledge of the alert setup. @@ -145,6 +151,8 @@ Annotations are displayed in Grafana and are included by default in notification - `runbook_url`: The runbook page to guide operators managing a potential incident. - `__dashboardUid__` and `__panelId__`: [Link the alert to a dashboard and panel](ref:link-alert-rules-to-panels) to facilitate alert investigation. +{{< /shared >}} + For example, you can edit the annotation `summary` to explain why the alert was triggered: ``` diff --git a/docs/sources/alerting/fundamentals/notifications/_index.md b/docs/sources/alerting/fundamentals/notifications/_index.md index 3a0599722d3..fd8a77448b8 100644 --- a/docs/sources/alerting/fundamentals/notifications/_index.md +++ b/docs/sources/alerting/fundamentals/notifications/_index.md @@ -83,10 +83,14 @@ Start defining your [contact points](ref:contact-points) to specify how to recei ### Contact points +{{< shared id="contact-points-fundamentals" >}} + [Contact points](ref:contact-points) contain the configuration for sending alert notifications, specifying destinations like email, Slack, IRM, webhooks, and their notification messages. A contact point is a list of integrations, each sending a message to a specific destination. +{{< /shared >}} + By default, notification messages include common alert details, such as the number of alerts, alert names, labels, annotations, and other alert information. You can also customize notification messages and use notification templates. First, create the contact point and test the notifications. Then, configure the alert rule to send its notifications to either a contact point or through Notification Policies. From 4a26cb92c633b025441568388abcd1a2f8122bf4 Mon Sep 17 00:00:00 2001 From: Andrew Hackmann <5140848+bossinc@users.noreply.github.com> Date: Fri, 1 Aug 2025 11:01:25 -0500 Subject: [PATCH 31/89] ElasticSearch: Fix inline casting bug when validating the index (#108951) split out inline casts --- pkg/tsdb/elasticsearch/healthcheck.go | 10 +++++++--- pkg/tsdb/elasticsearch/healthcheck_test.go | 10 ++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/pkg/tsdb/elasticsearch/healthcheck.go b/pkg/tsdb/elasticsearch/healthcheck.go index a3e04aafb6f..928945691de 100644 --- a/pkg/tsdb/elasticsearch/healthcheck.go +++ b/pkg/tsdb/elasticsearch/healthcheck.go @@ -191,11 +191,15 @@ func validateIndex(ctx context.Context, ds *es.DatasourceInfo) (message string, return "Failed to unmarshal field capabilities response", "error" } if fieldCaps["error"] != nil { - if errorMessage, ok := fieldCaps["error"].(map[string]any)["reason"].(string); ok { - return fmt.Sprintf("Error validating index: %s", errorMessage), "warning" - } else { + errorMap, ok := fieldCaps["error"].(map[string]any) + if !ok { return "Error validating index", "warning" } + errorMessage, ok := errorMap["reason"].(string) + if !ok { + return "Error validating index", "warning" + } + return fmt.Sprintf("Error validating index: %s", errorMessage), "warning" } fields, ok := fieldCaps["fields"].(map[string]any) diff --git a/pkg/tsdb/elasticsearch/healthcheck_test.go b/pkg/tsdb/elasticsearch/healthcheck_test.go index b3f6dc97c93..48fd00e8adc 100644 --- a/pkg/tsdb/elasticsearch/healthcheck_test.go +++ b/pkg/tsdb/elasticsearch/healthcheck_test.go @@ -58,6 +58,16 @@ func Test_validateIndex_Warning_ErrorValidatingIndex(t *testing.T) { assert.Equal(t, "Elasticsearch data source is healthy. Warning: Error validating index: index_not_found", res.Message) } +func Test_validateIndex_Warning_ErrorValidatingIndex2(t *testing.T) { + service := GetMockService(http.StatusOK, "200 OK", `{"status":"green"}`, `{"error":"not a map"}`) + res, _ := service.CheckHealth(mockedCfg, &backend.CheckHealthRequest{ + PluginContext: backend.PluginContext{}, + Headers: nil, + }) + assert.Equal(t, backend.HealthStatusOk, res.Status) + assert.Equal(t, "Elasticsearch data source is healthy. Warning: Error validating index", res.Message) +} + func Test_validateIndex_Warning_WrongTimestampType(t *testing.T) { service := GetMockService(http.StatusOK, "200 OK", `{"status":"green"}`, `{"fields":{"timestamp":{"float":{"metadata_field":true}}}}`) res, _ := service.CheckHealth(mockedCfg, &backend.CheckHealthRequest{ From 147df3de0893fd1f6b4866edbc0ce71c9833bc2a Mon Sep 17 00:00:00 2001 From: Eve Meelan <81647476+Eve832@users.noreply.github.com> Date: Fri, 1 Aug 2025 12:23:58 -0400 Subject: [PATCH 32/89] Pricing update: no more Cloud Advanced (#109056) * scrub Cloud Advanced * prettier edit --- .../migration-guide/manually-migrate-to-grafana-cloud.md | 2 +- .../alerting/alerting-rules/create-grafana-managed-rule.md | 2 +- docs/sources/introduction/grafana-enterprise.md | 2 +- .../configure-grafana/configure-custom-branding/index.md | 5 +---- .../configure-authentication/auth-proxy/index.md | 3 ++- .../configure-authentication/azuread/index.md | 2 +- .../configure-authentication/generic-oauth/index.md | 2 +- .../configure-authentication/github/index.md | 2 +- .../configure-authentication/gitlab/index.md | 2 +- .../configure-authentication/google/index.md | 2 +- .../configure-authentication/keycloak/index.md | 2 +- .../configure-authentication/okta/index.md | 2 +- .../saml/configure-saml-team-role-mapping/_index.md | 2 +- .../configure-authentication/saml/saml-ui/_index.md | 4 ++-- .../configure-security/configure-request-security.md | 2 +- .../configure-security/configure-scim-provisioning/_index.md | 2 +- .../configure-scim-with-azuread/_index.md | 4 ++-- .../configure-scim-with-okta/_index.md | 4 ++-- .../configure-scim-provisioning/manage-users-teams/_index.md | 2 +- docs/sources/setup-grafana/configure-security/export-logs.md | 2 +- .../configure-security/planning-iam-strategy/index.md | 2 +- 21 files changed, 25 insertions(+), 27 deletions(-) diff --git a/docs/sources/administration/migration-guide/manually-migrate-to-grafana-cloud.md b/docs/sources/administration/migration-guide/manually-migrate-to-grafana-cloud.md index e68083eb4a0..5f4fa75a787 100644 --- a/docs/sources/administration/migration-guide/manually-migrate-to-grafana-cloud.md +++ b/docs/sources/administration/migration-guide/manually-migrate-to-grafana-cloud.md @@ -290,7 +290,7 @@ The following customizations are available via support: - Enabling [feature toggles](http://www.grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/feature-toggles). - [Single sign-on and team sync using SAML, LDAP, or OAuth](http://www.grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication). - Enable [embedding Grafana dashboards in other applications](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#allow_embedding) for Grafana Cloud contracted customers. -- [Audit logging](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/audit-grafana/) ([Usage insights logs and dashboards](https://grafana.com/docs/grafana-cloud/account-management/usage-insights/) are available in Grafana Cloud Pro and Advanced by default). +- [Audit logging](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/audit-grafana/) ([Usage insights logs and dashboards](https://grafana.com/docs/grafana-cloud/account-management/usage-insights/) are available in select Grafana Cloud paid accounts). Note that the following custom configurations are not supported in Grafana Cloud: diff --git a/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md b/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md index df7abac34b0..f7d1214271a 100644 --- a/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md +++ b/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md @@ -161,7 +161,7 @@ You can find the public data sources that support alert rules in the [Grafana Pl In Grafana Cloud, the number of Grafana-managed alert rules you can create depends on your Grafana Cloud plan. - Free Forever plan: You can create up to 100 free alert rules, with each alert rule having a maximum of 1000 alert instances. -- All paid plans (Pro and Advanced): They have a soft limit of 2000 alert rules and support unlimited alert instances. To increase the limit, open a support ticket from the [Cloud portal](/docs/grafana-cloud/account-management/support/). +- All paid plans: They have a soft limit of 2000 alert rules and support unlimited alert instances. To increase the limit, open a support ticket from the [Cloud portal](/docs/grafana-cloud/account-management/support/). ### Permissions diff --git a/docs/sources/introduction/grafana-enterprise.md b/docs/sources/introduction/grafana-enterprise.md index 3993809d076..ef8884f3c55 100644 --- a/docs/sources/introduction/grafana-enterprise.md +++ b/docs/sources/introduction/grafana-enterprise.md @@ -19,7 +19,7 @@ To learn more about Grafana Enterprise, refer to [our product page](/enterprise) ## Enterprise features in Grafana Cloud -Many Grafana Enterprise features are also available in [Grafana Cloud](/docs/grafana-cloud) Free, Pro, and Advanced accounts. For details, refer to [Grafana Cloud pricing](/pricing/#featuresTable). +Many Grafana Enterprise features are also available in paid [Grafana Cloud](/docs/grafana-cloud) accounts. For details, refer to [Grafana Cloud features](/docs/grafana-cloud/introduction/understand-grafana-cloud-features/). For pricing and plans, refer to [Grafana Cloud pricing](https://grafana.com/pricing/). To migrate to Grafana Cloud, refer to [Migrate from Grafana Enterprise to Grafana Cloud](/docs/grafana//administration/migration-guide/) diff --git a/docs/sources/setup-grafana/configure-grafana/configure-custom-branding/index.md b/docs/sources/setup-grafana/configure-grafana/configure-custom-branding/index.md index 2fd80cbac5f..92004450844 100644 --- a/docs/sources/setup-grafana/configure-grafana/configure-custom-branding/index.md +++ b/docs/sources/setup-grafana/configure-grafana/configure-custom-branding/index.md @@ -15,10 +15,7 @@ weight: 300 Custom branding enables you to replace the Grafana Labs brand and logo with your corporate brand and logo. {{< admonition type="note" >}} -Available in [Grafana Enterprise](../../../introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud). For Cloud Advanced and Enterprise customers, please provide custom elements and logos to our Support team. We will help you host your images and update your custom branding. - -This feature is not available for Grafana Free and Pro tiers. -For more information on feature availability across plans, refer to our [feature comparison page](/docs/grafana-cloud/cost-management-and-billing/understand-grafana-cloud-features/) +Available in [Grafana Enterprise](../../../introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. For Cloud customers, please provide custom elements and logos to our Support team. We will help you host your images and update your custom branding. {{< /admonition >}} diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/auth-proxy/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/auth-proxy/index.md index 3d1c4a48a6b..a379eb82d52 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/auth-proxy/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/auth-proxy/index.md @@ -237,7 +237,8 @@ If the user is deleted from Grafana, the user will be not be able to login and r ### Team Sync {{< admonition type="note" >}} -Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/). +Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. + {{< /admonition >}} With Team Sync, it's possible to set up synchronization between teams in your authentication provider and Grafana. You can send Grafana values as part of an HTTP header and have Grafana map them to your team structure. This allows you to put users into specific teams automatically. diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/azuread/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/azuread/index.md index 69e6e1415f0..f3d2c5bea74 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/azuread/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/azuread/index.md @@ -414,7 +414,7 @@ auto_login = true ### Team Sync {{< admonition type="note" >}} -Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/). +Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} With Team Sync you can map your Entra ID groups to teams in Grafana so that your users will automatically be added to diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md index 9ebe70e6e55..f28dc35b7f6 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/generic-oauth/index.md @@ -320,7 +320,7 @@ org_mapping = org_foo:org_foo:Viewer org_bar:org_bar:Editor *:org_baz:Editor ## Configure team synchronization {{< admonition type="note" >}} -Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/). +Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} By using Team Sync, you can link your OAuth2 groups to teams within Grafana. This will automatically assign users to the appropriate teams. diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md index 7a327576cfd..c11ef4fd3ab 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md @@ -211,7 +211,7 @@ role_attribute_path = [login=='octocat'][0] && 'GrafanaAdmin' || 'Viewer' ## Configure team synchronization {{< admonition type="note" >}} -Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/). +Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} By using Team Sync, you can map teams from your GitHub organization to teams within Grafana. This will automatically assign users to the appropriate teams. diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md index 22363e59b54..ac45c634599 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/gitlab/index.md @@ -236,7 +236,7 @@ use_refresh_token = true ## Configure team synchronization {{< admonition type="note" >}} -Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/). +Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} By using Team Sync, you can map GitLab groups to teams within Grafana. This will automatically assign users to the appropriate teams. diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/google/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/google/index.md index 59f2c6951a8..367d05c068d 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/google/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/google/index.md @@ -160,7 +160,7 @@ auto_login = true ### Configure team synchronization {{< admonition type="note" >}} -Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/). +Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} With team sync, you can easily add users to teams by utilizing their Google groups. To set up team sync for Google OAuth, refer to the following example. diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/keycloak/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/keycloak/index.md index 88adc9d4a2a..6425eb09db7 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/keycloak/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/keycloak/index.md @@ -109,7 +109,7 @@ viewer ## Team sync {{< admonition type="note" >}} -Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/). +Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} [Teamsync](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-team-sync/) is a feature that allows you to map groups from your identity provider to Grafana teams. This is useful if you want to give your users access to specific dashboards or folders based on their group membership. diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md index 8166760890f..53618823a06 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/okta/index.md @@ -236,7 +236,7 @@ org_mapping = ["Group 1:org_foo:Viewer", "Group 2:org_bar:Editor", "*:3:Editor"] ### Configure team synchronization {{< admonition type="note" >}} -Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/). +Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} By using Team Sync, you can link your Okta groups to teams within Grafana. This will automatically assign users to the appropriate teams. diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/saml/configure-saml-team-role-mapping/_index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/saml/configure-saml-team-role-mapping/_index.md index edfedcefb9a..ad4dab8cf00 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/saml/configure-saml-team-role-mapping/_index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/saml/configure-saml-team-role-mapping/_index.md @@ -12,7 +12,7 @@ weight: 540 # Configure team sync for SAML {{< admonition type="note" >}} -Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/). +Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} To use SAML Team sync, set [`assertion_attribute_groups`](https://grafana.com/docs/grafana//setup-grafana/configure-grafana/enterprise-configuration/#assertion_attribute_groups) to the attribute name where you store user groups. Then Grafana will use attribute values extracted from SAML assertion to add user into the groups with the same name configured on the External group sync tab. diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/saml/saml-ui/_index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/saml/saml-ui/_index.md index 52d2c84fbfd..dee23439664 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/saml/saml-ui/_index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/saml/saml-ui/_index.md @@ -14,7 +14,7 @@ weight: 510 # Configure SAML authentication using the Grafana user interface {{< admonition type="note" >}} -Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) version 10.0 and later, and [Grafana Cloud Pro or Advanced](https://grafana.com/docs/grafana//introduction/grafana-cloud/). +Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) version 10.0 and later, and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} You can configure SAML authentication in Grafana through the user interface (UI) or the Grafana configuration file. For instructions on how to set up SAML using the Grafana configuration file, refer to [Configure SAML authentication using the configuration file](../#configure-saml-using-the-grafana-config-file). @@ -40,7 +40,7 @@ To follow this guide, you need: These permissions are granted by `fixed:authentication.config:writer` role. By default, this role is granted to Grafana server administrator in self-hosted instances and to Organization admins in Grafana Cloud instances. -- Grafana instance running Grafana version 10.0 or later with [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) or [Grafana Cloud Pro or Advanced](https://grafana.com/docs/grafana//introduction/grafana-cloud/) license. +- Grafana instance running Grafana version 10.0 or later with [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. ## Steps To Configure SAML Authentication diff --git a/docs/sources/setup-grafana/configure-security/configure-request-security.md b/docs/sources/setup-grafana/configure-security/configure-request-security.md index 8dca935e928..8164799a6d8 100644 --- a/docs/sources/setup-grafana/configure-security/configure-request-security.md +++ b/docs/sources/setup-grafana/configure-security/configure-request-security.md @@ -19,7 +19,7 @@ Request security allows you to limit requests from the Grafana server by targeti This can be used to limit access to internal systems that the server Grafana runs on can access but that users of Grafana should not be able to access. This feature does not affect traffic from the Grafana users browser. {{< admonition type="note" >}} -Available in [Grafana Enterprise](../../../introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/). +Available in [Grafana Enterprise](../../../introduction/grafana-enterprise/) and to users on select Grafana Cloud account plans. For pricing information, visit our [pricing page](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} {{< admonition type="note" >}} diff --git a/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/_index.md b/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/_index.md index d3c2496f75b..f8e2ee47611 100644 --- a/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/_index.md +++ b/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/_index.md @@ -20,7 +20,7 @@ weight: 300 System for Cross-domain Identity Management (SCIM) is an open standard that allows automated user provisioning and management. With SCIM, you can automate the provisioning of users and groups from your identity provider to Grafana. {{< admonition type="note" >}} -Available in [Grafana Enterprise](/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/) in [public preview](https://grafana.com/docs/release-life-cycle/). +Available in [Grafana Enterprise](/docs/grafana//introduction/grafana-enterprise/) and select Grafana Cloud plans in [public preview](https://grafana.com/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available. {{< /admonition >}} diff --git a/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/configure-scim-with-azuread/_index.md b/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/configure-scim-with-azuread/_index.md index 1554484f45b..bc04f80fa52 100644 --- a/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/configure-scim-with-azuread/_index.md +++ b/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/configure-scim-with-azuread/_index.md @@ -21,7 +21,7 @@ weight: 320 # Configure SCIM with Azure AD {{< admonition type="note" >}} -Available in [Grafana Enterprise](/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/). +Available in [Grafana Enterprise](/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} {{< admonition type="warning" >}} @@ -49,7 +49,7 @@ Refer to the [SAML authentication with Azure AD documentation](../../configure-a Before configuring SCIM with Azure AD, ensure you have: -- Grafana Enterprise or Grafana Cloud Advanced +- Grafana Enterprise or a paid Grafana Cloud account with SCIM provisioning enabled. - Admin access to both Grafana and Azure AD - SCIM feature enabled in Grafana diff --git a/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/configure-scim-with-okta/_index.md b/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/configure-scim-with-okta/_index.md index 1555ae72754..50434391f7e 100644 --- a/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/configure-scim-with-okta/_index.md +++ b/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/configure-scim-with-okta/_index.md @@ -19,7 +19,7 @@ weight: 320 # Configure SCIM with Okta {{< admonition type="note" >}} -Available in [Grafana Enterprise](/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/). +Available in [Grafana Enterprise](/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} {{< admonition type="warning" >}} @@ -39,7 +39,7 @@ For more information, refer to the [feature toggles documentation](/docs/grafana Before configuring SCIM with Okta, ensure you have: -- Grafana Enterprise or Grafana Cloud Advanced +- Grafana Enterprise or a paid Grafana Cloud account with SCIM provisioning enabled. - Admin access to both Grafana and Okta - [SAML authentication configured with Okta](../../configure-authentication/saml/configure-saml-with-okta/) - SCIM feature enabled in Grafana diff --git a/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/manage-users-teams/_index.md b/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/manage-users-teams/_index.md index 2b3b0524884..ed9592e5929 100644 --- a/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/manage-users-teams/_index.md +++ b/docs/sources/setup-grafana/configure-security/configure-scim-provisioning/manage-users-teams/_index.md @@ -18,7 +18,7 @@ weight: 310 # Manage users and teams with SCIM {{< admonition type="note" >}} -Available in [Grafana Enterprise](/docs/grafana//introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/). +Available in [Grafana Enterprise](/docs/grafana//introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} {{< admonition type="warning" >}} diff --git a/docs/sources/setup-grafana/configure-security/export-logs.md b/docs/sources/setup-grafana/configure-security/export-logs.md index 7bb7b453fc7..f55336f8a67 100644 --- a/docs/sources/setup-grafana/configure-security/export-logs.md +++ b/docs/sources/setup-grafana/configure-security/export-logs.md @@ -18,7 +18,7 @@ weight: 900 # Export logs of usage insights {{< admonition type="note" >}} -Available in [Grafana Enterprise](../../../introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/). +Available in [Grafana Enterprise](../../../introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} By exporting usage logs to Loki, you can directly query them and create dashboards of the information that matters to you most, such as dashboard errors, most active organizations, or your top-10 most-used queries. This configuration is done for you in Grafana Cloud, with provisioned dashboards. Read about them in the [Grafana Cloud documentation](/docs/grafana-cloud/usage-insights/). diff --git a/docs/sources/setup-grafana/configure-security/planning-iam-strategy/index.md b/docs/sources/setup-grafana/configure-security/planning-iam-strategy/index.md index 34d3ccd8dcb..e4a44e54ed6 100644 --- a/docs/sources/setup-grafana/configure-security/planning-iam-strategy/index.md +++ b/docs/sources/setup-grafana/configure-security/planning-iam-strategy/index.md @@ -182,7 +182,7 @@ When connecting Grafana to an identity provider, it's important to think beyond Team sync is a feature that allows you to synchronize teams or groups from your authentication provider with teams in Grafana. This means that users of specific teams or groups in LDAP, OAuth, or SAML will be automatically added or removed as members of corresponding teams in Grafana. Whenever a user logs in, Grafana will check for any changes in the teams or groups of the authentication provider and update the user's teams in Grafana accordingly. This makes it easy to manage user permissions across multiple systems. {{< admonition type="note" >}} -Available in [Grafana Enterprise](../../../introduction/grafana-enterprise/) and [Grafana Cloud Advanced](/docs/grafana-cloud/). +Available in [Grafana Enterprise](../../../introduction/grafana-enterprise/) and to customers on select Grafana Cloud plans. For pricing information, visit [pricing](https://grafana.com/pricing/) or contact our sales team. {{< /admonition >}} {{< admonition type="note" >}} From 7e479689395650976f735cfd5528016048ec0652 Mon Sep 17 00:00:00 2001 From: Paul Marbach Date: Fri, 1 Aug 2025 12:27:53 -0400 Subject: [PATCH 33/89] TableNG: Wrap text for DataLinks and Pills (#108645) * TableNG: Wrap text for DataLinks and Pills; groundwork for max wrap length * disable editing max wrapped lines for now * disable wrap text line limit e2e * new i18n extract after commenting out input * wip * kill max wrapped lines for now * more cleanup * remove targeting classes added for max wrapped lines * fix Pill test * couple more style cleanups * fix e2es given these updates * add a couple tests * wip: tests * add tests * bump up capital letters in lorem ipsum * fix copy-pasta mistake * use a local count instead of getCellLinks * fix linting on test --- .betterer.results | 6 +- .../panels-suite/table-kitchenSink.spec.ts | 602 +++++++++--------- .../panels-suite/table-sparkline.spec.ts | 39 +- .../grafana-schema/src/common/common.gen.ts | 87 +-- packages/grafana-schema/src/common/table.cue | 25 +- .../Table/TableNG/Cells/PillCell.test.tsx | 152 ++--- .../Table/TableNG/Cells/PillCell.tsx | 92 ++- .../src/components/Table/TableNG/TableNG.tsx | 67 +- .../components/Table/TableNG/hooks.test.ts | 81 +-- .../src/components/Table/TableNG/hooks.ts | 13 +- .../src/components/Table/TableNG/types.ts | 11 +- .../components/Table/TableNG/utils.test.ts | 482 ++++++-------- .../src/components/Table/TableNG/utils.ts | 132 +++- .../table/cells/AutoCellOptionsEditor.tsx | 2 - .../ColorBackgroundCellOptionsEditor.tsx | 2 - .../table/table-new/TableCellOptionEditor.tsx | 21 +- .../table-new/cells/AutoCellOptionsEditor.tsx | 27 - .../ColorBackgroundCellOptionsEditor.tsx | 5 +- .../table-new/cells/TextWrapOptionsEditor.tsx | 29 + public/locales/en-US/grafana.json | 5 +- 20 files changed, 930 insertions(+), 950 deletions(-) delete mode 100644 public/app/plugins/panel/table/table-new/cells/AutoCellOptionsEditor.tsx create mode 100644 public/app/plugins/panel/table/table-new/cells/TextWrapOptionsEditor.tsx diff --git a/.betterer.results b/.betterer.results index 239af992de5..0493a87d6d3 100644 --- a/.betterer.results +++ b/.betterer.results @@ -3919,9 +3919,6 @@ exports[`better eslint`] = { "public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx:5381": [ [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"] ], - "public/app/plugins/panel/table/table-new/cells/AutoCellOptionsEditor.tsx:5381": [ - [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"] - ], "public/app/plugins/panel/table/table-new/cells/BarGaugeCellOptionsEditor.tsx:5381": [ [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"], [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"] @@ -3939,6 +3936,9 @@ exports[`better eslint`] = { [0, 0, 0, "\'VerticalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"], [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"] ], + "public/app/plugins/panel/table/table-new/cells/TextWrapOptionsEditor.tsx:5381": [ + [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"] + ], "public/app/plugins/panel/table/table-new/migrations.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"], diff --git a/e2e-playwright/panels-suite/table-kitchenSink.spec.ts b/e2e-playwright/panels-suite/table-kitchenSink.spec.ts index f386fb4175c..c7947fcd281 100644 --- a/e2e-playwright/panels-suite/table-kitchenSink.spec.ts +++ b/e2e-playwright/panels-suite/table-kitchenSink.spec.ts @@ -4,12 +4,7 @@ import { test, expect } from '@grafana/plugin-e2e'; const DASHBOARD_UID = 'dcb9f5e9-8066-4397-889e-864b99555dbb'; -test.use({ - viewport: { width: 2000, height: 1080 }, - featureToggles: { - tableNextGen: true, - }, -}); +test.use({ viewport: { width: 2000, height: 1080 }, featureToggles: { tableNextGen: true } }); // helper utils const waitForTableLoad = async (loc: Page | Locator) => { @@ -46,337 +41,324 @@ const getColumnIdx = async (loc: Page | Locator, columnName: string) => { return result; }; -test.describe( - 'Panels test: Table - Kitchen Sink', - { - tag: ['@panels'], - }, - () => { - test('Tests word wrap, hover overflow, and cell inspect', async ({ gotoDashboardPage, selectors, page }) => { - const dashboardPage = await gotoDashboardPage({ - uid: DASHBOARD_UID, - queryParams: new URLSearchParams({ editPanel: '1' }), - }); +test.describe('Panels test: Table - Kitchen Sink', { tag: ['@panels', '@table'] }, () => { + test('Tests word wrap, hover overflow, and cell inspect', async ({ gotoDashboardPage, selectors, page }) => { + const dashboardPage = await gotoDashboardPage({ + uid: DASHBOARD_UID, + queryParams: new URLSearchParams({ editPanel: '1' }), + }); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) - ).toBeVisible(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) + ).toBeVisible(); - // to avoid a race condition when counting up , wait for react-data-grid to finish rendering. - await waitForTableLoad(page); + // to avoid a race condition when counting up , wait for react-data-grid to finish rendering. + await waitForTableLoad(page); - const longTextColIdx = await getColumnIdx(page, 'Long Text'); + const longTextColIdx = await getColumnIdx(page, 'Long Text'); - // text wrapping is enabled by default on this panel. - await expect(getCellHeight(page, 1, longTextColIdx)).resolves.toBeGreaterThan(100); + // text wrapping is enabled by default on this panel. + await expect(getCellHeight(page, 1, longTextColIdx)).resolves.toBeGreaterThan(100); - // toggle the lorem ipsum column's wrap text toggle and confirm that the height shrinks. - await dashboardPage - .getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Wrap text')) - .last() - .click(); - await expect(getCellHeight(page, 1, longTextColIdx)).resolves.toBeLessThan(100); + // FIXME very bad selector to get the correct "wrap text" toggle here. + // toggle the lorem ipsum column's wrap text toggle and confirm that the height shrinks. + await page + .locator('[id="Override 13"]') + .locator(`[aria-label="${selectors.components.PanelEditor.OptionsPane.fieldLabel('Wrap text')}"]`) + .click(); + await expect(getCellHeight(page, 1, longTextColIdx)).resolves.toBeLessThan(100); - // test that hover overflow works. - const loremIpsumCell = await getCell(page, 1, longTextColIdx); - await loremIpsumCell.scrollIntoViewIfNeeded(); - await loremIpsumCell.hover(); - await expect(getCellHeight(page, 1, longTextColIdx)).resolves.toBeGreaterThan(100); - await (await getCell(page, 1, longTextColIdx + 1)).hover(); - await expect(getCellHeight(page, 1, longTextColIdx)).resolves.toBeLessThan(100); + // test that hover overflow works. + const loremIpsumCell = await getCell(page, 1, longTextColIdx); + await loremIpsumCell.scrollIntoViewIfNeeded(); + await loremIpsumCell.hover(); + await expect(getCellHeight(page, 1, longTextColIdx)).resolves.toBeGreaterThan(100); + await (await getCell(page, 1, longTextColIdx + 1)).hover(); + await expect(getCellHeight(page, 1, longTextColIdx)).resolves.toBeLessThan(100); - // enable cell inspect, confirm that hover no longer triggers. + // enable cell inspect, confirm that hover no longer triggers. + await dashboardPage + .getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Cell options Cell value inspect')) + .first() + .locator('label[for="custom.inspect"]') + .click(); + await loremIpsumCell.hover(); + await expect(getCellHeight(page, 1, longTextColIdx)).resolves.toBeLessThan(100); + + // click cell inspect, check that cell inspection pops open in the side as we'd expect. + await loremIpsumCell.getByLabel('Inspect value').click(); + const loremIpsumText = await loremIpsumCell.textContent(); + expect(loremIpsumText).toBeDefined(); + await expect(page.getByRole('dialog').getByText(loremIpsumText!)).toBeVisible(); + }); + + test('Tests visibility and display name via overrides', async ({ gotoDashboardPage, selectors, page }) => { + const dashboardPage = await gotoDashboardPage({ + uid: DASHBOARD_UID, + queryParams: new URLSearchParams({ editPanel: '1' }), + }); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) + ).toBeVisible(); + + // confirm that "State" column is hidden by default. + expect(page.getByRole('row').nth(0)).not.toContainText('State'); + + // toggle the "State" column visibility and test that it appears before re-hiding it. + // FIXME this selector is utterly godawful, but there's no way to give testIds or aria-labels or anything to + // the panel editor builder. we should fix that to make e2e's easier to write for our team. + const hideStateColumnSwitch = page.locator('[id="Override 12"]').locator('label').last(); + await hideStateColumnSwitch.click(); + expect(page.getByRole('row').nth(0)).toContainText('State'); + + // now change the display name of the "State" column. + // FIXME it would be good to have a better selector here too. + const displayNameInput = page.locator('[id="Override 12"]').locator('input[value="State"]').last(); + await displayNameInput.fill('State (renamed)'); + await displayNameInput.press('Enter'); + expect(page.getByRole('row').nth(0)).toContainText('State (renamed)'); + }); + + // we test niche cases for sorting, filtering, pagination, etc. in a unit tests already. + // we mainly want to test the happiest paths for these in e2es as well to check for integration + // issues, but the unit tests can confirm that the internal logic works as expected much more quickly and thoroughly. + // hashtag testing pyramid. + test('Tests sorting by column', async ({ gotoDashboardPage, selectors, page }) => { + const dashboardPage = await gotoDashboardPage({ + uid: DASHBOARD_UID, + queryParams: new URLSearchParams({ editPanel: '1' }), + }); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) + ).toBeVisible(); + + // click the "State" column header to sort it. + const stateColumnHeader = await getCell(page, 0, 1); + + await stateColumnHeader.getByText('Info').click(); + await expect(stateColumnHeader).toHaveAttribute('aria-sort', 'ascending'); + expect(getCell(page, 1, 1)).resolves.toContainText('down'); // down or down fast + + await stateColumnHeader.getByText('Info').click(); + await expect(stateColumnHeader).toHaveAttribute('aria-sort', 'descending'); + expect(getCell(page, 1, 1)).resolves.toContainText('up'); // up or up fast + + await stateColumnHeader.getByText('Info').click(); + await expect(stateColumnHeader).not.toHaveAttribute('aria-sort'); + }); + + test('Tests filtering within a column', async ({ gotoDashboardPage, selectors, page }) => { + const dashboardPage = await gotoDashboardPage({ + uid: DASHBOARD_UID, + queryParams: new URLSearchParams({ editPanel: '1' }), + }); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) + ).toBeVisible(); + + await waitForTableLoad(page); + + const infoColumnIdx = await getColumnIdx(page, 'Info'); + + const stateColumnHeader = page.getByRole('columnheader').nth(infoColumnIdx); + + // get the first value in the "State" column, filter it out, then check that it went away. + const firstStateValue = (await (await getCell(page, 1, infoColumnIdx)).textContent())!; + await stateColumnHeader.getByTestId(selectors.components.Panels.Visualization.TableNG.Filters.HeaderButton).click(); + const filterContainer = dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Visualization.TableNG.Filters.Container + ); + + await expect(filterContainer).toBeVisible(); + + // select all, then click the first value to unselect it, filtering it out. + await filterContainer.getByTestId(selectors.components.Panels.Visualization.TableNG.Filters.SelectAll).click(); + await filterContainer.getByTitle(firstStateValue, { exact: true }).locator('label').click(); + await filterContainer.getByRole('button', { name: 'Ok' }).click(); + + // make sure the filter container closed when we clicked "Ok". + await expect(filterContainer).not.toBeVisible(); + + // did it actually filter out our value? + await expect(getCell(page, 1, infoColumnIdx)).resolves.not.toHaveText(firstStateValue); + }); + + test('Tests pagination, row height adjustment', async ({ gotoDashboardPage, selectors, page }) => { + const rowRe = /([\d]+) - ([\d]+) of ([\d]+) rows/; + const getRowStatus = async (page: Page | Locator) => { + const text = (await page.getByText(rowRe).textContent()) ?? ''; + const match = text.match(rowRe); + return { + start: parseInt(match?.[1] ?? '0', 10), + end: parseInt(match?.[2] ?? '0', 10), + total: parseInt(match?.[3] ?? '0', 10), + }; + }; + + const dashboardPage = await gotoDashboardPage({ + uid: DASHBOARD_UID, + queryParams: new URLSearchParams({ editPanel: '1' }), + }); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) + ).toBeVisible(); + + await page + .getByLabel(selectors.components.PanelEditor.OptionsPane.fieldLabel(`Enable pagination`), { exact: true }) + .click(); + + // because of text wrapping, we're guaranteed to only be showing a single row when we enable pagination. + await expect(page.getByText(/([\d]+) - ([\d]+) of ([\d]+) rows/)).toBeVisible(); + + // FIXME horrible selector for the "Wrap text" toggle for the "Long text" column. + await page + .locator('[id="Override 13"]') + .locator(`[aria-label="${selectors.components.PanelEditor.OptionsPane.fieldLabel('Wrap text')}"]`) + .click(); + + // any number of rows that is not "1" is allowed here, we don't want to police the exact number of rows that + // are rendered since there are tons of factors which could effect this. we do want to grab this number for comparison + // in a second, though. + const smallRowStatus = await getRowStatus(page); + expect(smallRowStatus.end).toBeGreaterThan(1); + expect(page.getByRole('grid').getByRole('row')).toHaveCount(smallRowStatus.end + 1); + + // change cell height to Large + await dashboardPage + .getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Table Cell height')) + .locator('input') + .last() + .click(); + const largeRowStatus = await getRowStatus(page); + expect(largeRowStatus.end).toBeLessThan(smallRowStatus.end); + expect(page.getByRole('grid').getByRole('row')).toHaveCount(largeRowStatus.end + 1); + + // click a page over with the directional nav + await page.getByLabel('next page').click(); + const nextPageStatus = await getRowStatus(page); + expect(nextPageStatus.start).toBe(largeRowStatus.end + 1); + expect(nextPageStatus.end).toBe(largeRowStatus.end * 2); + expect(nextPageStatus.total).toBe(largeRowStatus.total); + + // click a page number + await page.getByTestId('data-testid panel content').getByRole('navigation').getByText('4', { exact: true }).click(); + const fourthPageStatus = await getRowStatus(page); + expect(fourthPageStatus.start).toBe(largeRowStatus.end * 3 + 1); + expect(fourthPageStatus.end).toBe(largeRowStatus.end * 4); + expect(fourthPageStatus.total).toBe(largeRowStatus.total); + }); + + test.skip('Tests DataLinks (single and multi) and actions', async ({ gotoDashboardPage, selectors, page }) => { + const addDataLink = async (title: string, url: string) => { await dashboardPage .getByGrafanaSelector( - selectors.components.PanelEditor.OptionsPane.fieldLabel('Cell options Cell value inspect') + selectors.components.PanelEditor.OptionsPane.fieldLabel('Data links and actions Data links') ) - .first() - .locator('label[for="custom.inspect"]') + .locator('button') + .filter({ hasText: 'Add link' }) .click(); - await loremIpsumCell.hover(); - await expect(getCellHeight(page, 1, longTextColIdx)).resolves.toBeLessThan(100); - // click cell inspect, check that cell inspection pops open in the side as we'd expect. - await loremIpsumCell.getByLabel('Inspect value').click(); - const loremIpsumText = await loremIpsumCell.textContent(); - expect(loremIpsumText).toBeDefined(); - await expect(page.getByRole('dialog').getByText(loremIpsumText!)).toBeVisible(); + // DataLinks dialog has popped open - fill it in and add a global datalink. + await expect(page.getByRole('dialog')).toBeVisible(); + await page.getByRole('dialog').locator('#link-title').fill(title); + await page.getByRole('dialog').locator('#data-link-input [contenteditable="true"]').focus(); + await page.getByRole('dialog').locator('#data-link-input [contenteditable="true"]').fill(url); + await page.getByRole('dialog').locator('#data-link-input [contenteditable="true"]').blur(); + await page.getByRole('dialog').locator('button[aria-disabled="false"]').filter({ hasText: 'Save' }).click(); + await expect(page.getByRole('dialog')).not.toBeVisible(); + }; + + const dashboardPage = await gotoDashboardPage({ + uid: DASHBOARD_UID, + queryParams: new URLSearchParams({ editPanel: '1' }), }); - test('Tests visibility and display name via overrides', async ({ gotoDashboardPage, selectors, page }) => { - const dashboardPage = await gotoDashboardPage({ - uid: DASHBOARD_UID, - queryParams: new URLSearchParams({ editPanel: '1' }), - }); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) + ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) - ).toBeVisible(); + // disable text wrapping for this test to make it easier to click the links, the long lorem ipsum + // can push the links off the screen. + // FIXME very bad selector to get the correct "wrap text" toggle here. + await page + .locator('[id="Override 13"]') + .locator(`[aria-label="${selectors.components.PanelEditor.OptionsPane.fieldLabel('Wrap text')}"]`) + .click(); - // confirm that "State" column is hidden by default. - expect(page.getByRole('row').nth(0)).not.toContainText('State'); + const infoColumnIdx = await getColumnIdx(page, 'Info'); + const pillColIdx = await getColumnIdx(page, 'Pills'); + const dataLinkColIdx = await getColumnIdx(page, 'Data Link'); - // toggle the "State" column visibility and test that it appears before re-hiding it. - // FIXME this selector is utterly godawful, but there's no way to give testIds or aria-labels or anything to - // the panel editor builder. we should fix that to make e2e's easier to write for our team. - const hideStateColumnSwitch = page.locator('[id="Override 12"]').locator('label').last(); - await hideStateColumnSwitch.click(); - expect(page.getByRole('row').nth(0)).toContainText('State'); + // Info column has a single DataLink by default. + const infoCell = await getCell(page, 1, infoColumnIdx); + await expect(infoCell.locator('a')).toBeVisible(); + expect(infoCell.locator('a')).toHaveAttribute('href'); + expect(infoCell.locator('a')).not.toHaveAttribute('aria-haspopup'); - // now change the display name of the "State" column. - // FIXME it would be good to have a better selector here too. - const displayNameInput = page.locator('[id="Override 12"]').locator('input[value="State"]').last(); - await displayNameInput.fill('State (renamed)'); - await displayNameInput.press('Enter'); - expect(page.getByRole('row').nth(0)).toContainText('State (renamed)'); - }); + // now, add a DataLink to the whole table + await addDataLink('Test link', 'https://grafana.com'); - // we test niche cases for sorting, filtering, pagination, etc. in a unit tests already. - // we mainly want to test the happiest paths for these in e2es as well to check for integration - // issues, but the unit tests can confirm that the internal logic works as expected much more quickly and thoroughly. - // hashtag testing pyramid. - test('Tests sorting by column', async ({ gotoDashboardPage, selectors, page }) => { - const dashboardPage = await gotoDashboardPage({ - uid: DASHBOARD_UID, - queryParams: new URLSearchParams({ editPanel: '1' }), - }); + // add a DataLink to the whole table, all cells will now have a single link. + const colCount = await page.getByRole('row').nth(1).getByRole('gridcell').count(); + for (let colIdx = 0; colIdx < colCount; colIdx++) { + // - pills column currently does not support DataLinks. + // - we don't apply DataLinks to the DataLinks column itself, since they're rendered inside. + if (colIdx === pillColIdx || colIdx === dataLinkColIdx) { + continue; + } - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) - ).toBeVisible(); + const cell = await getCell(page, 1, colIdx); + await expect(cell.locator('a')).toBeVisible(); + expect(cell.locator('a')).toHaveAttribute('href'); + expect(cell.locator('a')).not.toHaveAttribute('aria-haspopup', 'menu'); + } - // click the "State" column header to sort it. - const stateColumnHeader = await getCell(page, 0, 1); + const headerContainer = dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer); - await stateColumnHeader.getByText('Info').click(); - await expect(stateColumnHeader).toHaveAttribute('aria-sort', 'ascending'); - expect(getCell(page, 1, 1)).resolves.toContainText('down'); // down or down fast + // add another data link. now we'll check that the multi-link popups work. + await addDataLink('Another test link', 'https://grafana.com/foo'); - await stateColumnHeader.getByText('Info').click(); - await expect(stateColumnHeader).toHaveAttribute('aria-sort', 'descending'); - expect(getCell(page, 1, 1)).resolves.toContainText('up'); // up or up fast - - await stateColumnHeader.getByText('Info').click(); - await expect(stateColumnHeader).not.toHaveAttribute('aria-sort'); - }); - - test('Tests filtering within a column', async ({ gotoDashboardPage, selectors, page }) => { - const dashboardPage = await gotoDashboardPage({ - uid: DASHBOARD_UID, - queryParams: new URLSearchParams({ editPanel: '1' }), - }); - - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) - ).toBeVisible(); - - await waitForTableLoad(page); - - const infoColumnIdx = await getColumnIdx(page, 'Info'); - - const stateColumnHeader = page.getByRole('columnheader').nth(infoColumnIdx); - - // get the first value in the "State" column, filter it out, then check that it went away. - const firstStateValue = (await (await getCell(page, 1, infoColumnIdx)).textContent())!; - await stateColumnHeader - .getByTestId(selectors.components.Panels.Visualization.TableNG.Filters.HeaderButton) - .click(); - const filterContainer = dashboardPage.getByGrafanaSelector( - selectors.components.Panels.Visualization.TableNG.Filters.Container - ); - - await expect(filterContainer).toBeVisible(); - - // select all, then click the first value to unselect it, filtering it out. - await filterContainer.getByTestId(selectors.components.Panels.Visualization.TableNG.Filters.SelectAll).click(); - await filterContainer.getByTitle(firstStateValue, { exact: true }).locator('label').click(); - await filterContainer.getByRole('button', { name: 'Ok' }).click(); - - // make sure the filter container closed when we clicked "Ok". - await expect(filterContainer).not.toBeVisible(); - - // did it actually filter out our value? - await expect(getCell(page, 1, infoColumnIdx)).resolves.not.toHaveText(firstStateValue); - }); - - test('Tests pagination, row height adjustment', async ({ gotoDashboardPage, selectors, page }) => { - const rowRe = /([\d]+) - ([\d]+) of ([\d]+) rows/; - const getRowStatus = async (page: Page | Locator) => { - const text = (await page.getByText(rowRe).textContent()) ?? ''; - const match = text.match(rowRe); - return { - start: parseInt(match?.[1] ?? '0', 10), - end: parseInt(match?.[2] ?? '0', 10), - total: parseInt(match?.[3] ?? '0', 10), - }; - }; - - const dashboardPage = await gotoDashboardPage({ - uid: DASHBOARD_UID, - queryParams: new URLSearchParams({ editPanel: '1' }), - }); - - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) - ).toBeVisible(); - - await page - .getByLabel(selectors.components.PanelEditor.OptionsPane.fieldLabel(`Enable pagination`), { exact: true }) - .click(); - - // because of text wrapping, we're guaranteed to only be showing a single row when we enable pagination. - await expect(page.getByText(/([\d]+) - ([\d]+) of ([\d]+) rows/)).toBeVisible(); - - // disable text wrap and see the number of rows. - await dashboardPage - .getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Wrap text')) - .last() - .click(); - - // any number of rows that is not "1" is allowed here, we don't want to police the exact number of rows that - // are rendered since there are tons of factors which could effect this. we do want to grab this number for comparison - // in a second, though. - const smallRowStatus = await getRowStatus(page); - expect(smallRowStatus.end).toBeGreaterThan(1); - expect(page.getByRole('grid').getByRole('row')).toHaveCount(smallRowStatus.end + 1); - - // change cell height to Large - await dashboardPage - .getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Table Cell height')) - .locator('input') - .last() - .click(); - const largeRowStatus = await getRowStatus(page); - expect(largeRowStatus.end).toBeLessThan(smallRowStatus.end); - expect(page.getByRole('grid').getByRole('row')).toHaveCount(largeRowStatus.end + 1); - - // click a page over with the directional nav - await page.getByLabel('next page').click(); - const nextPageStatus = await getRowStatus(page); - expect(nextPageStatus.start).toBe(largeRowStatus.end + 1); - expect(nextPageStatus.end).toBe(largeRowStatus.end * 2); - expect(nextPageStatus.total).toBe(largeRowStatus.total); - - // click a page number - await page - .getByTestId('data-testid panel content') - .getByRole('navigation') - .getByText('4', { exact: true }) - .click(); - const fourthPageStatus = await getRowStatus(page); - expect(fourthPageStatus.start).toBe(largeRowStatus.end * 3 + 1); - expect(fourthPageStatus.end).toBe(largeRowStatus.end * 4); - expect(fourthPageStatus.total).toBe(largeRowStatus.total); - }); - - // TODO: skipping this test for now due to flakiness in adding DataLinks. - test.skip('Tests DataLinks (single and multi) and actions', async ({ gotoDashboardPage, selectors, page }) => { - const addDataLink = async (title: string, url: string) => { - await dashboardPage - .getByGrafanaSelector( - selectors.components.PanelEditor.OptionsPane.fieldLabel('Data links and actions Data links') - ) - .locator('button') - .filter({ hasText: 'Add link' }) - .click(); - - // DataLinks dialog has popped open - fill it in and add a global datalink. - await expect(page.getByRole('dialog')).toBeVisible(); - await page.getByRole('dialog').locator('#link-title').fill(title); - await page.getByRole('dialog').locator('#data-link-input [contenteditable="true"]').focus(); - await page.getByRole('dialog').locator('#data-link-input [contenteditable="true"]').fill(url); - await page.getByRole('dialog').locator('#data-link-input [contenteditable="true"]').blur(); - await page.getByRole('dialog').locator('button[aria-disabled="false"]').filter({ hasText: 'Save' }).click(); - await expect(page.getByRole('dialog')).not.toBeVisible(); - }; - - const dashboardPage = await gotoDashboardPage({ - uid: DASHBOARD_UID, - queryParams: new URLSearchParams({ editPanel: '1' }), - }); - - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) - ).toBeVisible(); - - // disable text wrapping for this test to make it easier to click the links, the long lorem ipsum - // can push the links off the screen. - await dashboardPage - .getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Wrap text')) - .last() - .click(); - - const infoColumnIdx = await getColumnIdx(page, 'Info'); - const pillColIdx = await getColumnIdx(page, 'Pills'); - const dataLinkColIdx = await getColumnIdx(page, 'Data Link'); - - // Info column has a single DataLink by default. - const infoCell = await getCell(page, 1, infoColumnIdx); - await expect(infoCell.locator('a')).toBeVisible(); - expect(infoCell.locator('a')).toHaveAttribute('href'); - expect(infoCell.locator('a')).not.toHaveAttribute('aria-haspopup'); - - // now, add a DataLink to the whole table - await addDataLink('Test link', 'https://grafana.com'); - - // add a DataLink to the whole table, all cells will now have a single link. - const colCount = await page.getByRole('row').nth(1).getByRole('gridcell').count(); - for (let colIdx = 0; colIdx < colCount; colIdx++) { - // - pills column currently does not support DataLinks. - // - we don't apply DataLinks to the DataLinks column itself, since they're rendered inside. - if (colIdx === pillColIdx || colIdx === dataLinkColIdx) { - continue; - } - - const cell = await getCell(page, 1, colIdx); - await expect(cell.locator('a')).toBeVisible(); - expect(cell.locator('a')).toHaveAttribute('href'); + // loop thru the columns, click the links, observe that the tooltip appears, and close the tooltip. + for (let colIdx = 0; colIdx < colCount; colIdx++) { + const cell = await getCell(page, 1, colIdx); + if (colIdx === infoColumnIdx) { + // the Info column should still have its single link. expect(cell.locator('a')).not.toHaveAttribute('aria-haspopup', 'menu'); + continue; } - const headerContainer = dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer); - - // add another data link. now we'll check that the multi-link popups work. - await addDataLink('Another test link', 'https://grafana.com/foo'); - - // loop thru the columns, click the links, observe that the tooltip appears, and close the tooltip. - for (let colIdx = 0; colIdx < colCount; colIdx++) { - const cell = await getCell(page, 1, colIdx); - if (colIdx === infoColumnIdx) { - // the Info column should still have its single link. - expect(cell.locator('a')).not.toHaveAttribute('aria-haspopup', 'menu'); - continue; - } - - // - pills column currently does not support DataLinks. - // - we don't apply DataLinks to the DataLinks column itself, since they're rendered inside. - if (colIdx === pillColIdx || colIdx === dataLinkColIdx) { - continue; - } - - await cell.locator('a').click({ force: true }); - await expect(page.getByTestId(selectors.components.DataLinksActionsTooltip.tooltipWrapper)).toBeVisible(); - - await headerContainer.click(); // convenient just to click the header to close the tooltip. - await expect(page.getByTestId(selectors.components.DataLinksActionsTooltip.tooltipWrapper)).not.toBeVisible(); + // - pills column currently does not support DataLinks. + // - we don't apply DataLinks to the DataLinks column itself, since they're rendered inside. + if (colIdx === pillColIdx || colIdx === dataLinkColIdx) { + continue; } - // add an Action to the whole table and check that the action button is added to the tooltip. - // TODO -- saving for another day. + await cell.locator('a').click({ force: true }); + await expect(page.getByTestId(selectors.components.DataLinksActionsTooltip.tooltipWrapper)).toBeVisible(); + + await headerContainer.click(); // convenient just to click the header to close the tooltip. + await expect(page.getByTestId(selectors.components.DataLinksActionsTooltip.tooltipWrapper)).not.toBeVisible(); + } + + // add an Action to the whole table and check that the action button is added to the tooltip. + // TODO -- saving for another day. + }); + + test('Empty Table panel', async ({ gotoDashboardPage, selectors }) => { + const dashboardPage = await gotoDashboardPage({ + uid: DASHBOARD_UID, + queryParams: new URLSearchParams({ editPanel: '2' }), }); - test('Empty Table panel', async ({ gotoDashboardPage, selectors }) => { - const dashboardPage = await gotoDashboardPage({ - uid: DASHBOARD_UID, - queryParams: new URLSearchParams({ editPanel: '2' }), - }); - - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.PanelDataErrorMessage) - ).toBeVisible(); - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) - ).not.toBeVisible(); - }); - } -); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.PanelDataErrorMessage) + ).toBeVisible(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) + ).not.toBeVisible(); + }); +}); diff --git a/e2e-playwright/panels-suite/table-sparkline.spec.ts b/e2e-playwright/panels-suite/table-sparkline.spec.ts index 16dc55f3df4..d2ac814e2df 100644 --- a/e2e-playwright/panels-suite/table-sparkline.spec.ts +++ b/e2e-playwright/panels-suite/table-sparkline.spec.ts @@ -1,29 +1,18 @@ import { test, expect } from '@grafana/plugin-e2e'; -test.use({ - viewport: { width: 1280, height: 1080 }, - featureToggles: { - tableNextGen: true, - }, -}); +test.use({ viewport: { width: 1280, height: 1080 }, featureToggles: { tableNextGen: true } }); -test.describe( - 'Panels test: Table - Sparkline', - { - tag: ['@panels'], - }, - () => { - test('Tests sparkline tables are successfully rendered', async ({ gotoDashboardPage, selectors, page }) => { - await gotoDashboardPage({ - uid: 'd6373b49-1957-4f00-9218-ee2120d3ecd9', - queryParams: new URLSearchParams({ editPanel: '2' }), - }); - - await expect(page.getByRole('grid')).toBeVisible(); - - const uplotCount = await page.locator('.uplot').count(); - const rowCount = await page.getByRole('row').count(); - expect(uplotCount).toBe(rowCount - 1); +test.describe('Panels test: Table - Sparkline', { tag: ['@panels', '@table'] }, () => { + test('Tests sparkline tables are successfully rendered', async ({ gotoDashboardPage, selectors, page }) => { + await gotoDashboardPage({ + uid: 'd6373b49-1957-4f00-9218-ee2120d3ecd9', + queryParams: new URLSearchParams({ editPanel: '2' }), }); - } -); + + await expect(page.getByRole('grid')).toBeVisible(); + + const uplotCount = await page.locator('.uplot').count(); + const rowCount = await page.getByRole('row').count(); + expect(uplotCount).toBe(rowCount - 1); + }); +}); diff --git a/packages/grafana-schema/src/common/common.gen.ts b/packages/grafana-schema/src/common/common.gen.ts index b98c83c9525..9b229c4d1e9 100644 --- a/packages/grafana-schema/src/common/common.gen.ts +++ b/packages/grafana-schema/src/common/common.gen.ts @@ -722,6 +722,16 @@ export enum TableCellBackgroundDisplayMode { Gradient = 'gradient', } +/** + * Whenever we add text wrapping, we should add all text wrapping options at once + */ +export interface TableWrapTextOptions { + /** + * if true, wrap the text content of the cell + */ + wrapText?: boolean; +} + /** * Sort by field state */ @@ -755,17 +765,15 @@ export const defaultTableFooterOptions: Partial = { /** * Auto mode table cell options */ -export interface TableAutoCellOptions { +export interface TableAutoCellOptions extends TableWrapTextOptions { type: TableCellDisplayMode.Auto; - wrapText?: boolean; } /** * Colored text cell options */ -export interface TableColorTextCellOptions { +export interface TableColorTextCellOptions extends TableWrapTextOptions { type: TableCellDisplayMode.ColorText; - wrapText?: boolean; } /** @@ -787,7 +795,7 @@ export interface TableImageCellOptions { /** * Show data links in the cell */ -export interface TableDataLinksCellOptions { +export interface TableDataLinksCellOptions extends TableWrapTextOptions { type: TableCellDisplayMode.DataLinks; } @@ -818,11 +826,14 @@ export interface TableSparklineCellOptions extends GraphFieldConfig { /** * Colored background cell options */ -export interface TableColoredBackgroundCellOptions { +export interface TableColoredBackgroundCellOptions extends TableWrapTextOptions { applyToRow?: boolean; mode?: TableCellBackgroundDisplayMode; type: TableCellDisplayMode.ColorBackground; - wrapText?: boolean; +} + +export interface TablePillCellOptions extends TableWrapTextOptions { + type: TableCellDisplayMode.Pill; } /** @@ -841,37 +852,6 @@ export enum TableCellHeight { */ export type TableCellOptions = (TableAutoCellOptions | TableSparklineCellOptions | TableBarGaugeCellOptions | TableColoredBackgroundCellOptions | TableColorTextCellOptions | TableImageCellOptions | TablePillCellOptions | TableDataLinksCellOptions | TableActionsCellOptions | TableJsonViewCellOptions); -/** - * Field options for each field within a table (e.g 10, "The String", 64.20, etc.) - * Generally defines alignment, filtering capabilties, display options, etc. - */ -export interface TableFieldOptions { - align: FieldTextAlignment; - cellOptions: TableCellOptions; - /** - * This field is deprecated in favor of using cellOptions - */ - displayMode?: TableCellDisplayMode; - filterable?: boolean; - hidden?: boolean; // ?? default is missing or false ?? - /** - * Hides any header for a column, useful for columns that show some static content or buttons. - */ - hideHeader?: boolean; - inspect: boolean; - minWidth?: number; - width?: number; - /** - * Enables text wrapping for column headers - */ - wrapHeaderText?: boolean; -} - -export const defaultTableFieldOptions: Partial = { - align: 'auto', - inspect: false, -}; - /** * Use UTC/GMT timezone */ @@ -987,10 +967,37 @@ export enum ComparisonOperation { NEQ = 'neq', } -export interface TablePillCellOptions { - type: TableCellDisplayMode.Pill; +/** + * Field options for each field within a table (e.g 10, "The String", 64.20, etc.) + * Generally defines alignment, filtering capabilties, display options, etc. + */ +export interface TableFieldOptions { + align: FieldTextAlignment; + cellOptions: TableCellOptions; + /** + * This field is deprecated in favor of using cellOptions + */ + displayMode?: TableCellDisplayMode; + filterable?: boolean; + hidden?: boolean; // ?? default is missing or false ?? + /** + * Hides any header for a column, useful for columns that show some static content or buttons. + */ + hideHeader?: boolean; + inspect: boolean; + minWidth?: number; + width?: number; + /** + * Enables text wrapping for column headers + */ + wrapHeaderText?: boolean; } +export const defaultTableFieldOptions: Partial = { + align: 'auto', + inspect: false, +}; + /** * A specific timezone from https://en.wikipedia.org/wiki/Tz_database */ diff --git a/packages/grafana-schema/src/common/table.cue b/packages/grafana-schema/src/common/table.cue index acf4a6b7480..0a15fb926b5 100644 --- a/packages/grafana-schema/src/common/table.cue +++ b/packages/grafana-schema/src/common/table.cue @@ -11,6 +11,12 @@ TableCellDisplayMode: "auto" | "color-text" | "color-background" | "color-backgr // or a gradient. TableCellBackgroundDisplayMode: "basic" | "gradient" @cuetsy(kind="enum",memberNames="Basic|Gradient") +// Whenever we add text wrapping, we should add all text wrapping options at once +TableWrapTextOptions: { + // if true, wrap the text content of the cell + wrapText?: bool +} @cuetsy(kind="interface") + // Sort by field state TableSortByFieldState: { // Sets the display name of the field to sort by @@ -31,14 +37,12 @@ TableFooterOptions: { // Auto mode table cell options TableAutoCellOptions: { type: TableCellDisplayMode & "auto" - wrapText?: bool -} @cuetsy(kind="interface") +} & TableWrapTextOptions @cuetsy(kind="interface") // Colored text cell options TableColorTextCellOptions: { type: TableCellDisplayMode & "color-text" - wrapText?: bool -} @cuetsy(kind="interface") +} & TableWrapTextOptions @cuetsy(kind="interface") // Json view cell options TableJsonViewCellOptions: { @@ -55,7 +59,7 @@ TableImageCellOptions: { // Show data links in the cell TableDataLinksCellOptions: { type: TableCellDisplayMode & "data-links" -} @cuetsy(kind="interface") +} & TableWrapTextOptions @cuetsy(kind="interface") // Show actions in the cell TableActionsCellOptions: { @@ -81,8 +85,11 @@ TableColoredBackgroundCellOptions: { type: TableCellDisplayMode & "color-background" mode?: TableCellBackgroundDisplayMode applyToRow?: bool - wrapText?: bool -} @cuetsy(kind="interface") +} & TableWrapTextOptions @cuetsy(kind="interface") + +TablePillCellOptions: { + type: TableCellDisplayMode & "pill" +} & TableWrapTextOptions @cuetsy(kind="interface") // Height of a table cell TableCellHeight: "sm" | "md" | "lg" | "auto" @cuetsy(kind="enum") @@ -108,7 +115,3 @@ TableFieldOptions: { // Enables text wrapping for column headers wrapHeaderText?: bool } @cuetsy(kind="interface") - -TablePillCellOptions: { - type: TableCellDisplayMode & "pill" -} @cuetsy(kind="interface") diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.test.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.test.tsx index b7249e88b2b..55b9d3e19ba 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.test.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.test.tsx @@ -1,54 +1,18 @@ import { render, RenderResult } from '@testing-library/react'; -import { DataFrame, Field, FieldType, GrafanaTheme2, MappingType, createTheme } from '@grafana/data'; -import { TableCellDisplayMode, TablePillCellOptions } from '@grafana/schema'; +import { Field, FieldType, MappingType, createTheme } from '@grafana/data'; -import { mockThemeContext } from '../../../../themes/ThemeContext'; - -import { PillCell, getStyles } from './PillCell'; +import { PillCell } from './PillCell'; describe('PillCell', () => { - let pillClass: string; - let restoreThemeContext: () => void; + const theme = createTheme(); - beforeEach(() => { - pillClass = getStyles(createTheme()).pill; - restoreThemeContext = mockThemeContext(createTheme()); - }); - - afterEach(() => { - restoreThemeContext(); - }); - - const mockCellOptions: TablePillCellOptions = { - type: TableCellDisplayMode.Pill, - }; - - const mockField: Field = { + const fieldWithValues = (values: unknown[]): Field => ({ name: 'test', type: FieldType.string, - values: [], + values: values, config: {}, - }; - - const mockFrame: DataFrame = { - name: 'test', - fields: [mockField], - length: 1, - }; - - const defaultProps = { - field: mockField, - justifyContent: 'flex-start' as const, - cellOptions: mockCellOptions, - rowIdx: 0, - frame: mockFrame, - height: 30, - width: 100, - theme: {} as GrafanaTheme2, - cellInspect: false, - showFilters: false, - }; + }); const ser = new XMLSerializer(); @@ -60,88 +24,84 @@ describe('PillCell', () => { // one class for lightTextPill, darkTextPill describe('Color by hash (classic palette)', () => { - const props = { ...defaultProps }; - it('single value', () => { expectHTML( - render(), - `value1` + render(), + `value1` ); }); it('empty string', () => { - expectHTML(render(), ''); + expectHTML(render(), ''); }); - // it('null', () => { - // expectHTML( - // render(), - // 'value1' - // ); - // }); + it('null', () => { + const { container } = render(); + expect(container).toBeEmptyDOMElement(); + }); it('CSV values', () => { expectHTML( - render(), + render(), ` - value1 - value2 - value3 + value1 + value2 + value3 ` ); }); it('JSON array values', () => { expectHTML( - render(), + render(), ` - value1 - value2 - value3 + value1 + value2 + value3 ` ); }); - - // TODO: handle null values? }); describe('Color by value mappings', () => { - const field: Field = { - ...mockField, - config: { - ...mockField.config, - mappings: [ - { - type: MappingType.ValueToText, - options: { - success: { color: '#00FF00' }, - error: { color: '#FF0000' }, - warning: { color: '#FFFF00' }, - }, - }, - ], - }, - display: (value: unknown) => ({ - text: String(value), - color: - value === 'success' ? '#00FF00' : value === 'error' ? '#FF0000' : value === 'warning' ? '#FFFF00' : '#FF780A', - numeric: 0, - }), - }; - - const props = { - ...defaultProps, - field, - }; - it('CSV values', () => { + const mockField = fieldWithValues(['success,error,warning,unknown']); + const field = { + ...mockField, + config: { + ...mockField.config, + mappings: [ + { + type: MappingType.ValueToText, + options: { + success: { color: '#00FF00' }, + error: { color: '#FF0000' }, + warning: { color: '#FFFF00' }, + }, + }, + ], + }, + display: (value: unknown) => ({ + text: String(value), + color: + value === 'success' + ? '#00FF00' + : value === 'error' + ? '#FF0000' + : value === 'warning' + ? '#FFFF00' + : '#FF780A', + numeric: 0, + }), + } satisfies Field; + expectHTML( - render(), + render(), ` - success - error - warning - unknown + success + error + warning + unknown ` ); }); diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.tsx index c1ca23b7f69..35b759aa224 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.tsx @@ -1,4 +1,3 @@ -import { css } from '@emotion/css'; import { useMemo } from 'react'; import { @@ -8,11 +7,36 @@ import { Field, getColorByStringHash, FALLBACK_COLOR, + fieldColorModeRegistry, } from '@grafana/data'; import { FieldColorModeId } from '@grafana/schema'; -import { useStyles2, useTheme2 } from '../../../../themes/ThemeContext'; -import { TableCellRendererProps } from '../types'; +import { PillCellProps, TableCellValue } from '../types'; + +export function PillCell({ rowIdx, field, theme }: PillCellProps) { + const value = field.values[rowIdx]; + const pills: Pill[] = useMemo(() => { + const pillValues = inferPills(value); + return pillValues.length > 0 ? createPills(pillValues, field, theme) : []; + }, [value, field, theme]); + + if (pills.length === 0) { + return null; + } + + return pills.map((pill) => ( + + {pill.value} + + )); +} interface Pill { value: string; @@ -21,6 +45,9 @@ interface Pill { color: string; } +const SPLIT_RE = /\s*,\s*/; +const TRANSPARENT = 'rgba(0,0,0,0)'; + function createPills(pillValues: string[], field: Field, theme: GrafanaTheme2): Pill[] { return pillValues.map((pill, index) => { const bgColor = getPillColor(pill, field, theme); @@ -34,38 +61,13 @@ function createPills(pillValues: string[], field: Field, theme: GrafanaTheme2): }); } -export function PillCell({ value, field }: TableCellRendererProps) { - const styles = useStyles2(getStyles); - const theme = useTheme2(); - - const pills: Pill[] = useMemo(() => { - const pillValues = inferPills(String(value)); - return createPills(pillValues, field, theme); - }, [value, field, theme]); - - return pills.map((pill) => ( - - {pill.value} - - )); -} - -const SPLIT_RE = /\s*,\s*/; -const TRANSPARENT = 'rgba(0,0,0,0)'; - -export function inferPills(value: string): string[] { - if (value === '') { +export function inferPills(rawValue: TableCellValue): string[] { + if (rawValue === '' || rawValue == null) { return []; } + const value = String(rawValue); + if (value[0] === '[') { try { return JSON.parse(value); @@ -77,6 +79,7 @@ export function inferPills(value: string): string[] { return value.trim().split(SPLIT_RE); } +// FIXME: this does not yet support "shades of a color" function getPillColor(value: string, field: Field, theme: GrafanaTheme2): string { const cfg = field.config; @@ -88,19 +91,14 @@ function getPillColor(value: string, field: Field, theme: GrafanaTheme2): string return theme.visualization.getColorByName(cfg.color?.fixedColor ?? FALLBACK_COLOR); } - // TODO: instead of classicColors we need to pull colors from theme, same way as FieldColorModeId.PaletteClassicByName (see fieldColor.ts) - return getColorByStringHash(classicColors, value); -} + let colors = classicColors; + const configuredColor = cfg.color; + if (configuredColor) { + const mode = fieldColorModeRegistry.get(configuredColor.mode); + if (typeof mode?.getColors === 'function') { + colors = mode.getColors(theme); + } + } -export const getStyles = (theme: GrafanaTheme2) => ({ - pill: css({ - display: 'inline-block', - padding: theme.spacing(0.25, 0.75), - marginInlineEnd: theme.spacing(0.5), - marginBlock: theme.spacing(0.5), - borderRadius: theme.shape.radius.default, - fontSize: theme.typography.bodySmall.fontSize, - lineHeight: theme.typography.bodySmall.lineHeight, - whiteSpace: 'nowrap', - }), -}); + return getColorByStringHash(colors, value); +} diff --git a/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx b/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx index 40cd49278d3..8d6c9bb5ef8 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx @@ -367,14 +367,15 @@ export function TableNG(props: TableNGProps) { case TableCellDisplayMode.ColorText: case TableCellDisplayMode.DataLinks: case TableCellDisplayMode.JSONView: + case TableCellDisplayMode.Pill: cellClass = getCellStyles( theme, + cellType, textAlign, shouldWrap, shouldOverflow, canBeColorized, - isMonospace, - cellType === TableCellDisplayMode.DataLinks + isMonospace ); break; } @@ -821,6 +822,7 @@ const getGridStyles = ( border: 'none', '.rdg-cell': { + padding: TABLE.CELL_PADDING, '&:last-child': { borderInlineEnd: 'none', }, @@ -843,8 +845,6 @@ const getGridStyles = ( '.rdg-header-row, .rdg-summary-row': { '.rdg-cell': { zIndex: theme.zIndex.tooltip - 1, - paddingInline: TABLE.CELL_PADDING, - paddingBlock: TABLE.CELL_PADDING, }, }, }), @@ -941,35 +941,36 @@ const getHeaderCellStyles = (theme: GrafanaTheme2, justifyContent: Property.Just const getCellStyles = ( theme: GrafanaTheme2, + cellType: TableCellDisplayMode, textAlign: TextAlign, shouldWrap: boolean, shouldOverflow: boolean, isColorized: boolean, - isMonospace: boolean, - // TODO: replace this with cellTypeStyles: TemplateStringsArray object - isLinkCell: boolean + isMonospace: boolean ) => css({ display: 'flex', alignItems: 'center', textAlign, justifyContent: getJustifyContent(textAlign), - paddingInline: TABLE.CELL_PADDING, minHeight: '100%', backgroundClip: 'padding-box !important', // helps when cells have a bg color + ...(shouldWrap && { whiteSpace: isMonospace ? 'pre' : 'pre-line' }), ...(isMonospace && { fontFamily: 'monospace' }), - // should omit if no cell actions, and no shouldOverflow '&:hover, &[aria-selected=true]': { '.table-cell-actions': { display: 'flex', }, ...(shouldOverflow && { - whiteSpace: 'pre-line', + zIndex: theme.zIndex.tooltip - 2, + whiteSpace: isMonospace ? 'pre' : 'pre-line', height: 'fit-content', minWidth: 'fit-content', - ...(isMonospace && { whiteSpace: 'pre' }), + ...(cellType === TableCellDisplayMode.Pill && { + flexWrap: 'wrap', + }), }), }, @@ -989,21 +990,39 @@ const getCellStyles = ( }), }, - ...(isLinkCell && { + ...(cellType === TableCellDisplayMode.DataLinks && { + ...(shouldWrap && { + flexDirection: 'column', + justifyContent: 'center', + alignItems: getJustifyContent(textAlign), + }), '> a': { - // display: 'inline', // textWrap ? 'block' : 'inline', + flexWrap: 'nowrap', + ...(!shouldWrap && { + paddingInline: theme.spacing(0.5), + borderRight: `2px solid ${theme.colors.border.medium}`, + '&:first-child': { + paddingInlineStart: 0, + }, + '&:last-child': { + paddingInlineEnd: 0, + borderRight: 'none', + }, + }), + }, + }), + + ...(cellType === TableCellDisplayMode.Pill && { + display: 'inline-flex', + gap: theme.spacing(0.5), + flexWrap: shouldWrap ? 'wrap' : 'nowrap', + '> span': { + display: 'flex', + padding: theme.spacing(0.25, 0.75), + borderRadius: theme.shape.radius.default, + fontSize: theme.typography.bodySmall.fontSize, + lineHeight: theme.typography.bodySmall.lineHeight, whiteSpace: 'nowrap', - paddingInline: theme.spacing(1), - borderRight: `2px solid ${theme.colors.border.medium}`, - - '&:first-of-type': { - paddingInlineStart: 0, - }, - - '&:last-of-type': { - borderRight: 'none', - paddingInlineEnd: 0, - }, }, }), }); diff --git a/packages/grafana-ui/src/components/Table/TableNG/hooks.test.ts b/packages/grafana-ui/src/components/Table/TableNG/hooks.test.ts index f7a1a1b858a..ce378961589 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/hooks.test.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/hooks.test.ts @@ -490,24 +490,26 @@ describe('TableNG hooks', () => { const { fields } = setupData(); + let modifiedFields = fields.map((field) => { + if (field.name === 'name') { + return { + ...field, + name: 'Longer name that needs wrapping', + config: { + ...field.config, + custom: { + ...field.config?.custom, + wrapHeaderText: true, + }, + }, + }; + } + return field; + }); + renderHook(() => { return useHeaderHeight({ - fields: fields.map((field) => { - if (field.name === 'name') { - return { - ...field, - name: 'Longer name that needs wrapping', - config: { - ...field.config, - custom: { - ...field.config?.custom, - wrapHeaderText: true, - }, - }, - }; - } - return field; - }), + fields: modifiedFields, columnWidths: [100, 100, 100], enabled: true, typographyCtx: { ...typographyCtx, wrappedCount: countFn }, @@ -516,27 +518,29 @@ describe('TableNG hooks', () => { }); }); - expect(countFn).toHaveBeenCalledWith('Longer name that needs wrapping', 86); + expect(countFn).toHaveBeenCalledWith('Longer name that needs wrapping', 86, modifiedFields[0], -1); + + modifiedFields = fields.map((field) => { + if (field.name === 'name') { + return { + ...field, + name: 'Longer name that needs wrapping', + config: { + ...field.config, + custom: { + ...field.config?.custom, + filterable: true, + wrapHeaderText: true, + }, + }, + }; + } + return field; + }); renderHook(() => { return useHeaderHeight({ - fields: fields.map((field) => { - if (field.name === 'name') { - return { - ...field, - name: 'Longer name that needs wrapping', - config: { - ...field.config, - custom: { - ...field.config?.custom, - filterable: true, - wrapHeaderText: true, - }, - }, - }; - } - return field; - }), + fields: modifiedFields, columnWidths: [100, 100, 100], enabled: true, typographyCtx: { ...typographyCtx, wrappedCount: countFn }, @@ -545,7 +549,7 @@ describe('TableNG hooks', () => { }); }); - expect(countFn).toHaveBeenCalledWith('Longer name that needs wrapping', 26); + expect(countFn).toHaveBeenCalledWith('Longer name that needs wrapping', 26, modifiedFields[0], -1); }); }); @@ -764,7 +768,12 @@ describe('TableNG hooks', () => { expect(result.current(rows[0])).toEqual(expect.any(Number)); - expect(estimateLinesFn).toHaveBeenCalledWith('Annie Lennox', 100 - TABLE.CELL_PADDING * 2 - TABLE.BORDER_RIGHT); + expect(estimateLinesFn).toHaveBeenCalledWith( + 'Annie Lennox', + 100 - TABLE.CELL_PADDING * 2 - TABLE.BORDER_RIGHT, + fieldsWithWrappedText[0], + 0 + ); }); }); }); diff --git a/packages/grafana-ui/src/components/Table/TableNG/hooks.ts b/packages/grafana-ui/src/components/Table/TableNG/hooks.ts index 70a790d9133..5c349bdd1ab 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/hooks.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/hooks.ts @@ -3,7 +3,7 @@ import { Column, DataGridHandle, DataGridProps, SortColumn } from 'react-data-gr import { Field, fieldReducers, FieldType, formattedValueToString, reduceField } from '@grafana/data'; -import { TableColumnResizeActionCallback } from '../types'; +import { TableCellDisplayMode, TableColumnResizeActionCallback } from '../types'; import { TABLE } from './constants'; import { FilterType, TableFooterCalc, TableRow, TableSortByFieldState, TableSummaryRow, TypographyCtx } from './types'; @@ -15,6 +15,7 @@ import { getRowHeight, buildHeaderLineCounters, buildRowLineCounters, + getCellOptions, } from './utils'; // Helper function to get displayed value @@ -437,7 +438,15 @@ export function useRowHeight({ defaultHeight, lineCounters, TABLE.LINE_HEIGHT, - TABLE.CELL_PADDING * 2 + (field, numLines) => { + // Pill cells have vertical padding between each row + if (getCellOptions(field).type === TableCellDisplayMode.Pill) { + return TABLE.CELL_PADDING * (numLines - 1) + TABLE.CELL_PADDING * 2; + } + + // default vertical padding for cells + return TABLE.CELL_PADDING * 2; + } ); } return result; diff --git a/packages/grafana-ui/src/components/Table/TableNG/types.ts b/packages/grafana-ui/src/components/Table/TableNG/types.ts index 1d736974189..d28bab7b668 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/types.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/types.ts @@ -248,6 +248,12 @@ export interface ActionCellProps { getActions: GetActionsFunctionLocal; } +export interface PillCellProps { + theme: GrafanaTheme2; + field: Field; + rowIdx: number; +} + // Comparator for sorting table values export type Comparator = (a: TableCellValue, b: TableCellValue) => number; @@ -264,13 +270,14 @@ export interface ScrollPosition { export interface TypographyCtx { ctx: CanvasRenderingContext2D; - font: string; + fontFamily: string; + letterSpacing: number; avgCharWidth: number; estimateLines: LineCounter; wrappedCount: LineCounter; } -export type LineCounter = (value: unknown, width: number) => number; +export type LineCounter = (value: unknown, width: number, field: Field, rowIdx: number) => number; export interface LineCounterEntry { /** * given a values and the available width, returns the line count for that value diff --git a/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts b/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts index e86de2a7009..4dd20cac215 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts @@ -5,6 +5,7 @@ import { createTheme, DataFrame, DataFrameWithValue, + DataLink, DisplayValue, Field, FieldType, @@ -40,23 +41,17 @@ import { createTypographyContext, applySort, SINGLE_LINE_ESTIMATE_THRESHOLD, + wrapUwrapCount, + getDataLinksCounter, + getPillLineCounter, } from './utils'; describe('TableNG utils', () => { describe('alignment', () => { it.each(['left', 'center', 'right'] as const)('should return "%s" when configured', (align) => { - expect( - getAlignment({ - name: 'Value', - type: FieldType.string, - values: [], - config: { - custom: { - align, - }, - }, - }) - ).toBe(align); + expect(getAlignment({ name: 'Value', type: FieldType.string, values: [], config: { custom: { align } } })).toBe( + align + ); }); it.each([ @@ -65,16 +60,7 @@ describe('TableNG utils', () => { { type: FieldType.boolean, align: 'left' }, { type: FieldType.time, align: 'left' }, ])('should return "$align" for field type $type by default', ({ type, align }) => { - expect( - getAlignment({ - name: 'Test', - type, - values: [], - config: { - custom: {}, - }, - }) - ).toBe(align); + expect(getAlignment({ name: 'Test', type, values: [], config: { custom: {} } })).toBe(align); }); it.each([ @@ -91,17 +77,7 @@ describe('TableNG utils', () => { name: 'Test', type: FieldType.number, values: [], - config: { - custom: { - ...(cellType !== undefined - ? { - cellOptions: { - type: cellType, - }, - } - : {}), - }, - }, + config: { custom: { ...(cellType !== undefined ? { cellOptions: { type: cellType } } : {}) } }, }) ).toBe(align); }); @@ -122,34 +98,17 @@ describe('TableNG utils', () => { colors: { isDark: true, mode: 'dark', - primary: { - text: '#FFFFFF', - main: '#FF0000', - }, - background: { - canvas: '#000000', - primary: '#111111', - }, - text: { - primary: '#FFFFFF', - }, - action: { - hover: '#FF0000', - }, + primary: { text: '#FFFFFF', main: '#FF0000' }, + background: { canvas: '#000000', primary: '#111111' }, + text: { primary: '#FFFFFF' }, + action: { hover: '#FF0000' }, }, } as unknown as GrafanaTheme2; it('should handle color background mode', () => { - const field = { - type: TableCellDisplayMode.ColorBackground as const, - mode: TableCellBackgroundDisplayMode.Basic, - }; + const field = { type: TableCellDisplayMode.ColorBackground as const, mode: TableCellBackgroundDisplayMode.Basic }; - const displayValue = { - text: '100', - numeric: 100, - color: '#ff0000', - }; + const displayValue = { text: '100', numeric: 100, color: '#ff0000' }; const colors = getCellColors(theme, field, displayValue); expect(colors.bgColor).toBe('rgb(255, 0, 0)'); @@ -162,11 +121,7 @@ describe('TableNG utils', () => { mode: TableCellBackgroundDisplayMode.Gradient, }; - const displayValue = { - text: '100', - numeric: 100, - color: '#ff0000', - }; + const displayValue = { text: '100', numeric: 100, color: '#ff0000' }; const colors = getCellColors(theme, field, displayValue); expect(colors.bgColor).toBe('linear-gradient(120deg, rgb(255, 54, 36), #ff0000)'); @@ -185,12 +140,7 @@ describe('TableNG utils', () => { const records = frameToRecords(frame); expect(records).toHaveLength(2); - expect(records[0]).toEqual({ - __depth: 0, - __index: 0, - time: 1, - value: 10, - }); + expect(records[0]).toEqual({ __depth: 0, __index: 0, time: 1, value: 10 }); }); }); @@ -203,36 +153,22 @@ describe('TableNG utils', () => { config: {}, values: [1, 22, 333, 4444], // No state property initially - display: (value: unknown) => ({ - text: String(value), - numeric: Number(value), - }), + display: (value: unknown) => ({ text: String(value), numeric: Number(value) }), }; // Create a display value - const displayValue: DisplayValue = { - text: '1', - numeric: 1, - }; + const displayValue: DisplayValue = { text: '1', numeric: 1 }; // Call getAlignmentFactor with the first row const result = getAlignmentFactor(field, displayValue, 0); // Verify the result has the text property - expect(result).toEqual( - expect.objectContaining({ - text: '1', - }) - ); + expect(result).toEqual(expect.objectContaining({ text: '1' })); // Verify that field.state was created and contains the alignment factor expect(field.state).toBeDefined(); expect(field.state?.alignmentFactors).toBeDefined(); - expect(field.state?.alignmentFactors).toEqual( - expect.objectContaining({ - text: '1', - }) - ); + expect(field.state?.alignmentFactors).toEqual(expect.objectContaining({ text: '1' })); }); it('should update alignment factor when a longer value is found', () => { @@ -242,39 +178,21 @@ describe('TableNG utils', () => { type: FieldType.number, config: {}, values: [1, 22, 333, 4444], - state: { - alignmentFactors: { - text: '1', - }, - }, - display: (value: unknown) => ({ - text: String(value), - numeric: Number(value), - }), + state: { alignmentFactors: { text: '1' } }, + display: (value: unknown) => ({ text: String(value), numeric: Number(value) }), }; // Create a display value that is longer than the existing alignment factor - const displayValue: DisplayValue = { - text: '4444', - numeric: 4444, - }; + const displayValue: DisplayValue = { text: '4444', numeric: 4444 }; // Call getAlignmentFactor const result = getAlignmentFactor(field, displayValue, 3); // Verify the result is updated to the longer value - expect(result).toEqual( - expect.objectContaining({ - text: '4444', - }) - ); + expect(result).toEqual(expect.objectContaining({ text: '4444' })); // Verify that field.state.alignmentFactors was updated - expect(field.state?.alignmentFactors).toEqual( - expect.objectContaining({ - text: '4444', - }) - ); + expect(field.state?.alignmentFactors).toEqual(expect.objectContaining({ text: '4444' })); }); it('should not update alignment factor when a shorter value is found', () => { @@ -284,39 +202,21 @@ describe('TableNG utils', () => { type: FieldType.number, config: {}, values: [1, 22, 333, 4444], - state: { - alignmentFactors: { - text: '4444', - }, - }, - display: (value: unknown) => ({ - text: String(value), - numeric: Number(value), - }), + state: { alignmentFactors: { text: '4444' } }, + display: (value: unknown) => ({ text: String(value), numeric: Number(value) }), }; // Create a display value that is shorter than the existing alignment factor - const displayValue: DisplayValue = { - text: '1', - numeric: 1, - }; + const displayValue: DisplayValue = { text: '1', numeric: 1 }; // Call getAlignmentFactor const result = getAlignmentFactor(field, displayValue, 0); // Verify the result is still the longer value - expect(result).toEqual( - expect.objectContaining({ - text: '4444', - }) - ); + expect(result).toEqual(expect.objectContaining({ text: '4444' })); // Verify that field.state.alignmentFactors was not changed - expect(field.state?.alignmentFactors).toEqual( - expect.objectContaining({ - text: '4444', - }) - ); + expect(field.state?.alignmentFactors).toEqual(expect.objectContaining({ text: '4444' })); }); it('should add alignment factor to existing field state', () => { @@ -334,38 +234,24 @@ describe('TableNG utils', () => { // Or if noValue is a valid property: // noValue: true }, - display: (value: unknown) => ({ - text: String(value), - numeric: Number(value), - }), + display: (value: unknown) => ({ text: String(value), numeric: Number(value) }), }; // Create a display value - const displayValue: DisplayValue = { - text: '1', - numeric: 1, - }; + const displayValue: DisplayValue = { text: '1', numeric: 1 }; // Call getAlignmentFactor with the first row const result = getAlignmentFactor(field, displayValue, 0); // Verify the result has the text property - expect(result).toEqual( - expect.objectContaining({ - text: '1', - }) - ); + expect(result).toEqual(expect.objectContaining({ text: '1' })); // Verify that field.state was preserved and alignment factor was added expect(field.state).toBeDefined(); // Check for the valid property we used expect(field.state?.calcs).toBeDefined(); expect(field.state?.alignmentFactors).toBeDefined(); - expect(field.state?.alignmentFactors).toEqual( - expect.objectContaining({ - text: '1', - }) - ); + expect(field.state?.alignmentFactors).toEqual(expect.objectContaining({ text: '1' })); }); it.todo('alignmentFactor.text = displayValue.text;'); @@ -398,11 +284,7 @@ describe('TableNG utils', () => { ]; const result = getColumnTypes(fields); - expect(result).toEqual({ - name: FieldType.string, - age: FieldType.number, - active: FieldType.boolean, - }); + expect(result).toEqual({ name: FieldType.string, age: FieldType.number, active: FieldType.boolean }); }); it('should recursively build column types when nested fields are present', () => { @@ -448,20 +330,13 @@ describe('TableNG utils', () => { const frame: DataFrame = { fields: [ { type: FieldType.string, name: 'stringCol', config: {}, values: [] }, - { - type: FieldType.nestedFrames, - name: 'nestedCol', - config: {}, - values: [], - }, + { type: FieldType.nestedFrames, name: 'nestedCol', config: {}, values: [] }, ], length: 0, name: 'test', }; - expect(getColumnTypes(frame.fields)).toEqual({ - stringCol: FieldType.string, - }); + expect(getColumnTypes(frame.fields)).toEqual({ stringCol: FieldType.string }); }); }); @@ -557,18 +432,12 @@ describe('TableNG utils', () => { describe('migrateTableDisplayModeToCellOptions', () => { it('should migrate basic to gauge mode', () => { const result = migrateTableDisplayModeToCellOptions(TableCellDisplayMode.BasicGauge); - expect(result).toEqual({ - type: TableCellDisplayMode.Gauge, - mode: BarGaugeDisplayMode.Basic, - }); + expect(result).toEqual({ type: TableCellDisplayMode.Gauge, mode: BarGaugeDisplayMode.Basic }); }); it('should migrate gradient-gauge to gauge mode with gradient', () => { const result = migrateTableDisplayModeToCellOptions(TableCellDisplayMode.GradientGauge); - expect(result).toEqual({ - type: TableCellDisplayMode.Gauge, - mode: BarGaugeDisplayMode.Gradient, - }); + expect(result).toEqual({ type: TableCellDisplayMode.Gauge, mode: BarGaugeDisplayMode.Gradient }); }); it('should migrate color-background to color background with gradient', () => { @@ -581,20 +450,13 @@ describe('TableNG utils', () => { it('should handle other display modes', () => { const result = migrateTableDisplayModeToCellOptions(TableCellDisplayMode.ColorText); - expect(result).toEqual({ - type: TableCellDisplayMode.ColorText, - }); + expect(result).toEqual({ type: TableCellDisplayMode.ColorText }); }); }); describe('getCellOptions', () => { it('should return default options when no custom config is provided', () => { - const field: Field = { - name: 'test', - type: FieldType.string, - config: {}, - values: [], - }; + const field: Field = { name: 'test', type: FieldType.string, config: {}, values: [] }; const options = getCellOptions(field); @@ -607,35 +469,21 @@ describe('TableNG utils', () => { name: 'test', type: FieldType.string, config: { - custom: { - cellOptions: { - type: TableCellDisplayMode.ColorText, - inspectEnabled: false, - wrapText: true, - }, - }, + custom: { cellOptions: { type: TableCellDisplayMode.ColorText, inspectEnabled: false, wrapText: true } }, }, values: [], }; const options = getCellOptions(field); - expect(options).toEqual({ - type: TableCellDisplayMode.ColorText, - inspectEnabled: false, - wrapText: true, - }); + expect(options).toEqual({ type: TableCellDisplayMode.ColorText, inspectEnabled: false, wrapText: true }); }); it('should handle legacy displayMode property', () => { const field: Field = { name: 'test', type: FieldType.string, - config: { - custom: { - displayMode: 'color-background', - }, - }, + config: { custom: { displayMode: 'color-background' } }, values: [], }; @@ -649,14 +497,7 @@ describe('TableNG utils', () => { const field: Field = { name: 'test', type: FieldType.string, - config: { - custom: { - displayMode: 'color-background', - cellOptions: { - type: TableCellDisplayMode.ColorText, - }, - }, - }, + config: { custom: { displayMode: 'color-background', cellOptions: { type: TableCellDisplayMode.ColorText } } }, values: [], }; @@ -689,13 +530,7 @@ describe('TableNG utils', () => { const field: Field = { name: 'test', type: FieldType.string, - config: { - custom: { - cellOptions: { - type: TableCellDisplayMode.JSONView, - }, - }, - }, + config: { custom: { cellOptions: { type: TableCellDisplayMode.JSONView } } }, values: [], }; @@ -707,12 +542,7 @@ describe('TableNG utils', () => { describe('getCellLinks', () => { it('should return undefined when field has no getLinks function', () => { - const field: Field = { - name: 'test', - type: FieldType.string, - config: {}, - values: ['value'], - }; + const field: Field = { name: 'test', type: FieldType.string, config: {}, values: ['value'] }; const links = getCellLinks(field, 0); expect(links).toEqual(undefined); @@ -987,36 +817,112 @@ describe('TableNG utils', () => { // actually executed the JS correctly. If you called `count` with a sensible value and width, // it wouldn't give you a very reasonable answer in Jest's DOM environment for some reason. it('creates the context using uwrap', () => { + const field: Field = { name: 'test', type: FieldType.string, config: {}, values: ['foo', 'bar', 'baz'] }; const ctx = createTypographyContext(14, 'sans-serif', 0.15); + expect(ctx).toEqual( expect.objectContaining({ - font: '14px sans-serif', ctx: expect.any(CanvasRenderingContext2D), + fontFamily: 'sans-serif', + letterSpacing: 0.15, wrappedCount: expect.any(Function), estimateLines: expect.any(Function), avgCharWidth: expect.any(Number), }) ); - expect(ctx.wrappedCount('the quick brown fox jumps over the lazy dog', 100)).toEqual(expect.any(Number)); - expect(ctx.estimateLines('the quick brown fox jumps over the lazy dog', 100)).toEqual(expect.any(Number)); + expect(ctx.wrappedCount('the quick brown fox jumps over the lazy dog', 100, field, 0)).toEqual( + expect.any(Number) + ); + expect(ctx.estimateLines('the quick brown fox jumps over the lazy dog', 100, field, 0)).toEqual( + expect.any(Number) + ); + }); + }); + + describe('wrapUwrapCount', () => { + const field: Field = { name: 'test', type: FieldType.string, config: {}, values: ['foo', 'bar', 'baz'] }; + + it('wraps the uwrap count function', () => { + const wrappedCount = wrapUwrapCount(jest.fn(() => 2)); + expect(wrappedCount('test string', 100, field, 0)).toBe(2); + }); + + it('returns 1 for null or undefined values', () => { + const wrappedCount = wrapUwrapCount(jest.fn(() => 2)); + expect(wrappedCount(null, 100, field, 0)).toBe(1); + expect(wrappedCount(undefined, 100, field, 0)).toBe(1); }); }); describe('getTextLineEstimator', () => { const counter = getTextLineEstimator(10); + const field: Field = { name: 'test', type: FieldType.string, config: {}, values: ['foo', 'bar', 'baz'] }; it('returns -1 if there are no strings or dashes within the string', () => { - expect(counter('asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf', 5)).toBe(-1); + expect(counter('asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf', 5, field, 0)).toBe(-1); }); it('calculates an approximate rendered height for the text based on the width and avgCharWidth', () => { - expect(counter('asdfas dfasdfasdf asdfasdfasdfa sdfasdfasdfasdf 23', 200)).toBe(2.5); + expect(counter('asdfas dfasdfasdf asdfasdfasdfa sdfasdfasdfasdf 23', 200, field, 0)).toBe(2.5); + }); + }); + + describe('getDataLinksCounter', () => { + it('counts number of valid links using getCellLinks', () => { + const field: Field = { + name: 'test', + type: FieldType.string, + config: { + links: [ + { title: 'Link 1', url: 'http://example.com/1' }, + { title: 'Invalid Link' } as DataLink, // No href or onClick + { + title: 'Link w', + url: 'asdf', + onClick: jest.fn(() => {}), + }, + ], + }, + values: ['value1'], + }; + + const counter = getDataLinksCounter(); + expect(counter('my value', 100, field, 0)).toBe(2); + }); + }); + + describe('getPillLineCounter', () => { + it('counts up the number of lines using the pill measuring method', () => { + const counter = getPillLineCounter(jest.fn((str) => str.length * 5)); + expect(counter('tag1,tag2', 100, {} as Field, 0)).toBe(1); + expect(counter('tag1,tag2,tag3,tag4,tag5,tag6', 100, {} as Field, 0)).toBe(3); + }); + + it('returns 0 if value is null', () => { + const counter = getPillLineCounter(jest.fn((str) => str.length * 5)); + expect(counter(null, 100, {} as Field, 0)).toBe(0); + }); + + it('returns 0 if no pills are inferred', () => { + const counter = getPillLineCounter(jest.fn((str) => str.length * 5)); + expect(counter('', 100, {} as Field, 0)).toBe(0); + }); + + it('caches the width measurement for the same value', () => { + const widthMeasurement = jest.fn((str) => str.length * 5); + const counter = getPillLineCounter(widthMeasurement); + counter('tag1,tag2,tag3,tag4,tag5,tag6', 100, {} as Field, 0); + counter('tag1,tag2', 100, {} as Field, 0); + counter('tag2', 200, {} as Field, 0); + counter('tag2,tag3,tag2,tag4,tag4,tag2,tag5', 300, {} as Field, 0); + expect(widthMeasurement).toHaveBeenCalledTimes(6); // Should only call for unique values }); }); describe('buildHeaderLineCounters', () => { const ctx = { - font: '14px sans-serif', + fontFamily: 'sans-serif', + letterSpacing: 0.15, ctx: {} as CanvasRenderingContext2D, count: jest.fn(() => 2), avgCharWidth: 7, @@ -1057,15 +963,15 @@ describe('TableNG utils', () => { describe('buildRowLineCounters', () => { const ctx = { - font: '14px sans-serif', + fontFamily: 'sans-serif', + letterSpacing: 0.15, ctx: {} as CanvasRenderingContext2D, - count: jest.fn(() => 2), wrappedCount: jest.fn(() => 2), estimateLines: jest.fn(() => 2), avgCharWidth: 7, }; - it('returns an array of line counters for each column', () => { + it('sets up text line counters for each text column if wrapping is on', () => { const fields: Field[] = [ { name: 'Name', type: FieldType.string, values: [], config: { custom: { cellOptions: { wrapText: true } } } }, { @@ -1095,6 +1001,42 @@ describe('TableNG utils', () => { expect(counters![0].fieldIdxs).toEqual([1]); }); + it('sets up line counting for pills if present and wrapping is on', () => { + const fields: Field[] = [ + { + name: 'Tags', + type: FieldType.string, + values: ['tag1,tag2', 'tag3', '["tag4","tag5","tag6"]'], + config: { custom: { cellOptions: { type: TableCellDisplayMode.Pill, wrapText: true } } }, + }, + ]; + const counters = buildRowLineCounters(fields, ctx); + expect(counters![0].estimate).toEqual(expect.any(Function)); + expect(counters![0].estimate!('tag1,tag2', 100, fields[0], 0)).toEqual(expect.any(Number)); + expect(counters![0].counter).toEqual(expect.any(Function)); + expect(counters![0].counter('tag1,tag2', 100, fields[0], 0)).toEqual(expect.any(Number)); + expect(counters![0].fieldIdxs).toEqual([0]); + }); + + it('sets up line counting for datalinks if present and wrapping is on', () => { + const fields: Field[] = [ + { + name: 'Links', + type: FieldType.string, + values: ['http://example.com/1', 'http://example.com/2'], + config: { custom: { cellOptions: { type: TableCellDisplayMode.DataLinks, wrapText: true } } }, + getLinks: jest.fn((): LinkModel[] => [ + { title: 'Link 1', href: 'http://example.com/1', target: '_blank', origin: { datasourceUid: 'test' } }, + { title: 'Link 2', href: 'http://example.com/2', target: '_self', origin: { datasourceUid: 'test' } }, + ]), + }, + ]; + const counters = buildRowLineCounters(fields, ctx); + expect(counters![0].counter).toEqual(expect.any(Function)); + expect(counters![0].counter('http://example.com/1', 100, fields[0], 0)).toEqual(expect.any(Number)); + expect(counters![0].fieldIdxs).toEqual([0]); + }); + it('does not enable text counting for non-string fields', () => { const fields: Field[] = [ { name: 'Name', type: FieldType.string, values: [], config: { custom: {} } }, @@ -1162,15 +1104,15 @@ describe('TableNG utils', () => { it('should take colWidths into account when calculating max wrap cell', () => { getRowHeight(fields, 3, [50, 60], 36, counters, 20, 10); - expect(counters[0].counter).toHaveBeenCalledWith('longer one here', 50); - expect(counters[1].counter).toHaveBeenCalledWith(123456, 60); + expect(counters[0].counter).toHaveBeenCalledWith('longer one here', 50, fields[0], 3); + expect(counters[1].counter).toHaveBeenCalledWith(123456, 60, fields[1], 3); }); // this is used to calc wrapped header height it('should use the display name if the rowIdx is -1', () => { getRowHeight(fields, -1, [50, 60], 36, counters, 20, 10); - expect(counters[0].counter).toHaveBeenCalledWith('Name', 50); - expect(counters[1].counter).toHaveBeenCalledWith('Age', 60); + expect(counters[0].counter).toHaveBeenCalledWith('Name', 50, fields[0], -1); + expect(counters[1].counter).toHaveBeenCalledWith('Age', 60, fields[1], -1); }); it('should ignore columns which do not have line counters', () => { @@ -1230,18 +1172,8 @@ describe('TableNG utils', () => { expect( computeColWidths( [ - { - name: 'A', - type: FieldType.string, - values: [], - config: { custom: { width: 100 } }, - }, - { - name: 'B', - type: FieldType.string, - values: [], - config: { custom: { width: 200 } }, - }, + { name: 'A', type: FieldType.string, values: [], config: { custom: { width: 100 } } }, + { name: 'B', type: FieldType.string, values: [], config: { custom: { width: 200 } } }, ], 500 ) @@ -1252,18 +1184,8 @@ describe('TableNG utils', () => { expect( computeColWidths( [ - { - name: 'A', - type: FieldType.string, - values: [], - config: {}, - }, - { - name: 'B', - type: FieldType.string, - values: [], - config: { custom: { width: 200 } }, - }, + { name: 'A', type: FieldType.string, values: [], config: {} }, + { name: 'B', type: FieldType.string, values: [], config: { custom: { width: 200 } } }, ], 500 ) @@ -1274,18 +1196,8 @@ describe('TableNG utils', () => { expect( computeColWidths( [ - { - name: 'A', - type: FieldType.string, - values: [], - config: { custom: { minWidth: 100 } }, - }, - { - name: 'B', - type: FieldType.string, - values: [], - config: { custom: { minWidth: 100 } }, - }, + { name: 'A', type: FieldType.string, values: [], config: { custom: { minWidth: 100 } } }, + { name: 'B', type: FieldType.string, values: [], config: { custom: { minWidth: 100 } } }, ], 100 ) @@ -1296,18 +1208,8 @@ describe('TableNG utils', () => { expect( computeColWidths( [ - { - name: 'A', - type: FieldType.string, - values: [], - config: {}, - }, - { - name: 'B', - type: FieldType.string, - values: [], - config: {}, - }, + { name: 'A', type: FieldType.string, values: [], config: {} }, + { name: 'B', type: FieldType.string, values: [], config: {} }, ], // we have two columns but have set the table to the width of one default column. COLUMN.DEFAULT_WIDTH @@ -1332,28 +1234,14 @@ describe('TableNG utils', () => { ], }); - const sortColumns: SortColumn[] = [ - { - columnKey: 'time', - direction: 'ASC', - }, - ]; + const sortColumns: SortColumn[] = [{ columnKey: 'time', direction: 'ASC' }]; const records = applySort(frameToRecords(frame), frame.fields, sortColumns); expect(records).toMatchObject([ - { - time: 1, - value: 20, - }, - { - time: 1, - value: 10, - }, - { - time: 2, - value: 30, - }, + { time: 1, value: 20 }, + { time: 1, value: 10 }, + { time: 2, value: 30 }, ]); }); }); diff --git a/packages/grafana-ui/src/components/Table/TableNG/utils.ts b/packages/grafana-ui/src/components/Table/TableNG/utils.ts index a24a361bfda..96e6c71c018 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/utils.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/utils.ts @@ -25,6 +25,7 @@ import { import { getTextColorForAlphaBackground } from '../../../utils/colors'; import { TableCellOptions } from '../types'; +import { inferPills } from './Cells/PillCell'; import { COLUMN, TABLE } from './constants'; import { CellColors, @@ -92,15 +93,19 @@ export function createTypographyContext(fontSize: number, fontFamily: string, le ctx.letterSpacing = `${letterSpacing}px`; ctx.font = font; + // 1/6 of the characters in this string are capitalized. Since the avgCharWidth is used for estimation, it's + // better that the estimation over-estimates the width than if it underestimates it, so we're a little on the + // aggressive side here and could even go more aggressive if we get complaints in the future. const txt = - "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s."; + "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s. 1234567890 ALL CAPS TO HELP WITH MEASUREMENT."; const txtWidth = ctx.measureText(txt).width; const avgCharWidth = txtWidth / txt.length + letterSpacing; const { count } = varPreLine(ctx); return { ctx, - font, + fontFamily, + letterSpacing, avgCharWidth, estimateLines: getTextLineEstimator(avgCharWidth), wrappedCount: wrapUwrapCount(count), @@ -108,7 +113,7 @@ export function createTypographyContext(fontSize: number, fontFamily: string, le } /** - * @internal + * @internal wraps the uwrap count function to ensure that it is given a string. */ export function wrapUwrapCount(count: Count): LineCounter { return (value, width) => { @@ -141,6 +146,71 @@ export function getTextLineEstimator(avgCharWidth: number): LineCounter { }; } +/** + * @internal + */ +export function getDataLinksCounter(): LineCounter { + const linksCountCache: Record = {}; + + // when we render links, we need to filter out the invalid links. since the call to `getLinks` is expensive, + // we'll cache the result and reuse it for every row in the table. this cache is cleared when line counts are + // rebuilt anytime from the `useRowHeight` hook, and that includes adding and removing data links. + return (_value, _width, field) => { + const cacheKey = getDisplayName(field); + if (linksCountCache[cacheKey] === undefined) { + let count = 0; + for (const l of field.config?.links ?? []) { + if (l.onClick || l.url) { + count += 1; + } + } + linksCountCache[cacheKey] = count; + } + + return linksCountCache[cacheKey]; + }; +} + +const PILLS_FONT_SIZE = 12; +const PILLS_SPACING = 12; // 6px horizontal padding on each side +const PILLS_GAP = 4; // gap between pills + +export function getPillLineCounter(measureWidth: (value: string) => number): LineCounter { + const widthCache: Record = {}; + + return (value, width) => { + if (value == null) { + return 0; + } + + const pillValues = inferPills(String(value)); + if (pillValues.length === 0) { + return 0; + } + + let lines = 0; + let currentLineUse = width; + + for (const pillValue of pillValues) { + let rawWidth = widthCache[pillValue]; + if (rawWidth === undefined) { + rawWidth = measureWidth(pillValue); + widthCache[pillValue] = rawWidth; + } + const pillWidth = rawWidth + PILLS_SPACING; + + if (currentLineUse + pillWidth + PILLS_GAP > width) { + lines++; + currentLineUse = pillWidth; + } else { + currentLineUse += pillWidth + PILLS_GAP; + } + } + + return lines; + }; +} + /** * @internal return a text line counter for every field which has wrapHeaderText enabled. */ @@ -175,12 +245,33 @@ export function buildRowLineCounters(fields: Field[], typographyCtx: TypographyC const field = fields[fieldIdx]; if (shouldTextWrap(field)) { wrappedFields++; - // TODO: Pills, DataLinks, and JSON will have custom line counters here. - // for string fields, we really want to find the longest field ahead of time to reduce the number of calls to `count`. - // calling `count` is going to get a perfectly accurate line count, but it is expensive, so we'd rather estimate the line - // count and call the counter only for the field which will take up the most space based on its - if (field.type === FieldType.string) { + const cellType = getCellOptions(field).type; + if (cellType === TableCellDisplayMode.DataLinks) { + result.dataLinksCounter = result.dataLinksCounter ?? { + counter: getDataLinksCounter(), + fieldIdxs: [], + }; + result.dataLinksCounter.fieldIdxs.push(fieldIdx); + } else if (cellType === TableCellDisplayMode.Pill) { + if (!result.pillCounter) { + const pillTypographyCtx = createTypographyContext( + PILLS_FONT_SIZE, + typographyCtx.fontFamily, + typographyCtx.letterSpacing + ); + + result.pillCounter = { + estimate: getPillLineCounter((value) => value.length * pillTypographyCtx.avgCharWidth), + counter: getPillLineCounter((value) => pillTypographyCtx.ctx.measureText(value).width), + fieldIdxs: [], + }; + } + result.pillCounter.fieldIdxs.push(fieldIdx); + } + + // for string fields, we estimate the length of a line using `avgCharWidth` to limit expensive calls `count`. + else if (field.type === FieldType.string) { result.textCounter = result.textCounter ?? { counter: typographyCtx.wrappedCount, estimate: typographyCtx.estimateLines, @@ -215,7 +306,9 @@ export function getRowHeight( defaultHeight: number, lineCounters?: LineCounterEntry[], lineHeight = TABLE.LINE_HEIGHT, - verticalPadding = 0 + // when this is a function, the field which was measured as the maximum size will be returned, as well as the + // calculated number of lines, so that the consumer can use it in case the vertical padding value differs field-by-field. + verticalPadding: number | ((field: Field, numLines: number) => number) = TABLE.CELL_PADDING ): number { if (!lineCounters?.length) { return defaultHeight; @@ -224,6 +317,7 @@ export function getRowHeight( let maxLines = -1; let maxValue = ''; let maxWidth = 0; + let maxField: Field | undefined; let preciseCounter: LineCounter | undefined; for (const { estimate, counter, fieldIdxs } of lineCounters) { @@ -239,11 +333,12 @@ export function getRowHeight( const cellValueRaw = rowIdx === -1 ? getDisplayName(field) : field.values[rowIdx]; if (cellValueRaw != null) { const colWidth = columnWidths[fieldIdx]; - const approxLines = count(cellValueRaw, colWidth); + const approxLines = count(cellValueRaw, colWidth, field, rowIdx); if (approxLines > maxLines) { maxLines = approxLines; maxValue = cellValueRaw; maxWidth = colWidth; + maxField = field; preciseCounter = isEstimating ? counter : undefined; } } @@ -252,18 +347,23 @@ export function getRowHeight( // if the value is -1 or the estimate for the max cell was less than the SINGLE_LINE_ESTIMATE_THRESHOLD, we trust // that the estimator correctly identified that no text wrapping is needed for this row, skipping the preciseCounter. - if (maxLines < SINGLE_LINE_ESTIMATE_THRESHOLD) { + if (maxField === undefined || maxLines < SINGLE_LINE_ESTIMATE_THRESHOLD) { return defaultHeight; } // if we finished this row height loop with an estimate, we need to call // the `preciseCounter` method to get the exact line count. if (preciseCounter !== undefined) { - maxLines = preciseCounter(maxValue, maxWidth); + maxLines = preciseCounter(maxValue, maxWidth, maxField, rowIdx); } - // we want a round number of lines for rendering - const totalHeight = Math.ceil(maxLines) * lineHeight + verticalPadding; + // round up to the nearest line before doing math + maxLines = Math.ceil(maxLines); + + // adjust for vertical padding and line height, and clamp to a minimum default height + const verticalPaddingValue = + typeof verticalPadding === 'function' ? verticalPadding(maxField, maxLines) : verticalPadding; + const totalHeight = maxLines * lineHeight + verticalPaddingValue; return Math.max(totalHeight, defaultHeight); } @@ -276,9 +376,7 @@ export function shouldTextOverflow(field: Field): boolean { const eligibleCellType = // Tech debt: Technically image cells are of type string, which is misleading (kinda?) // so we need to ensurefield.type === FieldType.string we don't apply overflow hover states for type image - (field.type === FieldType.string && - cellOptions.type !== TableCellDisplayMode.Image && - cellOptions.type !== TableCellDisplayMode.Pill) || + (field.type === FieldType.string && cellOptions.type !== TableCellDisplayMode.Image) || // regardless of the underlying cell type, data links cells have text overflow. cellOptions.type === TableCellDisplayMode.DataLinks; diff --git a/public/app/plugins/panel/table/cells/AutoCellOptionsEditor.tsx b/public/app/plugins/panel/table/cells/AutoCellOptionsEditor.tsx index 7b108fbc155..e97d481e0b3 100644 --- a/public/app/plugins/panel/table/cells/AutoCellOptionsEditor.tsx +++ b/public/app/plugins/panel/table/cells/AutoCellOptionsEditor.tsx @@ -8,8 +8,6 @@ export const AutoCellOptionsEditor = ({ cellOptions, onChange, }: TableCellEditorProps) => { - // Handle row coloring changes - const onWrapTextChange = () => { cellOptions.wrapText = !cellOptions.wrapText; onChange(cellOptions); diff --git a/public/app/plugins/panel/table/cells/ColorBackgroundCellOptionsEditor.tsx b/public/app/plugins/panel/table/cells/ColorBackgroundCellOptionsEditor.tsx index afd6353a43e..33c3761493d 100644 --- a/public/app/plugins/panel/table/cells/ColorBackgroundCellOptionsEditor.tsx +++ b/public/app/plugins/panel/table/cells/ColorBackgroundCellOptionsEditor.tsx @@ -21,13 +21,11 @@ export const ColorBackgroundCellOptionsEditor = ({ onChange(cellOptions); }; - // Handle row coloring changes const onColorRowChange = () => { cellOptions.applyToRow = !cellOptions.applyToRow; onChange(cellOptions); }; - // Handle row coloring changes const onWrapTextChange = () => { cellOptions.wrapText = !cellOptions.wrapText; onChange(cellOptions); diff --git a/public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx b/public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx index 77e2acf0808..92cbbf0f264 100644 --- a/public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx +++ b/public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx @@ -4,14 +4,14 @@ import { useState } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { t } from '@grafana/i18n'; -import { TableCellOptions } from '@grafana/schema'; +import { TableCellOptions, TableWrapTextOptions } from '@grafana/schema'; import { Combobox, ComboboxOption, Field, TableCellDisplayMode, useStyles2 } from '@grafana/ui'; -import { AutoCellOptionsEditor } from './cells/AutoCellOptionsEditor'; import { BarGaugeCellOptionsEditor } from './cells/BarGaugeCellOptionsEditor'; import { ColorBackgroundCellOptionsEditor } from './cells/ColorBackgroundCellOptionsEditor'; import { ImageCellOptionsEditor } from './cells/ImageCellOptionsEditor'; import { SparklineCellOptionsEditor } from './cells/SparklineCellOptionsEditor'; +import { TextWrapOptionsEditor } from './cells/TextWrapOptionsEditor'; // The props that any cell type editor are expected // to handle. In this case the generic type should @@ -26,6 +26,19 @@ interface Props { onChange: (v: TableCellOptions) => void; } +const TEXT_WRAP_CELL_TYPES = new Set([ + TableCellDisplayMode.Auto, + TableCellDisplayMode.Sparkline, + TableCellDisplayMode.ColorText, + TableCellDisplayMode.ColorBackground, + TableCellDisplayMode.DataLinks, + TableCellDisplayMode.Pill, +]); + +function isTextWrapCellType(value: TableCellOptions): value is TableCellOptions & TableWrapTextOptions { + return TEXT_WRAP_CELL_TYPES.has(value.type); +} + export const TableCellOptionEditor = ({ value, onChange }: Props) => { const cellType = value.type; const styles = useStyles2(getStyles); @@ -79,9 +92,7 @@ export const TableCellOptionEditor = ({ value, onChange }: Props) => { - {(cellType === TableCellDisplayMode.Auto || cellType === TableCellDisplayMode.ColorText) && ( - - )} + {isTextWrapCellType(value) && } {cellType === TableCellDisplayMode.Gauge && ( )} diff --git a/public/app/plugins/panel/table/table-new/cells/AutoCellOptionsEditor.tsx b/public/app/plugins/panel/table/table-new/cells/AutoCellOptionsEditor.tsx deleted file mode 100644 index 5aae9d65b7a..00000000000 --- a/public/app/plugins/panel/table/table-new/cells/AutoCellOptionsEditor.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { selectors } from '@grafana/e2e-selectors'; -import { t } from '@grafana/i18n'; -import { TableAutoCellOptions, TableColoredBackgroundCellOptions, TableColorTextCellOptions } from '@grafana/schema'; -import { Field, Switch } from '@grafana/ui'; - -import { TableCellEditorProps } from '../TableCellOptionEditor'; - -export const AutoCellOptionsEditor = ({ - cellOptions, - onChange, -}: TableCellEditorProps) => { - // Handle row coloring changes - const onWrapTextChange = () => { - cellOptions.wrapText = !cellOptions.wrapText; - onChange(cellOptions); - }; - - return ( - - - - ); -}; diff --git a/public/app/plugins/panel/table/table-new/cells/ColorBackgroundCellOptionsEditor.tsx b/public/app/plugins/panel/table/table-new/cells/ColorBackgroundCellOptionsEditor.tsx index b7d5d2ab3dc..33d85539ec4 100644 --- a/public/app/plugins/panel/table/table-new/cells/ColorBackgroundCellOptionsEditor.tsx +++ b/public/app/plugins/panel/table/table-new/cells/ColorBackgroundCellOptionsEditor.tsx @@ -6,7 +6,7 @@ import { Field, RadioButtonGroup, Switch } from '@grafana/ui'; import { TableCellEditorProps } from '../TableCellOptionEditor'; -import { AutoCellOptionsEditor } from './AutoCellOptionsEditor'; +import { TextWrapOptionsEditor } from './TextWrapOptionsEditor'; const colorBackgroundOpts: Array> = [ { value: TableCellBackgroundDisplayMode.Basic, label: 'Basic' }, @@ -21,7 +21,6 @@ export const ColorBackgroundCellOptionsEditor = ({ cellOptions.mode = v; onChange(cellOptions); }; - // Handle row coloring changes const onColorRowChange = () => { cellOptions.applyToRow = !cellOptions.applyToRow; onChange(cellOptions); @@ -54,7 +53,7 @@ export const ColorBackgroundCellOptionsEditor = ({ /> - { cellOptions.wrapText = updatedCellOptions.wrapText; diff --git a/public/app/plugins/panel/table/table-new/cells/TextWrapOptionsEditor.tsx b/public/app/plugins/panel/table/table-new/cells/TextWrapOptionsEditor.tsx new file mode 100644 index 00000000000..74ddaa092ea --- /dev/null +++ b/public/app/plugins/panel/table/table-new/cells/TextWrapOptionsEditor.tsx @@ -0,0 +1,29 @@ +import { selectors } from '@grafana/e2e-selectors'; +import { t } from '@grafana/i18n'; +import { TableCellOptions, TableWrapTextOptions } from '@grafana/schema'; +import { Field, Switch } from '@grafana/ui'; + +import { TableCellEditorProps } from '../TableCellOptionEditor'; + +export const TextWrapOptionsEditor = ({ + cellOptions, + onChange, +}: TableCellEditorProps) => { + // Handle row coloring changes + const onWrapTextChange = () => { + cellOptions.wrapText = !cellOptions.wrapText; + onChange(cellOptions); + }; + + return ( + <> + + + + + ); +}; diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 339cb81d0d1..927b0c58839 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -12582,7 +12582,10 @@ "name-show-table-header": "Show table header", "name-wrap-header-text": "Wrap header text", "placeholder-column-width": "auto", - "placeholder-fields": "All Numeric Fields" + "placeholder-fields": "All Numeric Fields", + "text-wrap-options": { + "label-wrap-text": "Wrap text" + } }, "table-new": { "category-cell-options": "Cell options", From 2f0190d775062b1f1e33a8b6323f5fad78ddacb0 Mon Sep 17 00:00:00 2001 From: William Wernert Date: Fri, 1 Aug 2025 12:54:13 -0400 Subject: [PATCH 34/89] Alerting: Add store level pagination of rules (#108633) --- pkg/services/ngalert/api/persist.go | 1 + .../ngalert/api/prometheus/api_prometheus.go | 66 ++---- pkg/services/ngalert/models/alert_rule.go | 56 +++++ pkg/services/ngalert/store/alert_rule.go | 180 ++++++++++++++++ pkg/services/ngalert/store/alert_rule_test.go | 197 +++++++++++++++++- pkg/services/ngalert/tests/fakes/rules.go | 87 ++++++++ 6 files changed, 536 insertions(+), 51 deletions(-) diff --git a/pkg/services/ngalert/api/persist.go b/pkg/services/ngalert/api/persist.go index 2150edbe34c..5a60c2e0637 100644 --- a/pkg/services/ngalert/api/persist.go +++ b/pkg/services/ngalert/api/persist.go @@ -23,6 +23,7 @@ type RuleStore interface { GetAlertRuleByUID(ctx context.Context, query *ngmodels.GetAlertRuleByUIDQuery) (*ngmodels.AlertRule, error) GetAlertRulesGroupByRuleUID(ctx context.Context, query *ngmodels.GetAlertRulesGroupByRuleUIDQuery) ([]*ngmodels.AlertRule, error) ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) (ngmodels.RulesGroup, error) + ListAlertRulesByGroup(ctx context.Context, query *ngmodels.ListAlertRulesByGroupQuery) (ngmodels.RulesGroup, string, error) ListDeletedRules(ctx context.Context, orgID int64) ([]*ngmodels.AlertRule, error) // InsertAlertRules will insert all alert rules passed into the function diff --git a/pkg/services/ngalert/api/prometheus/api_prometheus.go b/pkg/services/ngalert/api/prometheus/api_prometheus.go index 2e753a6db1d..c223bce9aac 100644 --- a/pkg/services/ngalert/api/prometheus/api_prometheus.go +++ b/pkg/services/ngalert/api/prometheus/api_prometheus.go @@ -2,7 +2,6 @@ package api import ( "context" - "encoding/base64" "encoding/json" "errors" "fmt" @@ -30,7 +29,7 @@ import ( type RuleStoreReader interface { GetUserVisibleNamespaces(context.Context, int64, identity.Requester) (map[string]*folder.Folder, error) - ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) (ngmodels.RulesGroup, error) + ListAlertRulesStore } type RuleGroupAccessControlService interface { @@ -241,7 +240,7 @@ type RuleGroupStatusesOptions struct { } type ListAlertRulesStore interface { - ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) (ngmodels.RulesGroup, error) + ListAlertRulesByGroup(ctx context.Context, query *ngmodels.ListAlertRulesByGroupQuery) (ngmodels.RulesGroup, string, error) } func (srv PrometheusSrv) RouteGetRuleStatuses(c *contextmodel.ReqContext) response.Response { @@ -476,15 +475,24 @@ func PrepareRuleGroupStatuses(log log.Logger, store ListAlertRulesStore, opts Ru receiverName := opts.Query.Get("receiver_name") - alertRuleQuery := ngmodels.ListAlertRulesQuery{ - OrgID: opts.OrgID, - NamespaceUIDs: namespaceUIDs, - DashboardUID: dashboardUID, - PanelID: panelID, - RuleGroups: ruleGroups, - ReceiverName: receiverName, + maxGroups := getInt64WithDefault(opts.Query, "group_limit", -1) + nextToken := opts.Query.Get("group_next_token") + + if maxGroups == 0 { + return ruleResponse } - ruleList, err := store.ListAlertRules(opts.Ctx, &alertRuleQuery) + + byGroupQuery := ngmodels.ListAlertRulesByGroupQuery{ + OrgID: opts.OrgID, + GroupLimit: maxGroups, + GroupContinueToken: nextToken, + NamespaceUIDs: namespaceUIDs, + DashboardUID: dashboardUID, + PanelID: panelID, + RuleGroups: ruleGroups, + ReceiverName: receiverName, + } + ruleList, continueToken, err := store.ListAlertRulesByGroup(opts.Ctx, &byGroupQuery) if err != nil { ruleResponse.Status = "error" ruleResponse.Error = fmt.Sprintf("failure getting rules: %s", err.Error()) @@ -498,31 +506,9 @@ func PrepareRuleGroupStatuses(log log.Logger, store ListAlertRulesStore, opts Ru ruleNamesSet[rn] = struct{}{} } - maxGroups := getInt64WithDefault(opts.Query, "group_limit", -1) - nextToken := opts.Query.Get("group_next_token") - if nextToken != "" { - if _, err := base64.URLEncoding.DecodeString(nextToken); err != nil { - nextToken = "" - } - } - groupedRules := getGroupedRules(log, ruleList, ruleNamesSet, opts.AllowedNamespaces) rulesTotals := make(map[string]int64, len(groupedRules)) - var newToken string - foundToken := false for _, rg := range groupedRules { - if nextToken != "" && !foundToken { - if !tokenGreaterThanOrEqual(getRuleGroupNextToken(rg.Folder, rg.GroupKey.RuleGroup), nextToken) { - continue - } - foundToken = true - } - - if maxGroups > -1 && len(ruleResponse.Data.RuleGroups) == int(maxGroups) { - newToken = getRuleGroupNextToken(rg.Folder, rg.GroupKey.RuleGroup) - break - } - ruleGroup, totals := toRuleGroup(log, rg.GroupKey, rg.Folder, rg.Rules, provenanceRecords, limitAlertsPerRule, stateFilterSet, matchers, labelOptions, ruleStatusMutator, alertStateMutator) ruleGroup.Totals = totals for k, v := range totals { @@ -546,7 +532,7 @@ func PrepareRuleGroupStatuses(log log.Logger, store ListAlertRulesStore, opts Ru } } - ruleResponse.Data.NextToken = newToken + ruleResponse.Data.NextToken = continueToken // Only return Totals if there is no pagination if maxGroups == -1 { @@ -556,18 +542,6 @@ func PrepareRuleGroupStatuses(log log.Logger, store ListAlertRulesStore, opts Ru return ruleResponse } -func getRuleGroupNextToken(namespace, group string) string { - return base64.URLEncoding.EncodeToString([]byte(namespace + "/" + group)) -} - -// Returns true if tokenA >= tokenB -func tokenGreaterThanOrEqual(tokenA string, tokenB string) bool { - decodedTokenA, _ := base64.URLEncoding.DecodeString(tokenA) - decodedTokenB, _ := base64.URLEncoding.DecodeString(tokenB) - - return string(decodedTokenA) >= string(decodedTokenB) -} - type ruleGroup struct { Folder string GroupKey ngmodels.AlertRuleGroupKey diff --git a/pkg/services/ngalert/models/alert_rule.go b/pkg/services/ngalert/models/alert_rule.go index b4a4a94eaba..b1f415f929d 100644 --- a/pkg/services/ngalert/models/alert_rule.go +++ b/pkg/services/ngalert/models/alert_rule.go @@ -2,6 +2,7 @@ package models import ( "context" + "encoding/base64" "encoding/json" "errors" "fmt" @@ -848,6 +849,61 @@ type GetAlertRulesGroupByRuleUIDQuery struct { OrgID int64 } +type RuleTypeFilter int + +const ( + RuleTypeFilterAll RuleTypeFilter = iota + RuleTypeFilterAlerting + RuleTypeFilterRecording +) + +type ListAlertRulesByGroupQuery struct { + OrgID int64 + RuleUIDs []string + NamespaceUIDs []string + ExcludeOrgs []int64 + RuleGroups []string + + // DashboardUID and PanelID are optional and allow filtering rules + // to return just those for a dashboard and panel. + DashboardUID string + PanelID int64 + + ReceiverName string + TimeIntervalName string + + HasPrometheusRuleDefinition *bool + + RuleType RuleTypeFilter + + GroupLimit int64 // Number of groups to fetch + GroupContinueToken string // Token for per-group pagination +} + +type GroupCursor struct { + NamespaceUID string `json:"n"` + RuleGroup string `json:"g"` +} + +func EncodeGroupCursor(c GroupCursor) string { + data, _ := json.Marshal(c) + return base64.URLEncoding.EncodeToString(data) +} + +func DecodeGroupCursor(token string) (GroupCursor, error) { + var c GroupCursor + data, err := base64.URLEncoding.DecodeString(token) + if err != nil { + return c, fmt.Errorf("failed to decode group token: %w", err) + } + + if err := json.Unmarshal(data, &c); err != nil { + return c, fmt.Errorf("failed to unmarshal group cursor: %w", err) + } + + return c, nil +} + // ListAlertRulesQuery is the query for listing alert rules type ListAlertRulesQuery struct { OrgID int64 diff --git a/pkg/services/ngalert/store/alert_rule.go b/pkg/services/ngalert/store/alert_rule.go index c535bbe4379..ab8676c754d 100644 --- a/pkg/services/ngalert/store/alert_rule.go +++ b/pkg/services/ngalert/store/alert_rule.go @@ -582,6 +582,186 @@ func (st DBstore) CountInFolders(ctx context.Context, orgID int64, folderUIDs [] return count, err } +func (st DBstore) ListAlertRulesByGroup(ctx context.Context, query *ngmodels.ListAlertRulesByGroupQuery) (result ngmodels.RulesGroup, nextToken string, err error) { + err = st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error { + q := sess.Table("alert_rule") + + if query.OrgID >= 0 { + q = q.Where("org_id = ?", query.OrgID) + } + + if query.DashboardUID != "" { + q = q.Where("dashboard_uid = ?", query.DashboardUID) + if query.PanelID != 0 { + q = q.Where("panel_id = ?", query.PanelID) + } + } + + if len(query.NamespaceUIDs) > 0 { + args, in := getINSubQueryArgs(query.NamespaceUIDs) + q = q.Where(fmt.Sprintf("namespace_uid IN (%s)", strings.Join(in, ",")), args...) + } + + if len(query.RuleUIDs) > 0 { + args, in := getINSubQueryArgs(query.RuleUIDs) + q = q.Where(fmt.Sprintf("uid IN (%s)", strings.Join(in, ",")), args...) + } + + var groupsMap map[string]struct{} + if len(query.RuleGroups) > 0 { + groupsMap = make(map[string]struct{}) + args, in := getINSubQueryArgs(query.RuleGroups) + q = q.Where(fmt.Sprintf("rule_group IN (%s)", strings.Join(in, ",")), args...) + for _, group := range query.RuleGroups { + groupsMap[group] = struct{}{} + } + } + + if query.ReceiverName != "" { + q, err = st.filterByContentInNotificationSettings(query.ReceiverName, q) + if err != nil { + return err + } + } + + if query.TimeIntervalName != "" { + q, err = st.filterByContentInNotificationSettings(query.TimeIntervalName, q) + if err != nil { + return err + } + } + + if query.HasPrometheusRuleDefinition != nil { + q, err = st.filterWithPrometheusRuleDefinition(*query.HasPrometheusRuleDefinition, q) + if err != nil { + return err + } + } + + switch query.RuleType { + case ngmodels.RuleTypeFilterAlerting: + q = q.Where("record = ''") + case ngmodels.RuleTypeFilterRecording: + q = q.Where("record != ''") + case ngmodels.RuleTypeFilterAll: + // no additional filter + default: + return fmt.Errorf("unknown rule type filter %q", query.RuleType) + } + + // Order by group first, then by rule index within group + q = q.Asc("namespace_uid", "rule_group", "rule_group_idx", "id") + + var cursor ngmodels.GroupCursor + if query.GroupContinueToken != "" { + // only set the cursor if it's valid, otherwise we'll start from the beginning + if cur, err := ngmodels.DecodeGroupCursor(query.GroupContinueToken); err == nil { + cursor = cur + } + } + + // Build group cursor condition + if cursor.NamespaceUID != "" { + q = buildGroupCursorCondition(q, cursor) + } + + // No arbitrary fetch limit - let the loop control pagination + alertRules := make([]*ngmodels.AlertRule, 0) + rule := new(alertRule) + rows, err := q.Rows(rule) + if err != nil { + return err + } + defer func() { + _ = rows.Close() + }() + + // Process rules and implement per-group pagination + var groupsFetched int64 + for rows.Next() { + rule := new(alertRule) + err = rows.Scan(rule) + if err != nil { + st.Logger.Error("Invalid rule found in DB store, ignoring it", "func", "ListAlertRulesByGroup", "error", err) + continue + } + + converted, err := alertRuleToModelsAlertRule(*rule, st.Logger) + if err != nil { + st.Logger.Error("Invalid rule found in DB store, cannot convert, ignoring it", "func", "ListAlertRulesByGroup", "error", err) + continue + } + + // Check if we've moved to a new group + key := ngmodels.GroupCursor{ + NamespaceUID: converted.NamespaceUID, + RuleGroup: converted.RuleGroup, + } + if key != cursor { + // Check if we've reached the group limit + if query.GroupLimit > 0 && groupsFetched == query.GroupLimit { + // Generate next token for the next group + nextToken = ngmodels.EncodeGroupCursor(cursor) + break + } + + // Reset for new group + cursor = key + groupsFetched++ + } + + // Apply post-query filters + if !shouldIncludeRule(&converted, query, groupsMap) { + continue + } + + alertRules = append(alertRules, &converted) + } + + result = alertRules + return nil + }) + return result, nextToken, err +} + +func buildGroupCursorCondition(sess *xorm.Session, c ngmodels.GroupCursor) *xorm.Session { + return sess.Where("(namespace_uid > ?)", c.NamespaceUID). + Or("(namespace_uid = ? AND rule_group > ?)", c.NamespaceUID, c.RuleGroup) +} + +func shouldIncludeRule(rule *ngmodels.AlertRule, query *ngmodels.ListAlertRulesByGroupQuery, groupsMap map[string]struct{}) bool { + if query.ReceiverName != "" { + if !slices.ContainsFunc(rule.NotificationSettings, func(settings ngmodels.NotificationSettings) bool { + return settings.Receiver == query.ReceiverName + }) { + return false + } + } + + if query.TimeIntervalName != "" { + if !slices.ContainsFunc(rule.NotificationSettings, func(settings ngmodels.NotificationSettings) bool { + return slices.Contains(settings.MuteTimeIntervals, query.TimeIntervalName) || + slices.Contains(settings.ActiveTimeIntervals, query.TimeIntervalName) + }) { + return false + } + } + + if query.HasPrometheusRuleDefinition != nil { + if *query.HasPrometheusRuleDefinition != rule.HasPrometheusRuleDefinition() { + return false + } + } + + if groupsMap != nil { + if _, ok := groupsMap[rule.RuleGroup]; !ok { + return false + } + } + + return true +} + // ListAlertRules is a handler for retrieving alert rules of specific organisation. func (st DBstore) ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) (result ngmodels.RulesGroup, err error) { err = st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error { diff --git a/pkg/services/ngalert/store/alert_rule_test.go b/pkg/services/ngalert/store/alert_rule_test.go index 74f51fd305a..a512b5949b4 100644 --- a/pkg/services/ngalert/store/alert_rule_test.go +++ b/pkg/services/ngalert/store/alert_rule_test.go @@ -1596,14 +1596,14 @@ func TestIntegrationGetRuleVersions(t *testing.T) { // createAlertRule creates an alert rule in the database and returns it. // If a generator is not specified, uniqueness of primary key is not guaranteed. -func createRule(t *testing.T, store *DBstore, generator *models.AlertRuleGenerator) *models.AlertRule { - t.Helper() +func createRule(tb testing.TB, store *DBstore, generator *models.AlertRuleGenerator) *models.AlertRule { + tb.Helper() if generator == nil { generator = models.RuleGen.With(models.RuleMuts.WithIntervalMatching(store.Cfg.BaseInterval)) } rule := generator.GenerateRef() converted, err := alertRuleFromModelsAlertRule(*rule) - require.NoError(t, err) + require.NoError(tb, err) err = store.SQLStore.WithDbSession(context.Background(), func(sess *db.Session) error { converted.ID = 0 _, err := sess.Table(alertRule{}).InsertOne(&converted) @@ -1622,12 +1622,12 @@ func createRule(t *testing.T, store *DBstore, generator *models.AlertRuleGenerat rule = &r return err }) - require.NoError(t, err) + require.NoError(tb, err) return rule } -func setupFolderService(t *testing.T, sqlStore db.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles) folder.Service { +func setupFolderService(t testing.TB, sqlStore db.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles) folder.Service { tracer := tracing.InitializeTracerForTest() inProcBus := bus.ProvideBus(tracer) folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) @@ -1735,6 +1735,169 @@ func TestIntegration_AlertRuleVersionsCleanup(t *testing.T) { }) } +func TestIntegration_ListAlertRulesByGroup(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + + sqlStore := db.InitTestDB(t) + cfg := setting.NewCfg() + cfg.UnifiedAlerting = setting.UnifiedAlertingSettings{ + BaseInterval: time.Duration(rand.Int64N(100)+1) * time.Second, + } + folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()) + bus := &fakeBus{} + orgID := int64(1) + ruleGen := models.RuleGen.With( + models.RuleMuts.WithIntervalMatching(cfg.UnifiedAlerting.BaseInterval), + models.RuleMuts.WithOrgID(orgID), + ) + store := createTestStore(sqlStore, folderService, &logtest.Fake{}, cfg.UnifiedAlerting, bus) + + // set test params + numFolders := 10 + numRules := 50 + rulesPerGroup := 5 + totalGroups := numRules / rulesPerGroup // 10 + + // create rules with different group names + rules, _ := createManyRules(t, + store, + ruleGen, + numFolders, + numRules, + rulesPerGroup, + ) + // sort rules by folder, then group, then group index + slices.SortStableFunc(rules, func(a, b *models.AlertRule) int { + if a.NamespaceUID != b.NamespaceUID { + return strings.Compare(a.NamespaceUID, b.NamespaceUID) + } + if a.RuleGroup != b.RuleGroup { + return strings.Compare(a.RuleGroup, b.RuleGroup) + } + return a.RuleGroupIndex - b.RuleGroupIndex + }) + + t.Run("should return all rules when no limit passed", func(t *testing.T) { + result, continueToken, err := store.ListAlertRulesByGroup(context.Background(), &models.ListAlertRulesByGroupQuery{ + OrgID: orgID, + }) + require.NoError(t, err) + require.Len(t, result, 50, "should return all rules when no limit is set") + require.Empty(t, continueToken, "continue token should be empty when no limit is set") + }) + + t.Run("should return paginated results when group limit is set", func(t *testing.T) { + // random number from 1 to totalGroups - 1 (to ensure we always receive less than totalGroups) + groupLimit := rand.Int64N(int64(totalGroups)-1) + 1 + result, continueToken, err := store.ListAlertRulesByGroup(context.Background(), &models.ListAlertRulesByGroupQuery{ + OrgID: orgID, + GroupLimit: groupLimit, + }) + require.NoError(t, err) + expectedRuleCount := groupLimit * int64(rulesPerGroup) + require.Len(t, result, int(expectedRuleCount), fmt.Sprintf("should return %d rules when group limit is set", expectedRuleCount)) + require.NotEmpty(t, continueToken, "continue token should not be empty when limit is set") + }) + + t.Run("pagination should all for continuation", func(t *testing.T) { + groupLimit := int64(2) // fixed group limit for this test + result, continueToken, err := store.ListAlertRulesByGroup(context.Background(), &models.ListAlertRulesByGroupQuery{ + OrgID: orgID, + GroupLimit: groupLimit, + }) + require.NoError(t, err) + require.Len(t, result, int(groupLimit*int64(rulesPerGroup)), "should return rules for the first two groups") + require.NotEmpty(t, continueToken, "continue token should not be empty") + + for i, rule := range result { + expected := rules[i].RuleGroup + actual := rule.RuleGroup + require.Equal(t, expected, actual, "rules should be ordered by group name") + } + + resultRules := make([]*models.AlertRule, 0, len(result)) + resultRules = append(resultRules, result...) + + // Continue from previous, fetching the rest of the rules + result, continueToken, err = store.ListAlertRulesByGroup(context.Background(), &models.ListAlertRulesByGroupQuery{ + OrgID: orgID, + GroupContinueToken: continueToken, + }) + require.NoError(t, err) + resultRules = append(resultRules, result...) + require.Len(t, resultRules, numRules, "should return all rules when continuing from the last token") + require.Empty(t, continueToken, "continue token should be empty when all rules are fetched") + for i, rule := range resultRules { + expected := rules[i].RuleGroup + actual := rule.RuleGroup + require.Equal(t, expected, actual, "rules should be ordered by group name") + } + }) +} + +func Benchmark_ListAlertRules(b *testing.B) { + orgID := int64(1) + ruleGen := models.RuleGen + + // init + sqlStore := db.InitTestDB(b) + cfg := setting.NewCfg() + cfg.UnifiedAlerting = setting.UnifiedAlertingSettings{ + BaseInterval: time.Duration(rand.Int64N(100)) * time.Second, + } + folderService := setupFolderService(b, sqlStore, cfg, featuremgmt.WithFeatures()) + bus := &fakeBus{} + store := createTestStore(sqlStore, folderService, &logtest.Fake{}, cfg.UnifiedAlerting, bus) + + ruleGen = ruleGen.With( + ruleGen.WithIntervalMatching(cfg.UnifiedAlerting.BaseInterval), + ruleGen.WithOrgID(orgID), + ) + + // define benchmark parameters + numFolders := 5 + numRules := 10000 + rulesPerGroup := 100 + assert.Greater(b, numRules, rulesPerGroup, "n must be greater than rulesPerGroup") + assert.Equal(b, 0, numRules%rulesPerGroup, "n % rulesPerGroup must be zero to create equal groups") + + // create rules and folders (5 folders, each with n/rulesPerGroup rules) + _, _ = createManyRules(b, + store, + ruleGen, + numFolders, // number of folders + numRules, // total number of rules + rulesPerGroup, // rules per group + ) + + b.Run(fmt.Sprintf("list %d rules unpaginated", numRules), func(b *testing.B) { + for b.Loop() { + _, err := store.ListAlertRules(context.Background(), &models.ListAlertRulesQuery{ + OrgID: orgID, + }) + if err != nil { + b.Fatal(err) + } + } + }) + + for _, groupLimit := range []int{1, 2, 5, 10, 50, 100} { + b.Run(fmt.Sprintf("list %d groups paginated", groupLimit), func(b *testing.B) { + for b.Loop() { + _, _, err := store.ListAlertRulesByGroup(context.Background(), &models.ListAlertRulesByGroupQuery{ + OrgID: orgID, + GroupLimit: int64(groupLimit), + }) + if err != nil { + b.Fatal(err) + } + } + }) + } +} + func TestIntegration_ListAlertRules(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") @@ -1975,3 +2138,27 @@ func (f *fakeBus) Publish(ctx context.Context, msg bus.Msg) error { return nil } + +func createManyRules(tb testing.TB, store *DBstore, ruleGen *models.AlertRuleGenerator, numFolders, numRules, rulesPerGroup int) ([]*models.AlertRule, []string) { + tb.Helper() + + require.Greater(tb, numRules, 0, "numRules must be greater than 0") + require.Greater(tb, numFolders, 0, "numFolders must be greater than 0") + require.Greater(tb, numRules, rulesPerGroup, "numRules must be greater than rulesPerGroup") + require.Greater(tb, rulesPerGroup, 0, "rulesPerGroup must be greater than 0") + require.Equal(tb, numRules%rulesPerGroup, 0, "numRules % rulesPerGroup must be zero to create equal groups") + + rules := make([]*models.AlertRule, 0, numRules) + namespaceUIDs := make([]string, numFolders) + for i := range namespaceUIDs { + namespaceUIDs[i] = fmt.Sprintf("ns-%d", i) + } + for i := 0; i < numRules; i++ { + gen := ruleGen.With( + ruleGen.WithNamespaceUID(namespaceUIDs[i%numFolders]), + ruleGen.WithGroupName(fmt.Sprintf("group_%d", i%(numRules/rulesPerGroup))), + ) + rules = append(rules, createRule(tb, store, gen)) + } + return rules, namespaceUIDs +} diff --git a/pkg/services/ngalert/tests/fakes/rules.go b/pkg/services/ngalert/tests/fakes/rules.go index 046522f3214..c17c70bf6c9 100644 --- a/pkg/services/ngalert/tests/fakes/rules.go +++ b/pkg/services/ngalert/tests/fakes/rules.go @@ -4,6 +4,7 @@ import ( "context" "math/rand" "slices" + "strings" "sync" "testing" "time" @@ -185,6 +186,88 @@ func (f *RuleStore) GetAlertRulesGroupByRuleUID(_ context.Context, q *models.Get return ruleList, nil } +func (f *RuleStore) ListAlertRulesByGroup(_ context.Context, q *models.ListAlertRulesByGroupQuery) (models.RulesGroup, string, error) { + f.mtx.Lock() + defer f.mtx.Unlock() + f.RecordedOps = append(f.RecordedOps, *q) + + if err := f.Hook(*q); err != nil { + return nil, "", err + } + + query := &models.ListAlertRulesQuery{ + OrgID: q.OrgID, + NamespaceUIDs: q.NamespaceUIDs, + DashboardUID: q.DashboardUID, + PanelID: q.PanelID, + RuleGroups: q.RuleGroups, + RuleUIDs: q.RuleUIDs, + ReceiverName: q.ReceiverName, + HasPrometheusRuleDefinition: q.HasPrometheusRuleDefinition, + } + + ruleList, err := f.listAlertRules(query) + if err != nil { + return nil, "", err + } + + // < group limit logic > + + // sort rules to ensure order is consistent, pagination depends on this + slices.SortFunc(ruleList, func(a, b *models.AlertRule) int { + nsCmp := strings.Compare(a.NamespaceUID, b.NamespaceUID) + if nsCmp != 0 { + return nsCmp + } + rgCmp := strings.Compare(a.RuleGroup, b.RuleGroup) + if rgCmp != 0 { + return rgCmp + } + return models.RulesGroupComparer(a, b) + }) + + var nextToken string + var cursor models.GroupCursor + if q.GroupContinueToken != "" { + if cur, err := models.DecodeGroupCursor(q.GroupContinueToken); err == nil { + cursor = cur + } + } + + if q.GroupLimit < 0 { + return ruleList, "", nil + } + + outputRules := make([]*models.AlertRule, 0, len(ruleList)) + var groupsFetched int64 + initialCursor := cursor + for _, r := range ruleList { + // skip rules before the initial cursor + if initialCursor.NamespaceUID != "" && + (strings.Compare(r.NamespaceUID, initialCursor.NamespaceUID) < 0 || + (strings.Compare(r.NamespaceUID, initialCursor.NamespaceUID) == 0 && strings.Compare(r.RuleGroup, initialCursor.RuleGroup) <= 0)) { + continue + } + + key := models.GroupCursor{ + NamespaceUID: r.NamespaceUID, + RuleGroup: r.RuleGroup, + } + if key != cursor { + if q.GroupLimit > 0 && groupsFetched == q.GroupLimit { + nextToken = models.EncodeGroupCursor(cursor) + break + } + cursor = key + groupsFetched++ + } + + outputRules = append(outputRules, r) + } + + return outputRules, nextToken, nil +} + func (f *RuleStore) ListAlertRules(_ context.Context, q *models.ListAlertRulesQuery) (models.RulesGroup, error) { f.mtx.Lock() defer f.mtx.Unlock() @@ -194,6 +277,10 @@ func (f *RuleStore) ListAlertRules(_ context.Context, q *models.ListAlertRulesQu return nil, err } + return f.listAlertRules(q) +} + +func (f *RuleStore) listAlertRules(q *models.ListAlertRulesQuery) (models.RulesGroup, error) { hasDashboard := func(r *models.AlertRule, dashboardUID string, panelID int64) bool { if dashboardUID != "" { if r.DashboardUID == nil || *r.DashboardUID != dashboardUID { From eb3a457c6dc95ed1ceba0d9ea48eada5d6a5fed7 Mon Sep 17 00:00:00 2001 From: Alexander Akhmetov Date: Fri, 1 Aug 2025 21:15:21 +0200 Subject: [PATCH 35/89] Alerting: Support JSON responses in the Prometheus conversion API (#109070) --- .../ngalert/api/api_convert_prometheus.go | 36 +++- .../api/api_convert_prometheus_test.go | 185 +++++++++++++++--- 2 files changed, 188 insertions(+), 33 deletions(-) diff --git a/pkg/services/ngalert/api/api_convert_prometheus.go b/pkg/services/ngalert/api/api_convert_prometheus.go index 345569be3c8..97afcf561d1 100644 --- a/pkg/services/ngalert/api/api_convert_prometheus.go +++ b/pkg/services/ngalert/api/api_convert_prometheus.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "mime" "net/http" "path/filepath" "strconv" @@ -155,7 +156,7 @@ func NewConvertPrometheusSrv( // RouteConvertPrometheusGetRules returns all Grafana-managed alert rules in all namespaces (folders) // that were imported from a Prometheus-compatible source. -// It responds with a YAML containing a mapping of folders to arrays of Prometheus rule groups. +// It responds with JSON or YAML containing a mapping of folders to arrays of Prometheus rule groups. func (srv *ConvertPrometheusSrv) RouteConvertPrometheusGetRules(c *contextmodel.ReqContext) response.Response { logger := srv.logger.FromContext(c.Req.Context()) @@ -166,7 +167,7 @@ func (srv *ConvertPrometheusSrv) RouteConvertPrometheusGetRules(c *contextmodel. if len(folders) == 0 || errors.Is(err, dashboards.ErrFolderNotFound) { // If there is no such folder or no children, return empty response // because mimirtool expects 200 OK response in this case. - return response.YAML(http.StatusOK, map[string][]apimodels.PrometheusRuleGroup{}) + return convertPrometheusResponse(c, http.StatusOK, map[string][]apimodels.PrometheusRuleGroup{}) } if err != nil { logger.Error("Failed to get folders", "error", err) @@ -193,7 +194,7 @@ func (srv *ConvertPrometheusSrv) RouteConvertPrometheusGetRules(c *contextmodel. return errorToResponse(err) } - return response.YAML(http.StatusOK, namespaces) + return convertPrometheusResponse(c, http.StatusOK, namespaces) } // RouteConvertPrometheusDeleteNamespace deletes all rule groups that were imported from a Prometheus-compatible source @@ -256,7 +257,7 @@ func (srv *ConvertPrometheusSrv) RouteConvertPrometheusDeleteRuleGroup(c *contex } // RouteConvertPrometheusGetNamespace returns the Grafana-managed alert rules for a specified namespace (folder). -// It responds with a YAML containing a mapping of a single folder to an array of Prometheus rule groups. +// It responds with JSON or YAML containing a mapping of a single folder to an array of Prometheus rule groups. func (srv *ConvertPrometheusSrv) RouteConvertPrometheusGetNamespace(c *contextmodel.ReqContext, namespaceTitle string) response.Response { logger := srv.logger.FromContext(c.Req.Context()) @@ -286,11 +287,11 @@ func (srv *ConvertPrometheusSrv) RouteConvertPrometheusGetNamespace(c *contextmo return errorToResponse(err) } - return response.YAML(http.StatusOK, ns) + return convertPrometheusResponse(c, http.StatusOK, ns) } // RouteConvertPrometheusGetRuleGroup retrieves a single rule group for a given namespace (folder) -// in Prometheus-compatible YAML format if it was imported from a Prometheus-compatible source. +// in Prometheus-compatible JSON or YAML format if it was imported from a Prometheus-compatible source. func (srv *ConvertPrometheusSrv) RouteConvertPrometheusGetRuleGroup(c *contextmodel.ReqContext, namespaceTitle string, group string) response.Response { logger := srv.logger.FromContext(c.Req.Context()) @@ -332,7 +333,7 @@ func (srv *ConvertPrometheusSrv) RouteConvertPrometheusGetRuleGroup(c *contextmo return errorToResponse(err) } - return response.YAML(http.StatusOK, promGroup) + return convertPrometheusResponse(c, http.StatusOK, promGroup) } // RouteConvertPrometheusPostRuleGroup converts a Prometheus rule group into a Grafana rule group @@ -608,7 +609,7 @@ func (srv *ConvertPrometheusSrv) RouteConvertPrometheusGetAlertmanagerConfig(c * TemplateFiles: extraCfg.TemplateFiles, } - resp := response.YAML(http.StatusOK, respBody) + resp := convertPrometheusResponse(c, http.StatusOK, respBody) resp.SetHeader(configIdentifierHeader, extraCfg.Identifier) resp.SetHeader(mergeMatchersHeader, formatMergeMatchers(extraCfg.MergeMatchers)) @@ -808,3 +809,22 @@ func parseConfigIdentifierHeader(c *contextmodel.ReqContext) string { } return identifier } + +// convertPrometheusResponse returns a JSON or YAML response based on the Accept header. +// Default is YAML for backward compatibility with mimirtool. +func convertPrometheusResponse(c *contextmodel.ReqContext, status int, body interface{}) *response.NormalResponse { + acceptHeader := c.Req.Header.Get("Accept") + + for _, accept := range strings.Split(acceptHeader, ",") { + mediaType, _, err := mime.ParseMediaType(accept) + if err != nil { + continue + } + + if mediaType == "application/json" { + return response.JSON(status, body) + } + } + + return response.YAML(status, body) +} diff --git a/pkg/services/ngalert/api/api_convert_prometheus_test.go b/pkg/services/ngalert/api/api_convert_prometheus_test.go index ea3a9a16a13..ca7833361c2 100644 --- a/pkg/services/ngalert/api/api_convert_prometheus_test.go +++ b/pkg/services/ngalert/api/api_convert_prometheus_test.go @@ -6,6 +6,7 @@ import ( "errors" "net/http" "net/http/httptest" + "strings" "testing" "time" @@ -597,17 +598,34 @@ func TestRouteConvertPrometheusGetRuleGroup(t *testing.T) { GenerateRef() ruleStore.PutRule(context.Background(), ruleInOtherFolder) - getResp := srv.RouteConvertPrometheusGetRuleGroup(rc, fldr.Title, groupKey.RuleGroup) - require.Equal(t, http.StatusOK, getResp.Status()) + t.Run("YAML response", func(t *testing.T) { + getResp := srv.RouteConvertPrometheusGetRuleGroup(rc, fldr.Title, groupKey.RuleGroup) + require.Equal(t, http.StatusOK, getResp.Status()) - var respGroup apimodels.PrometheusRuleGroup - err := yaml.Unmarshal(getResp.Body(), &respGroup) - require.NoError(t, err) + var respGroup apimodels.PrometheusRuleGroup + err := yaml.Unmarshal(getResp.Body(), &respGroup) + require.NoError(t, err) - require.Equal(t, groupKey.RuleGroup, respGroup.Name) - require.Equal(t, prommodel.Duration(time.Duration(rule.IntervalSeconds)*time.Second), respGroup.Interval) - require.Len(t, respGroup.Rules, 1) - require.Equal(t, promRule.Alert, respGroup.Rules[0].Alert) + require.Equal(t, groupKey.RuleGroup, respGroup.Name) + require.Equal(t, prommodel.Duration(time.Duration(rule.IntervalSeconds)*time.Second), respGroup.Interval) + require.Len(t, respGroup.Rules, 1) + require.Equal(t, promRule.Alert, respGroup.Rules[0].Alert) + }) + + t.Run("JSON response", func(t *testing.T) { + rc.Req.Header.Set("Accept", "application/json") + getResp := srv.RouteConvertPrometheusGetRuleGroup(rc, fldr.Title, groupKey.RuleGroup) + require.Equal(t, http.StatusOK, getResp.Status()) + + var jsonGroup apimodels.PrometheusRuleGroup + err := json.Unmarshal(getResp.Body(), &jsonGroup) + require.NoError(t, err) + + require.Equal(t, groupKey.RuleGroup, jsonGroup.Name) + require.Equal(t, prommodel.Duration(time.Duration(rule.IntervalSeconds)*time.Second), jsonGroup.Interval) + require.Len(t, jsonGroup.Rules, 1) + require.Equal(t, promRule.Alert, jsonGroup.Rules[0].Alert) + }) }) } @@ -690,16 +708,32 @@ func TestRouteConvertPrometheusGetNamespace(t *testing.T) { ruleStore.PutRule(context.Background(), rule) } - response := srv.RouteConvertPrometheusGetNamespace(rc, fldr.Title) - require.Equal(t, http.StatusOK, response.Status()) + t.Run("YAML response", func(t *testing.T) { + response := srv.RouteConvertPrometheusGetNamespace(rc, fldr.Title) + require.Equal(t, http.StatusOK, response.Status()) - var respNamespaces map[string][]apimodels.PrometheusRuleGroup - err := yaml.Unmarshal(response.Body(), &respNamespaces) - require.NoError(t, err) + var respNamespaces map[string][]apimodels.PrometheusRuleGroup + err := yaml.Unmarshal(response.Body(), &respNamespaces) + require.NoError(t, err) - require.Len(t, respNamespaces, 1) - require.Contains(t, respNamespaces, fldr.Title) - require.ElementsMatch(t, respNamespaces[fldr.Title], []apimodels.PrometheusRuleGroup{promGroup1, promGroup2}) + require.Len(t, respNamespaces, 1) + require.Contains(t, respNamespaces, fldr.Title) + require.ElementsMatch(t, respNamespaces[fldr.Title], []apimodels.PrometheusRuleGroup{promGroup1, promGroup2}) + }) + + t.Run("JSON response", func(t *testing.T) { + rc.Req.Header.Set("Accept", "application/json") + response := srv.RouteConvertPrometheusGetNamespace(rc, fldr.Title) + require.Equal(t, http.StatusOK, response.Status()) + + var jsonNamespaces map[string][]apimodels.PrometheusRuleGroup + err := json.Unmarshal(response.Body(), &jsonNamespaces) + require.NoError(t, err) + + require.Len(t, jsonNamespaces, 1) + require.Contains(t, jsonNamespaces, fldr.Title) + require.ElementsMatch(t, jsonNamespaces[fldr.Title], []apimodels.PrometheusRuleGroup{promGroup1, promGroup2}) + }) }) } @@ -821,19 +855,120 @@ func TestRouteConvertPrometheusGetRules(t *testing.T) { ruleStore.PutRule(context.Background(), rule) } - response := srv.RouteConvertPrometheusGetRules(rc) - require.Equal(t, http.StatusOK, response.Status()) + t.Run("YAML response", func(t *testing.T) { + response := srv.RouteConvertPrometheusGetRules(rc) + require.Equal(t, http.StatusOK, response.Status()) - var respNamespaces map[string][]apimodels.PrometheusRuleGroup - err := yaml.Unmarshal(response.Body(), &respNamespaces) - require.NoError(t, err) + var respNamespaces map[string][]apimodels.PrometheusRuleGroup + err := yaml.Unmarshal(response.Body(), &respNamespaces) + require.NoError(t, err) - require.Len(t, respNamespaces, 1) - require.Contains(t, respNamespaces, fldr.Title) - require.ElementsMatch(t, respNamespaces[fldr.Title], []apimodels.PrometheusRuleGroup{promGroup1, promGroup2}) + require.Len(t, respNamespaces, 1) + require.Contains(t, respNamespaces, fldr.Title) + require.ElementsMatch(t, respNamespaces[fldr.Title], []apimodels.PrometheusRuleGroup{promGroup1, promGroup2}) + }) + + t.Run("JSON response", func(t *testing.T) { + rc.Req.Header.Set("Accept", "application/json") + response := srv.RouteConvertPrometheusGetRules(rc) + require.Equal(t, http.StatusOK, response.Status()) + + var jsonNamespaces map[string][]apimodels.PrometheusRuleGroup + err := json.Unmarshal(response.Body(), &jsonNamespaces) + require.NoError(t, err) + + require.Len(t, jsonNamespaces, 1) + require.Contains(t, jsonNamespaces, fldr.Title) + require.ElementsMatch(t, jsonNamespaces[fldr.Title], []apimodels.PrometheusRuleGroup{promGroup1, promGroup2}) + }) }) } +func TestConvertPrometheusResponse(t *testing.T) { + testData := map[string][]apimodels.PrometheusRuleGroup{ + "test": { + { + Name: "test-group", + Rules: []apimodels.PrometheusRule{ + { + Alert: "TestAlert", + Expr: "up == 0", + }, + }, + }, + }, + } + + testCases := []struct { + name string + acceptHeader string + expectedType string + checkResponse func(t *testing.T, body []byte) + }{ + { + name: "by default returns YAML", + expectedType: "text/yaml", + checkResponse: func(t *testing.T, body []byte) { + require.True(t, strings.Contains(string(body), "test-group")) + require.True(t, strings.Contains(string(body), "TestAlert")) + var result map[string][]apimodels.PrometheusRuleGroup + err := yaml.Unmarshal(body, &result) + require.NoError(t, err) + }, + }, + { + name: "with application/json Accept header returns JSON", + acceptHeader: "application/json", + expectedType: "application/json", + checkResponse: func(t *testing.T, body []byte) { + require.True(t, strings.Contains(string(body), "test-group")) + require.True(t, strings.Contains(string(body), "TestAlert")) + var result map[string][]apimodels.PrometheusRuleGroup + err := json.Unmarshal(body, &result) + require.NoError(t, err) + }, + }, + { + name: "with application/yaml accept header returns YAML", + acceptHeader: "application/yaml", + expectedType: "text/yaml", + checkResponse: func(t *testing.T, body []byte) { + require.True(t, strings.Contains(string(body), "test-group")) + require.True(t, strings.Contains(string(body), "TestAlert")) + var result map[string][]apimodels.PrometheusRuleGroup + err := yaml.Unmarshal(body, &result) + require.NoError(t, err) + }, + }, + { + name: "with a header with both json and yaml returns JSON", + acceptHeader: "application/yaml, application/json", + expectedType: "application/json", + checkResponse: func(t *testing.T, body []byte) { + require.True(t, strings.Contains(string(body), "test-group")) + require.True(t, strings.Contains(string(body), "TestAlert")) + var result map[string][]apimodels.PrometheusRuleGroup + err := json.Unmarshal(body, &result) + require.NoError(t, err) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + rc := createRequestCtx() + if tc.acceptHeader != "" { + rc.Req.Header.Set("Accept", tc.acceptHeader) + } + + response := convertPrometheusResponse(rc, http.StatusOK, testData) + + require.Equal(t, http.StatusOK, response.Status()) + tc.checkResponse(t, response.Body()) + }) + } +} + func TestRouteConvertPrometheusDeleteNamespace(t *testing.T) { t.Run("for non-existent folder should return 404", func(t *testing.T) { srv, _, _ := createConvertPrometheusSrv(t) From b36a8e84ccb35b8ec3770b5a03c606b82453df2a Mon Sep 17 00:00:00 2001 From: Alexander Akhmetov Date: Fri, 1 Aug 2025 21:15:33 +0200 Subject: [PATCH 36/89] Alerting: Document "Get rule group" Prometheus conversion API endpoint (#109075) --- docs/sources/alerting/alerting-rules/alerting-migration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/sources/alerting/alerting-rules/alerting-migration.md b/docs/sources/alerting/alerting-rules/alerting-migration.md index 328ca0eefb7..08a301c24c3 100644 --- a/docs/sources/alerting/alerting-rules/alerting-migration.md +++ b/docs/sources/alerting/alerting-rules/alerting-migration.md @@ -287,6 +287,7 @@ The `GET` and `DELETE` endpoints work only with provisioned and imported alert r | -------- | ------------------------------------------------------------ | --------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | | GET | `/convert/prometheus/config/v1/rules` | Get all imported rule groups across all namespaces. | [List rule groups](/docs/mimir/latest/references/http-api/#list-rule-groups) | | GET | `/convert/prometheus/config/v1/rules/:namespaceTitle` | Get imported rule groups in a specific namespace. | [Get rule groups by namespace](/docs/mimir/latest/references/http-api/#get-rule-groups-by-namespace) | +| GET | `/convert/prometheus/config/v1/rules/:namespaceTitle/:group` | Get imported rule group in a specific namespace. | [Get rule group](/docs/mimir/latest/references/http-api/#get-rule-group) | | DELETE | `/convert/prometheus/config/v1/rules/:namespaceTitle` | Delete all imported alert rules in a namespace. | [Delete namespace](/docs/mimir/latest/references/http-api/#delete-namespace) | | DELETE | `/convert/prometheus/config/v1/rules/:namespaceTitle/:group` | Delete a specific imported rule group. | [Delete rule group](/docs/mimir/latest/references/http-api/#delete-rule-group) | From 172a69da751f20253e6584d810c883effa6de293 Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Fri, 1 Aug 2025 14:29:42 -0500 Subject: [PATCH 37/89] Feature toggle: Cleanup old ones (#109072) --- e2e/dashboards-search-suite/mode0.ini | 4 ---- e2e/dashboards-search-suite/mode1.ini | 4 ---- e2e/dashboards-search-suite/mode2-legacy-search-api.ini | 4 ---- e2e/dashboards-search-suite/mode2.ini | 4 ---- e2e/dashboards-search-suite/mode3.ini | 4 ---- e2e/dashboards-search-suite/mode4.ini | 4 ---- e2e/dashboards-search-suite/mode5.ini | 4 ---- pkg/services/featuremgmt/toggles-gitlog.csv | 4 ---- pkg/storage/unified/README.md | 4 ---- 9 files changed, 36 deletions(-) diff --git a/e2e/dashboards-search-suite/mode0.ini b/e2e/dashboards-search-suite/mode0.ini index 1e0c6c55b0a..e8f0a768c77 100644 --- a/e2e/dashboards-search-suite/mode0.ini +++ b/e2e/dashboards-search-suite/mode0.ini @@ -1,14 +1,10 @@ [server] [feature_toggles] -kubernetesFolders = true unifiedStorageSearch = true unifiedStorageSearchUI = true grafanaAPIServerWithExperimentalAPIs = true -kubernetesDashboardsAPI = true -kubernetesCliDashboards = true unifiedStorageSearchSprinkles = true -kubernetesFoldersServiceV2 = true unifiedStorageSearchPermissionFiltering = true [unified_storage.folders.folder.grafana.app] diff --git a/e2e/dashboards-search-suite/mode1.ini b/e2e/dashboards-search-suite/mode1.ini index 56e16cb4cff..5beecc31f65 100644 --- a/e2e/dashboards-search-suite/mode1.ini +++ b/e2e/dashboards-search-suite/mode1.ini @@ -1,14 +1,10 @@ [server] [feature_toggles] -kubernetesFolders = true unifiedStorageSearch = true unifiedStorageSearchUI = true grafanaAPIServerWithExperimentalAPIs = true -kubernetesDashboardsAPI = true -kubernetesCliDashboards = true unifiedStorageSearchSprinkles = true -kubernetesFoldersServiceV2 = true unifiedStorageSearchPermissionFiltering = true [unified_storage.folders.folder.grafana.app] diff --git a/e2e/dashboards-search-suite/mode2-legacy-search-api.ini b/e2e/dashboards-search-suite/mode2-legacy-search-api.ini index 4b671c8b78b..45b16de4034 100644 --- a/e2e/dashboards-search-suite/mode2-legacy-search-api.ini +++ b/e2e/dashboards-search-suite/mode2-legacy-search-api.ini @@ -1,14 +1,10 @@ [server] [feature_toggles] -kubernetesFolders = true unifiedStorageSearch = true unifiedStorageSearchUI = false grafanaAPIServerWithExperimentalAPIs = true -kubernetesDashboardsAPI = true -kubernetesCliDashboards = true unifiedStorageSearchSprinkles = true -kubernetesFoldersServiceV2 = true unifiedStorageSearchPermissionFiltering = true [unified_storage.folders.folder.grafana.app] diff --git a/e2e/dashboards-search-suite/mode2.ini b/e2e/dashboards-search-suite/mode2.ini index af96c552def..55538ee82e3 100644 --- a/e2e/dashboards-search-suite/mode2.ini +++ b/e2e/dashboards-search-suite/mode2.ini @@ -1,14 +1,10 @@ [server] [feature_toggles] -kubernetesFolders = true unifiedStorageSearch = true unifiedStorageSearchUI = true grafanaAPIServerWithExperimentalAPIs = true -kubernetesDashboardsAPI = true -kubernetesCliDashboards = true unifiedStorageSearchSprinkles = true -kubernetesFoldersServiceV2 = true unifiedStorageSearchPermissionFiltering = true [unified_storage.folders.folder.grafana.app] diff --git a/e2e/dashboards-search-suite/mode3.ini b/e2e/dashboards-search-suite/mode3.ini index a4a56f9d80c..5955dfcd72a 100644 --- a/e2e/dashboards-search-suite/mode3.ini +++ b/e2e/dashboards-search-suite/mode3.ini @@ -1,14 +1,10 @@ [server] [feature_toggles] -kubernetesFolders = true unifiedStorageSearch = true unifiedStorageSearchUI = true grafanaAPIServerWithExperimentalAPIs = true -kubernetesDashboardsAPI = true -kubernetesCliDashboards = true unifiedStorageSearchSprinkles = true -kubernetesFoldersServiceV2 = true unifiedStorageSearchPermissionFiltering = true [unified_storage.folders.folder.grafana.app] diff --git a/e2e/dashboards-search-suite/mode4.ini b/e2e/dashboards-search-suite/mode4.ini index dd774cb2f14..e0f6f6d892d 100644 --- a/e2e/dashboards-search-suite/mode4.ini +++ b/e2e/dashboards-search-suite/mode4.ini @@ -1,14 +1,10 @@ [server] [feature_toggles] -kubernetesFolders = true unifiedStorageSearch = true unifiedStorageSearchUI = true grafanaAPIServerWithExperimentalAPIs = true -kubernetesDashboardsAPI = true -kubernetesCliDashboards = true unifiedStorageSearchSprinkles = true -kubernetesFoldersServiceV2 = true unifiedStorageSearchPermissionFiltering = true [unified_storage.folders.folder.grafana.app] diff --git a/e2e/dashboards-search-suite/mode5.ini b/e2e/dashboards-search-suite/mode5.ini index 83437bda185..8722cb091eb 100644 --- a/e2e/dashboards-search-suite/mode5.ini +++ b/e2e/dashboards-search-suite/mode5.ini @@ -1,14 +1,10 @@ [server] [feature_toggles] -kubernetesFolders = true unifiedStorageSearch = true unifiedStorageSearchUI = true grafanaAPIServerWithExperimentalAPIs = true -kubernetesDashboardsAPI = true -kubernetesCliDashboards = true unifiedStorageSearchSprinkles = true -kubernetesFoldersServiceV2 = true unifiedStorageSearchPermissionFiltering = true [unified_storage.folders.folder.grafana.app] diff --git a/pkg/services/featuremgmt/toggles-gitlog.csv b/pkg/services/featuremgmt/toggles-gitlog.csv index 4a0ff55bc6e..3024aa121f9 100644 --- a/pkg/services/featuremgmt/toggles-gitlog.csv +++ b/pkg/services/featuremgmt/toggles-gitlog.csv @@ -360,7 +360,6 @@ appPlatformAccessTokens,2024-09-05T16:18:44Z,2024-10-14T10:47:18Z,d5ebaa0ef92ede appSidecar,2024-09-09T12:45:05Z,2025-04-10T20:04:12Z,5e2ac24890906e5070323d87730dd78a4f885963,Andrej Ocenas vizActions,2024-09-09T14:11:55Z,2025-02-26T23:15:01Z,af48d3db1eb2d8681843f5997e50fea5e5ea3096,Adela Almasan groupAttributeSync,2024-09-09T15:29:43Z,,6ded6a8872204a818b3795dc733cc5fe5db066a0,Aaron Godin -kubernetesFolders,2024-09-10T09:22:08Z,2025-01-23T14:25:03Z,b12a29a1dac8b9aec4a99be08e1665939cb27dc5,Arati R. alertingFilterV2,2024-09-11T11:29:26Z,,90ee52e8d9c14237f8a57b622c0def7512e657cd,Gilles De Mey improvedExternalSessionHandling,2024-09-17T10:54:39Z,,41cd0f51800d4849345fc0980ca4173967fc8e9e,Misi datasourceAPIServers,2024-09-19T08:28:27Z,,f21a5987a22bcdb596d6a258d2960e4151348b63,Ryan McKinley @@ -374,7 +373,6 @@ grafanaAPIServerTestingWithExperimentalAPIs,2024-10-03T10:11:40Z,2025-01-23T14:2 pluginsSriChecks,2024-10-04T12:55:09Z,,0db65d229e36b78802c1e8bd0713ac44e7a7cdc7,Giuseppe Guerra onPremToCloudMigrationsAlerts,2024-10-07T10:53:24Z,2024-12-17T11:56:18Z,712314e8324fd86ec33ecb840f868eb1f1cac154,Matheus Macabu appPlatformGrpcClientAuth,2024-10-14T10:47:18Z,,a69ee676babc7644da41781efc5ae2c301f06de6,Claudiu Dragalina-Paraipan -kubernetesDashboardsAPI,2024-10-15T19:30:05Z,2024-12-10T18:35:36Z,644a16048f034f6bc79883678f1f1a4b48233483,Stephanie Hingtgen unifiedStorageBigObjectsSupport,2024-10-17T10:18:29Z,,3457f219be1c8bce99f713d7a907ee339ef38229,Ryan McKinley timeRangeProvider,2024-10-22T10:52:33Z,,3bf3290340a7842bb1d83647343234b2e9e83b18,Andrej Ocenas dashboardNewLayouts,2024-10-23T08:55:45Z,,b700de81224caacd327fafb6ce0dfda8b38d39c6,Torkel Ödegaard @@ -407,7 +405,6 @@ feedbackButton,2024-12-02T17:08:15Z,,8a1b89a5ebb847f6b29e92dcea796f00c30431d6,Mi elasticsearchCrossClusterSearch,2024-12-12T22:20:04Z,,b3a12f486eba69e20dd7ff3a3d4dd065ede7a99f,Isabella Siu unifiedHistory,2024-12-13T10:41:18Z,,aac62c89dae1092836a91d1b6ae6bd7127fe676a,Laura Fernández lokiLabelNamesQueryApi,2024-12-13T14:31:41Z,,5ac7443fcec0db412d3333044a82c2c26b5aece7,Sven Grossmann -kubernetesCliDashboards,2024-12-13T22:55:43Z,2025-02-18T23:11:26Z,8f6e9f8ed0a5024a510cc337c9f1e6972bfb23d4,Stephanie Hingtgen useV2DashboardsAPI,2024-12-17T21:17:09Z,2025-03-12T17:43:32Z,070f0e4457c5967102ef157197073dc2662f6fb8,Dominik Prokop investigationsBackend,2024-12-18T08:31:03Z,,f46c07aba7b6faccd2ecafc83051d1410cacc867,Jackson Coelho unifiedStorageSearchSprinkles,2024-12-18T17:00:54Z,,4837585cab0fd84184a8c6f5d6891f442a2b95f1,owensmallwood @@ -421,7 +418,6 @@ improvedExternalSessionHandlingSAML,2025-01-09T17:02:49Z,,c52ec21c75ab72c2f7d282 teamHttpHeadersMimir,2025-01-13T10:42:47Z,,04acbcdef23f673bd6bbfdbbece29c9769ce155a,Eric Leijonmarck ABTestFeatureToggleA,2025-01-13T21:13:13Z,2025-05-27T19:18:23Z,009d7f42b3d09b3a6be1f00f07314e2b25af7ebc,Nathan Marrs ABTestFeatureToggleB,2025-01-13T21:13:13Z,2025-05-27T19:18:23Z,009d7f42b3d09b3a6be1f00f07314e2b25af7ebc,Nathan Marrs -kubernetesFoldersServiceV2,2025-01-13T21:15:35Z,2025-02-18T23:11:26Z,766d645d827f5e6e0872ae30e5fe23226ae85785,maicon queryLibraryDashboards,2025-01-14T11:01:15Z,2025-02-14T16:39:22Z,740cd22fe51a3543c182857f31fc97fd42263306,Ashley Harrison elasticsearchImprovedParsing,2025-01-15T17:05:54Z,,bab55a4cb84f2ba57838f96a492ab9aa7f307957,Adam Yeats grafanaAdvisor,2025-01-20T10:08:00Z,,c1364d6be6f552203ba786f17a89664304b89247,Andres Martinez Gotor diff --git a/pkg/storage/unified/README.md b/pkg/storage/unified/README.md index dd53fa622b0..608f51c062d 100644 --- a/pkg/storage/unified/README.md +++ b/pkg/storage/unified/README.md @@ -367,8 +367,6 @@ signing_keys_url = http://localhost:3011/api/signing-keys/keys mode = "on-prem" [feature_toggles] -kubernetesDashboardsAPI = true -kubernetesFolders = true unifiedStorage = true unifiedStorageSearch = true @@ -415,8 +413,6 @@ http_port = 3011 http_addr = "127.0.0.2" [feature_toggles] -kubernetesDashboardsAPI = true -kubernetesFolders = true unifiedStorageSearchUI = true [unified_storage.dashboards.dashboard.grafana.app] From 9f4773c9a5a35f7452e3df92006ac050fd397052 Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Fri, 1 Aug 2025 14:35:18 -0500 Subject: [PATCH 38/89] Provisioning: Extract to apps submodule (#109074) --- .github/CODEOWNERS | 2 +- Dockerfile | 1 + apps/provisioning/Makefile | 26 + apps/provisioning/go.mod | 78 + apps/provisioning/go.sum | 195 ++ apps/provisioning/kinds/cue.mod/module.cue | 4 + apps/provisioning/kinds/manifest.cue | 9 + .../kinds/provisioning/v0alpha1/constants.go | 18 + .../v0alpha1/repository_codec_gen.go | 28 + .../v0alpha1/repository_metadata_gen.go | 31 + .../v0alpha1/repository_object_gen.go | 319 +++ .../v0alpha1/repository_schema_gen.go | 34 + .../v0alpha1/repository_spec_gen.go | 169 ++ .../v0alpha1/repository_status_gen.go | 137 ++ .../provisioning/v0alpha1/zz_openapi_gen.go | 879 ++++++++ .../kinds/provisioning_manifest.go | 83 + apps/provisioning/kinds/repository.cue | 171 ++ .../apis/provisioning/v0alpha1/classic.go | 0 .../pkg}/apis/provisioning/v0alpha1/doc.go | 2 +- .../pkg}/apis/provisioning/v0alpha1/jobs.go | 0 .../apis/provisioning/v0alpha1/register.go | 0 .../apis/provisioning/v0alpha1/settings.go | 0 .../pkg}/apis/provisioning/v0alpha1/types.go | 0 .../apis/provisioning/v0alpha1/types_test.go | 2 +- .../v0alpha1/zz_generated.deepcopy.go | 0 .../v0alpha1/zz_generated.defaults.go | 0 .../v0alpha1/zz_generated.openapi.go | 218 +- ...enerated.openapi_violation_exceptions.list | 26 + .../applyconfiguration/internal/internal.go | 48 + .../v0alpha1/bitbucketrepositoryconfig.go | 0 .../v0alpha1/githubrepositoryconfig.go | 0 .../v0alpha1/gitlabrepositoryconfig.go | 0 .../v0alpha1/gitrepositoryconfig.go | 0 .../provisioning/v0alpha1/healthstatus.go | 0 .../v0alpha1/localrepositoryconfig.go | 0 .../provisioning/v0alpha1/repository.go | 0 .../provisioning/v0alpha1/repositoryspec.go | 2 +- .../provisioning/v0alpha1/repositorystatus.go | 0 .../provisioning/v0alpha1/resourcecount.go | 0 .../provisioning/v0alpha1/syncoptions.go | 2 +- .../provisioning/v0alpha1/syncstatus.go | 2 +- .../provisioning/v0alpha1/webhookstatus.go | 0 .../pkg/generated/applyconfiguration/utils.go | 54 + .../clientset/versioned/clientset.go | 106 + .../versioned/fake/clientset_generated.go | 117 + .../generated/clientset/versioned/fake/doc.go | 6 + .../clientset/versioned/fake/register.go | 42 + .../clientset/versioned/scheme/doc.go | 6 + .../clientset/versioned/scheme/register.go | 42 + .../typed/provisioning/v0alpha1/doc.go | 0 .../typed/provisioning/v0alpha1/fake/doc.go | 0 .../v0alpha1/fake/fake_provisioning_client.go | 2 +- .../v0alpha1/fake/fake_repository.go | 6 +- .../v0alpha1/generated_expansion.go | 0 .../v0alpha1/provisioning_client.go | 4 +- .../typed/provisioning/v0alpha1/repository.go | 6 +- .../informers/externalversions/factory.go | 248 +++ .../informers/externalversions/generic.go | 48 + .../internalinterfaces/factory_interfaces.go | 26 + .../provisioning/interface.go | 4 +- .../provisioning/v0alpha1/interface.go | 2 +- .../provisioning/v0alpha1/repository.go | 8 +- .../v0alpha1/expansion_generated.go | 0 .../provisioning/v0alpha1/repository.go | 2 +- go.work | 1 + hack/update-codegen.sh | 1 + ...enerated.openapi_violation_exceptions.list | 26 - pkg/generated/applyconfiguration/utils.go | 44 +- .../clientset/versioned/clientset.go | 15 +- .../versioned/fake/clientset_generated.go | 7 - .../clientset/versioned/fake/register.go | 2 - .../clientset/versioned/scheme/register.go | 2 - .../informers/externalversions/factory.go | 6 - .../informers/externalversions/generic.go | 11 +- .../provisioning/controller/finalizers.go | 2 +- .../provisioning/controller/repository.go | 10 +- .../apis/provisioning/controller/status.go | 4 +- .../provisioning/controller/status_test.go | 4 +- pkg/registry/apis/provisioning/extra.go | 2 +- pkg/registry/apis/provisioning/files.go | 2 +- pkg/registry/apis/provisioning/history.go | 2 +- pkg/registry/apis/provisioning/jobs.go | 2 +- .../apis/provisioning/jobs/delete/worker.go | 2 +- .../provisioning/jobs/delete/worker_test.go | 2 +- pkg/registry/apis/provisioning/jobs/driver.go | 2 +- .../apis/provisioning/jobs/export/all.go | 2 +- .../apis/provisioning/jobs/export/folders.go | 2 +- .../provisioning/jobs/export/folders_test.go | 2 +- .../jobs/export/mock_export_fn.go | 2 +- .../provisioning/jobs/export/resources.go | 2 +- .../jobs/export/resources_test.go | 2 +- .../apis/provisioning/jobs/export/worker.go | 2 +- .../provisioning/jobs/export/worker_test.go | 2 +- .../apis/provisioning/jobs/history.go | 2 +- .../apis/provisioning/jobs/history_mock.go | 2 +- .../jobs/job_progress_recorder_mock.go | 2 +- .../apis/provisioning/jobs/migrate/legacy.go | 2 +- .../jobs/migrate/legacy_resources.go | 2 +- .../jobs/migrate/legacy_resources_test.go | 2 +- .../provisioning/jobs/migrate/legacy_test.go | 2 +- .../migrate/mock_legacy_resources_migrator.go | 2 +- .../jobs/migrate/mock_migrator.go | 2 +- .../jobs/migrate/unifiedstorage.go | 2 +- .../jobs/migrate/unifiedstorage_test.go | 2 +- .../apis/provisioning/jobs/migrate/worker.go | 2 +- .../provisioning/jobs/migrate/worker_test.go | 2 +- .../apis/provisioning/jobs/move/worker.go | 2 +- .../provisioning/jobs/move/worker_test.go | 2 +- .../apis/provisioning/jobs/persistentstore.go | 2 +- .../apis/provisioning/jobs/progress.go | 2 +- .../provisioning/jobs/progress_fn_mock.go | 2 +- pkg/registry/apis/provisioning/jobs/queue.go | 2 +- .../apis/provisioning/jobs/queue_mock.go | 2 +- .../apis/provisioning/jobs/store_mock.go | 2 +- .../apis/provisioning/jobs/sync/changes.go | 2 +- .../provisioning/jobs/sync/changes_test.go | 2 +- .../apis/provisioning/jobs/sync/full_test.go | 2 +- .../jobs/sync/repository_patch_fn_mock.go | 2 +- .../apis/provisioning/jobs/sync/sync.go | 2 +- .../apis/provisioning/jobs/sync/sync_test.go | 2 +- .../provisioning/jobs/sync/syncer_mock.go | 2 +- .../apis/provisioning/jobs/sync/worker.go | 2 +- .../provisioning/jobs/sync/worker_test.go | 2 +- .../apis/provisioning/jobs/worker_mock.go | 2 +- pkg/registry/apis/provisioning/list.go | 2 +- pkg/registry/apis/provisioning/refs.go | 2 +- pkg/registry/apis/provisioning/register.go | 12 +- .../repository/config_repository_mock.go | 2 +- .../repository/git/git_repository_mock.go | 2 +- .../provisioning/repository/git/mutator.go | 2 +- .../repository/git/mutator_test.go | 2 +- .../provisioning/repository/git/repository.go | 2 +- .../repository/git/repository_test.go | 2 +- .../repository/git/staged_test.go | 2 +- .../github/github_repository_mock.go | 2 +- .../provisioning/repository/github/mutator.go | 2 +- .../repository/github/mutator_test.go | 2 +- .../repository/github/repository.go | 2 +- .../repository/github/repository_test.go | 2 +- .../provisioning/repository/local/local.go | 2 +- .../repository/local/local_test.go | 2 +- .../provisioning/repository/reader_mock.go | 2 +- .../provisioning/repository/repository.go | 2 +- .../repository/repository_mock.go | 2 +- .../repository/staged_repository_mock.go | 2 +- .../apis/provisioning/repository/test.go | 2 +- .../apis/provisioning/repository/test_test.go | 2 +- .../provisioning/repository/versioned_mock.go | 2 +- .../apis/provisioning/repository/workflows.go | 2 +- .../provisioning/repository/workflows_test.go | 2 +- .../apis/provisioning/resources/dualwriter.go | 2 +- .../apis/provisioning/resources/fileformat.go | 2 +- .../provisioning/resources/fileformat_test.go | 2 +- .../apis/provisioning/resources/id.go | 2 +- .../apis/provisioning/resources/object.go | 2 +- .../apis/provisioning/resources/parser.go | 2 +- .../provisioning/resources/parser_test.go | 2 +- .../apis/provisioning/resources/repository.go | 2 +- .../resources/repository_resources_mock.go | 2 +- .../resources/resource_lister_mock.go | 2 +- .../apis/provisioning/resources/tree.go | 2 +- pkg/registry/apis/provisioning/routes.go | 2 +- .../apis/provisioning/secrets/repository.go | 2 +- .../secrets/repository_secrets_mock.go | 2 +- .../provisioning/secrets/repository_test.go | 2 +- pkg/registry/apis/provisioning/test.go | 4 +- pkg/registry/apis/provisioning/types.go | 4 +- pkg/registry/apis/provisioning/usage/usage.go | 2 +- .../apis/provisioning/webhooks/mutator.go | 2 +- .../provisioning/webhooks/mutator_test.go | 2 +- .../webhooks/pullrequest/changes.go | 2 +- .../webhooks/pullrequest/changes_test.go | 2 +- .../webhooks/pullrequest/comment_test.go | 2 +- .../webhooks/pullrequest/mock_evaluator.go | 2 +- .../pullrequest/mock_pullrequest_repo.go | 2 +- .../webhooks/pullrequest/render.go | 2 +- .../webhooks/pullrequest/render_mock.go | 2 +- .../webhooks/pullrequest/render_test.go | 2 +- .../webhooks/pullrequest/worker.go | 2 +- .../webhooks/pullrequest/worker_test.go | 2 +- .../apis/provisioning/webhooks/register.go | 2 +- .../apis/provisioning/webhooks/render.go | 2 +- .../apis/provisioning/webhooks/repository.go | 2 +- .../provisioning/webhooks/repository_test.go | 2 +- .../apis/provisioning/webhooks/webhook.go | 2 +- pkg/services/authn/clients/provisioning.go | 2 +- .../authn/clients/provisioning_test.go | 2 +- pkg/services/live/features/watch.go | 2 +- .../provisioning.grafana.app-v0alpha1.json | 1950 +++++++++++++---- pkg/tests/apis/provisioning/helper_test.go | 2 +- .../apis/provisioning/provisioning_test.go | 2 +- pkg/tests/apis/provisioning/secrets_test.go | 2 +- 192 files changed, 4774 insertions(+), 766 deletions(-) create mode 100644 apps/provisioning/Makefile create mode 100644 apps/provisioning/go.mod create mode 100644 apps/provisioning/go.sum create mode 100644 apps/provisioning/kinds/cue.mod/module.cue create mode 100644 apps/provisioning/kinds/manifest.cue create mode 100644 apps/provisioning/kinds/provisioning/v0alpha1/constants.go create mode 100644 apps/provisioning/kinds/provisioning/v0alpha1/repository_codec_gen.go create mode 100644 apps/provisioning/kinds/provisioning/v0alpha1/repository_metadata_gen.go create mode 100644 apps/provisioning/kinds/provisioning/v0alpha1/repository_object_gen.go create mode 100644 apps/provisioning/kinds/provisioning/v0alpha1/repository_schema_gen.go create mode 100644 apps/provisioning/kinds/provisioning/v0alpha1/repository_spec_gen.go create mode 100644 apps/provisioning/kinds/provisioning/v0alpha1/repository_status_gen.go create mode 100644 apps/provisioning/kinds/provisioning/v0alpha1/zz_openapi_gen.go create mode 100644 apps/provisioning/kinds/provisioning_manifest.go create mode 100644 apps/provisioning/kinds/repository.cue rename {pkg => apps/provisioning/pkg}/apis/provisioning/v0alpha1/classic.go (100%) rename {pkg => apps/provisioning/pkg}/apis/provisioning/v0alpha1/doc.go (54%) rename {pkg => apps/provisioning/pkg}/apis/provisioning/v0alpha1/jobs.go (100%) rename {pkg => apps/provisioning/pkg}/apis/provisioning/v0alpha1/register.go (100%) rename {pkg => apps/provisioning/pkg}/apis/provisioning/v0alpha1/settings.go (100%) rename {pkg => apps/provisioning/pkg}/apis/provisioning/v0alpha1/types.go (100%) rename {pkg => apps/provisioning/pkg}/apis/provisioning/v0alpha1/types_test.go (91%) rename {pkg => apps/provisioning/pkg}/apis/provisioning/v0alpha1/zz_generated.deepcopy.go (100%) rename {pkg => apps/provisioning/pkg}/apis/provisioning/v0alpha1/zz_generated.defaults.go (100%) rename {pkg => apps/provisioning/pkg}/apis/provisioning/v0alpha1/zz_generated.openapi.go (82%) create mode 100644 apps/provisioning/pkg/apis/provisioning/v0alpha1/zz_generated.openapi_violation_exceptions.list create mode 100644 apps/provisioning/pkg/generated/applyconfiguration/internal/internal.go rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/bitbucketrepositoryconfig.go (100%) rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/githubrepositoryconfig.go (100%) rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/gitlabrepositoryconfig.go (100%) rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/gitrepositoryconfig.go (100%) rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/healthstatus.go (100%) rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/localrepositoryconfig.go (100%) rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/repository.go (100%) rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/repositoryspec.go (98%) rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/repositorystatus.go (100%) rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/resourcecount.go (100%) rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/syncoptions.go (95%) rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/syncstatus.go (97%) rename {pkg => apps/provisioning/pkg}/generated/applyconfiguration/provisioning/v0alpha1/webhookstatus.go (100%) create mode 100644 apps/provisioning/pkg/generated/applyconfiguration/utils.go create mode 100644 apps/provisioning/pkg/generated/clientset/versioned/clientset.go create mode 100644 apps/provisioning/pkg/generated/clientset/versioned/fake/clientset_generated.go create mode 100644 apps/provisioning/pkg/generated/clientset/versioned/fake/doc.go create mode 100644 apps/provisioning/pkg/generated/clientset/versioned/fake/register.go create mode 100644 apps/provisioning/pkg/generated/clientset/versioned/scheme/doc.go create mode 100644 apps/provisioning/pkg/generated/clientset/versioned/scheme/register.go rename {pkg => apps/provisioning/pkg}/generated/clientset/versioned/typed/provisioning/v0alpha1/doc.go (100%) rename {pkg => apps/provisioning/pkg}/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/doc.go (100%) rename {pkg => apps/provisioning/pkg}/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_provisioning_client.go (83%) rename {pkg => apps/provisioning/pkg}/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_repository.go (79%) rename {pkg => apps/provisioning/pkg}/generated/clientset/versioned/typed/provisioning/v0alpha1/generated_expansion.go (100%) rename {pkg => apps/provisioning/pkg}/generated/clientset/versioned/typed/provisioning/v0alpha1/provisioning_client.go (92%) rename {pkg => apps/provisioning/pkg}/generated/clientset/versioned/typed/provisioning/v0alpha1/repository.go (91%) create mode 100644 apps/provisioning/pkg/generated/informers/externalversions/factory.go create mode 100644 apps/provisioning/pkg/generated/informers/externalversions/generic.go create mode 100644 apps/provisioning/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go rename {pkg => apps/provisioning/pkg}/generated/informers/externalversions/provisioning/interface.go (78%) rename {pkg => apps/provisioning/pkg}/generated/informers/externalversions/provisioning/v0alpha1/interface.go (88%) rename {pkg => apps/provisioning/pkg}/generated/informers/externalversions/provisioning/v0alpha1/repository.go (88%) rename {pkg => apps/provisioning/pkg}/generated/listers/provisioning/v0alpha1/expansion_generated.go (100%) rename {pkg => apps/provisioning/pkg}/generated/listers/provisioning/v0alpha1/repository.go (95%) delete mode 100644 pkg/apis/provisioning/v0alpha1/zz_generated.openapi_violation_exceptions.list diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f26cfd876aa..749fa4f3058 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -73,7 +73,7 @@ /.air.toml @macabu # Git Sync / App Platform Provisioning -/pkg/apis/provisioning @grafana/grafana-git-ui-sync-team +/apps/provisioning/ @grafana/grafana-git-ui-sync-team /public/app/features/provisioning @grafana/grafana-git-ui-sync-team /pkg/registry/apis/provisioning @grafana/grafana-git-ui-sync-team /pkg/tests/apis/provisioning @grafana/grafana-git-ui-sync-team diff --git a/Dockerfile b/Dockerfile index ddc832d65c9..7300e989823 100644 --- a/Dockerfile +++ b/Dockerfile @@ -83,6 +83,7 @@ COPY pkg/storage/unified/apistore pkg/storage/unified/apistore COPY pkg/semconv pkg/semconv COPY pkg/aggregator pkg/aggregator COPY apps/playlist apps/playlist +COPY apps/provisioning apps/provisioning COPY apps/secret apps/secret COPY apps/investigations apps/investigations COPY apps/advisor apps/advisor diff --git a/apps/provisioning/Makefile b/apps/provisioning/Makefile new file mode 100644 index 00000000000..c3d7e748603 --- /dev/null +++ b/apps/provisioning/Makefile @@ -0,0 +1,26 @@ +include ../sdk.mk + +.PHONY: generate +generate: install-app-sdk update-app-sdk + @$(APP_SDK_BIN) generate -g ./kinds --grouping=group --postprocess --defencoding=none --useoldmanifestkinds + +.PHONY: build +build: generate + go build -o bin/provisioning ./cmd/operator + +# .PHONY: build/operator +# build/operator: build +# docker build -t provisioning:latest -f cmd/operator/Dockerfile . + +.PHONY: clean +clean: + rm -rf bin/ + rm -rf pkg/generated/ + +.PHONY: test +test: generate + go test ./... + +.PHONY: run +run: build + ./bin/provisioning \ No newline at end of file diff --git a/apps/provisioning/go.mod b/apps/provisioning/go.mod new file mode 100644 index 00000000000..ee2ff39fb13 --- /dev/null +++ b/apps/provisioning/go.mod @@ -0,0 +1,78 @@ +module github.com/grafana/grafana/apps/provisioning + +go 1.24.5 + +require ( + github.com/grafana/grafana-app-sdk v0.40.2 + github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956 + k8s.io/apimachinery v0.33.3 + k8s.io/client-go v0.33.3 + k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff + sigs.k8s.io/structured-merge-diff/v4 v4.7.0 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.12.1 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/getkin/kin-openapi v0.132.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-test/deep v1.1.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/gnostic-models v0.6.9 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grafana/grafana-app-sdk/logging v0.40.1 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mailru/easyjson v0.9.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect + github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect + github.com/onsi/ginkgo/v2 v2.22.2 // indirect + github.com/onsi/gomega v1.36.2 // indirect + github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.22.0 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.65.0 // indirect + github.com/prometheus/procfs v0.16.1 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/stretchr/testify v1.10.0 // indirect + github.com/x448/float16 v0.8.4 // indirect + go.opentelemetry.io/otel v1.37.0 // indirect + go.opentelemetry.io/otel/trace v1.37.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect + golang.org/x/net v0.42.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/sys v0.34.0 // indirect + golang.org/x/term v0.33.0 // indirect + golang.org/x/text v0.27.0 // indirect + golang.org/x/time v0.11.0 // indirect + google.golang.org/protobuf v1.36.6 // 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 + k8s.io/api v0.33.3 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect + sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/yaml v1.5.0 // indirect +) + +// transitive dependencies that need replaced +// TODO: stop depending on grafana core +replace github.com/grafana/grafana => ../.. diff --git a/apps/provisioning/go.sum b/apps/provisioning/go.sum new file mode 100644 index 00000000000..3b7ee516782 --- /dev/null +++ b/apps/provisioning/go.sum @@ -0,0 +1,195 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= +github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk= +github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= +github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= +github.com/google/go-cmp v0.5.9/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/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grafana/grafana-app-sdk v0.40.2 h1:j2ftFuqhX+exYUipfEjeWDs3i7oiJkweTF8gFLL7wWU= +github.com/grafana/grafana-app-sdk v0.40.2/go.mod h1:BbNXPNki3mtbkWxYqJsyA1Cj9AShSyaY33z8WkyfVv0= +github.com/grafana/grafana-app-sdk/logging v0.40.1 h1:ru+GqbaQk6jthA5l2Yo1WI/JbNXKNQmLiqNrxz7HGP4= +github.com/grafana/grafana-app-sdk/logging v0.40.1/go.mod h1:otUD9XpJD7A5sCLb8mcs9hIXGdeV6lnhzVwe747g4RU= +github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956 h1:FzReg7qT3G+11ZsFFbtguMdx+w1w76bJCOOH1fWfDKs= +github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956/go.mod h1:RRvSjHH12/PnQaXraMO65jUhVu8n59mzvhfIMBETnV4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +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= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= +github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= +github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= +github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= +github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= +github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= +github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= +go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= +golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +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= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8= +k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE= +k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA= +k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA= +k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= +k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= +k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI= +sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= +sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= diff --git a/apps/provisioning/kinds/cue.mod/module.cue b/apps/provisioning/kinds/cue.mod/module.cue new file mode 100644 index 00000000000..20a2c78795d --- /dev/null +++ b/apps/provisioning/kinds/cue.mod/module.cue @@ -0,0 +1,4 @@ +module: "github.com/grafana/grafana/apps/provisioning" +language: { + version: "v0.9.0" +} \ No newline at end of file diff --git a/apps/provisioning/kinds/manifest.cue b/apps/provisioning/kinds/manifest.cue new file mode 100644 index 00000000000..40ffa64d922 --- /dev/null +++ b/apps/provisioning/kinds/manifest.cue @@ -0,0 +1,9 @@ +package repository + +manifest: { + appName: "provisioning" + groupOverride: "provisioning.grafana.app" + kinds: [ + repository, + ] +} \ No newline at end of file diff --git a/apps/provisioning/kinds/provisioning/v0alpha1/constants.go b/apps/provisioning/kinds/provisioning/v0alpha1/constants.go new file mode 100644 index 00000000000..c326607a228 --- /dev/null +++ b/apps/provisioning/kinds/provisioning/v0alpha1/constants.go @@ -0,0 +1,18 @@ +package v0alpha1 + +import "k8s.io/apimachinery/pkg/runtime/schema" + +const ( + // APIGroup is the API group used by all kinds in this package + APIGroup = "provisioning.grafana.app" + // APIVersion is the API version used by all kinds in this package + APIVersion = "v0alpha1" +) + +var ( + // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package + GroupVersion = schema.GroupVersion{ + Group: APIGroup, + Version: APIVersion, + } +) diff --git a/apps/provisioning/kinds/provisioning/v0alpha1/repository_codec_gen.go b/apps/provisioning/kinds/provisioning/v0alpha1/repository_codec_gen.go new file mode 100644 index 00000000000..6202f5c6172 --- /dev/null +++ b/apps/provisioning/kinds/provisioning/v0alpha1/repository_codec_gen.go @@ -0,0 +1,28 @@ +// +// Code generated by grafana-app-sdk. DO NOT EDIT. +// + +package v0alpha1 + +import ( + "encoding/json" + "io" + + "github.com/grafana/grafana-app-sdk/resource" +) + +// RepositoryJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding +type RepositoryJSONCodec struct{} + +// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into` +func (*RepositoryJSONCodec) Read(reader io.Reader, into resource.Object) error { + return json.NewDecoder(reader).Decode(into) +} + +// Write writes JSON-encoded bytes into `writer` marshaled from `from` +func (*RepositoryJSONCodec) Write(writer io.Writer, from resource.Object) error { + return json.NewEncoder(writer).Encode(from) +} + +// Interface compliance checks +var _ resource.Codec = &RepositoryJSONCodec{} diff --git a/apps/provisioning/kinds/provisioning/v0alpha1/repository_metadata_gen.go b/apps/provisioning/kinds/provisioning/v0alpha1/repository_metadata_gen.go new file mode 100644 index 00000000000..162a34fd13c --- /dev/null +++ b/apps/provisioning/kinds/provisioning/v0alpha1/repository_metadata_gen.go @@ -0,0 +1,31 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v0alpha1 + +import ( + time "time" +) + +// metadata contains embedded CommonMetadata and can be extended with custom string fields +// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here +// without external reference as using the CommonMetadata reference breaks thema codegen. +type RepositoryMetadata struct { + UpdateTimestamp time.Time `json:"updateTimestamp"` + CreatedBy string `json:"createdBy"` + Uid string `json:"uid"` + CreationTimestamp time.Time `json:"creationTimestamp"` + DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"` + Finalizers []string `json:"finalizers"` + ResourceVersion string `json:"resourceVersion"` + Generation int64 `json:"generation"` + UpdatedBy string `json:"updatedBy"` + Labels map[string]string `json:"labels"` +} + +// NewRepositoryMetadata creates a new RepositoryMetadata object. +func NewRepositoryMetadata() *RepositoryMetadata { + return &RepositoryMetadata{ + Finalizers: []string{}, + Labels: map[string]string{}, + } +} diff --git a/apps/provisioning/kinds/provisioning/v0alpha1/repository_object_gen.go b/apps/provisioning/kinds/provisioning/v0alpha1/repository_object_gen.go new file mode 100644 index 00000000000..4154ffefb36 --- /dev/null +++ b/apps/provisioning/kinds/provisioning/v0alpha1/repository_object_gen.go @@ -0,0 +1,319 @@ +// +// Code generated by grafana-app-sdk. DO NOT EDIT. +// + +package v0alpha1 + +import ( + "fmt" + "github.com/grafana/grafana-app-sdk/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "time" +) + +// +k8s:openapi-gen=true +type Repository struct { + metav1.TypeMeta `json:",inline" yaml:",inline"` + metav1.ObjectMeta `json:"metadata" yaml:"metadata"` + + // Spec is the spec of the Repository + Spec RepositorySpec `json:"spec" yaml:"spec"` + + Status RepositoryStatus `json:"status" yaml:"status"` +} + +func (o *Repository) GetSpec() any { + return o.Spec +} + +func (o *Repository) SetSpec(spec any) error { + cast, ok := spec.(RepositorySpec) + if !ok { + return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec) + } + o.Spec = cast + return nil +} + +func (o *Repository) GetSubresources() map[string]any { + return map[string]any{ + "status": o.Status, + } +} + +func (o *Repository) GetSubresource(name string) (any, bool) { + switch name { + case "status": + return o.Status, true + default: + return nil, false + } +} + +func (o *Repository) SetSubresource(name string, value any) error { + switch name { + case "status": + cast, ok := value.(RepositoryStatus) + if !ok { + return fmt.Errorf("cannot set status type %#v, not of type RepositoryStatus", value) + } + o.Status = cast + return nil + default: + return fmt.Errorf("subresource '%s' does not exist", name) + } +} + +func (o *Repository) GetStaticMetadata() resource.StaticMetadata { + gvk := o.GroupVersionKind() + return resource.StaticMetadata{ + Name: o.ObjectMeta.Name, + Namespace: o.ObjectMeta.Namespace, + Group: gvk.Group, + Version: gvk.Version, + Kind: gvk.Kind, + } +} + +func (o *Repository) SetStaticMetadata(metadata resource.StaticMetadata) { + o.Name = metadata.Name + o.Namespace = metadata.Namespace + o.SetGroupVersionKind(schema.GroupVersionKind{ + Group: metadata.Group, + Version: metadata.Version, + Kind: metadata.Kind, + }) +} + +func (o *Repository) GetCommonMetadata() resource.CommonMetadata { + dt := o.DeletionTimestamp + var deletionTimestamp *time.Time + if dt != nil { + deletionTimestamp = &dt.Time + } + // Legacy ExtraFields support + extraFields := make(map[string]any) + if o.Annotations != nil { + extraFields["annotations"] = o.Annotations + } + if o.ManagedFields != nil { + extraFields["managedFields"] = o.ManagedFields + } + if o.OwnerReferences != nil { + extraFields["ownerReferences"] = o.OwnerReferences + } + return resource.CommonMetadata{ + UID: string(o.UID), + ResourceVersion: o.ResourceVersion, + Generation: o.Generation, + Labels: o.Labels, + CreationTimestamp: o.CreationTimestamp.Time, + DeletionTimestamp: deletionTimestamp, + Finalizers: o.Finalizers, + UpdateTimestamp: o.GetUpdateTimestamp(), + CreatedBy: o.GetCreatedBy(), + UpdatedBy: o.GetUpdatedBy(), + ExtraFields: extraFields, + } +} + +func (o *Repository) SetCommonMetadata(metadata resource.CommonMetadata) { + o.UID = types.UID(metadata.UID) + o.ResourceVersion = metadata.ResourceVersion + o.Generation = metadata.Generation + o.Labels = metadata.Labels + o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp) + if metadata.DeletionTimestamp != nil { + dt := metav1.NewTime(*metadata.DeletionTimestamp) + o.DeletionTimestamp = &dt + } else { + o.DeletionTimestamp = nil + } + o.Finalizers = metadata.Finalizers + if o.Annotations == nil { + o.Annotations = make(map[string]string) + } + if !metadata.UpdateTimestamp.IsZero() { + o.SetUpdateTimestamp(metadata.UpdateTimestamp) + } + if metadata.CreatedBy != "" { + o.SetCreatedBy(metadata.CreatedBy) + } + if metadata.UpdatedBy != "" { + o.SetUpdatedBy(metadata.UpdatedBy) + } + // Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields + if metadata.ExtraFields != nil { + if annotations, ok := metadata.ExtraFields["annotations"]; ok { + if cast, ok := annotations.(map[string]string); ok { + o.Annotations = cast + } + } + if managedFields, ok := metadata.ExtraFields["managedFields"]; ok { + if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok { + o.ManagedFields = cast + } + } + if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok { + if cast, ok := ownerReferences.([]metav1.OwnerReference); ok { + o.OwnerReferences = cast + } + } + } +} + +func (o *Repository) GetCreatedBy() string { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + return o.ObjectMeta.Annotations["grafana.com/createdBy"] +} + +func (o *Repository) SetCreatedBy(createdBy string) { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy +} + +func (o *Repository) GetUpdateTimestamp() time.Time { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"]) + return parsed +} + +func (o *Repository) SetUpdateTimestamp(updateTimestamp time.Time) { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339) +} + +func (o *Repository) GetUpdatedBy() string { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + return o.ObjectMeta.Annotations["grafana.com/updatedBy"] +} + +func (o *Repository) SetUpdatedBy(updatedBy string) { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy +} + +func (o *Repository) Copy() resource.Object { + return resource.CopyObject(o) +} + +func (o *Repository) DeepCopyObject() runtime.Object { + return o.Copy() +} + +func (o *Repository) DeepCopy() *Repository { + cpy := &Repository{} + o.DeepCopyInto(cpy) + return cpy +} + +func (o *Repository) DeepCopyInto(dst *Repository) { + dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion + dst.TypeMeta.Kind = o.TypeMeta.Kind + o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta) + o.Spec.DeepCopyInto(&dst.Spec) + o.Status.DeepCopyInto(&dst.Status) +} + +// Interface compliance compile-time check +var _ resource.Object = &Repository{} + +// +k8s:openapi-gen=true +type RepositoryList struct { + metav1.TypeMeta `json:",inline" yaml:",inline"` + metav1.ListMeta `json:"metadata" yaml:"metadata"` + Items []Repository `json:"items" yaml:"items"` +} + +func (o *RepositoryList) DeepCopyObject() runtime.Object { + return o.Copy() +} + +func (o *RepositoryList) Copy() resource.ListObject { + cpy := &RepositoryList{ + TypeMeta: o.TypeMeta, + Items: make([]Repository, len(o.Items)), + } + o.ListMeta.DeepCopyInto(&cpy.ListMeta) + for i := 0; i < len(o.Items); i++ { + if item, ok := o.Items[i].Copy().(*Repository); ok { + cpy.Items[i] = *item + } + } + return cpy +} + +func (o *RepositoryList) GetItems() []resource.Object { + items := make([]resource.Object, len(o.Items)) + for i := 0; i < len(o.Items); i++ { + items[i] = &o.Items[i] + } + return items +} + +func (o *RepositoryList) SetItems(items []resource.Object) { + o.Items = make([]Repository, len(items)) + for i := 0; i < len(items); i++ { + o.Items[i] = *items[i].(*Repository) + } +} + +func (o *RepositoryList) DeepCopy() *RepositoryList { + cpy := &RepositoryList{} + o.DeepCopyInto(cpy) + return cpy +} + +func (o *RepositoryList) DeepCopyInto(dst *RepositoryList) { + resource.CopyObjectInto(dst, o) +} + +// Interface compliance compile-time check +var _ resource.ListObject = &RepositoryList{} + +// Copy methods for all subresource types + +// DeepCopy creates a full deep copy of Spec +func (s *RepositorySpec) DeepCopy() *RepositorySpec { + cpy := &RepositorySpec{} + s.DeepCopyInto(cpy) + return cpy +} + +// DeepCopyInto deep copies Spec into another Spec object +func (s *RepositorySpec) DeepCopyInto(dst *RepositorySpec) { + resource.CopyObjectInto(dst, s) +} + +// DeepCopy creates a full deep copy of RepositoryStatus +func (s *RepositoryStatus) DeepCopy() *RepositoryStatus { + cpy := &RepositoryStatus{} + s.DeepCopyInto(cpy) + return cpy +} + +// DeepCopyInto deep copies RepositoryStatus into another RepositoryStatus object +func (s *RepositoryStatus) DeepCopyInto(dst *RepositoryStatus) { + resource.CopyObjectInto(dst, s) +} diff --git a/apps/provisioning/kinds/provisioning/v0alpha1/repository_schema_gen.go b/apps/provisioning/kinds/provisioning/v0alpha1/repository_schema_gen.go new file mode 100644 index 00000000000..e8f3a525d75 --- /dev/null +++ b/apps/provisioning/kinds/provisioning/v0alpha1/repository_schema_gen.go @@ -0,0 +1,34 @@ +// +// Code generated by grafana-app-sdk. DO NOT EDIT. +// + +package v0alpha1 + +import ( + "github.com/grafana/grafana-app-sdk/resource" +) + +// schema is unexported to prevent accidental overwrites +var ( + schemaRepository = resource.NewSimpleSchema("provisioning.grafana.app", "v0alpha1", &Repository{}, &RepositoryList{}, resource.WithKind("Repository"), + resource.WithPlural("repositories"), resource.WithScope(resource.NamespacedScope)) + kindRepository = resource.Kind{ + Schema: schemaRepository, + Codecs: map[resource.KindEncoding]resource.Codec{ + resource.KindEncodingJSON: &RepositoryJSONCodec{}, + }, + } +) + +// Kind returns a resource.Kind for this Schema with a JSON codec +func RepositoryKind() resource.Kind { + return kindRepository +} + +// Schema returns a resource.SimpleSchema representation of Repository +func RepositorySchema() *resource.SimpleSchema { + return schemaRepository +} + +// Interface compliance checks +var _ resource.Schema = kindRepository diff --git a/apps/provisioning/kinds/provisioning/v0alpha1/repository_spec_gen.go b/apps/provisioning/kinds/provisioning/v0alpha1/repository_spec_gen.go new file mode 100644 index 00000000000..54eb7ba4eda --- /dev/null +++ b/apps/provisioning/kinds/provisioning/v0alpha1/repository_spec_gen.go @@ -0,0 +1,169 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v0alpha1 + +// +k8s:openapi-gen=true +type RepositorySyncOptions struct { + // Enabled must be saved as true before any sync job will run + Enabled bool `json:"enabled"` + // Where values should be saved + Target RepositorySyncOptionsTarget `json:"target"` + // When non-zero, the sync will run periodically + IntervalSeconds *int64 `json:"intervalSeconds,omitempty"` +} + +// NewRepositorySyncOptions creates a new RepositorySyncOptions object. +func NewRepositorySyncOptions() *RepositorySyncOptions { + return &RepositorySyncOptions{} +} + +// +k8s:openapi-gen=true +type RepositoryLocalRepositoryConfig struct { + // Path to the local repository + Path string `json:"path"` +} + +// NewRepositoryLocalRepositoryConfig creates a new RepositoryLocalRepositoryConfig object. +func NewRepositoryLocalRepositoryConfig() *RepositoryLocalRepositoryConfig { + return &RepositoryLocalRepositoryConfig{} +} + +// +k8s:openapi-gen=true +type RepositoryGitHubRepositoryConfig struct { + // The repository URL (e.g. `https://github.com/example/test`). + Url *string `json:"url,omitempty"` + // The branch to use in the repository. + Branch string `json:"branch"` + // Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again. + Token *string `json:"token,omitempty"` + // Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted. + EncryptedToken []string `json:"encryptedToken,omitempty"` + // Whether we should show dashboard previews for pull requests. + // By default, this is false (i.e. we will not create previews). + GenerateDashboardPreviews *bool `json:"generateDashboardPreviews,omitempty"` + // Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. + Path *string `json:"path,omitempty"` +} + +// NewRepositoryGitHubRepositoryConfig creates a new RepositoryGitHubRepositoryConfig object. +func NewRepositoryGitHubRepositoryConfig() *RepositoryGitHubRepositoryConfig { + return &RepositoryGitHubRepositoryConfig{} +} + +// +k8s:openapi-gen=true +type RepositoryGitRepositoryConfig struct { + // The repository URL (e.g. `https://github.com/example/test.git`). + Url *string `json:"url,omitempty"` + // The branch to use in the repository. + Branch string `json:"branch"` + // TokenUser is the user that will be used to access the repository if it's a personal access token. + TokenUser *string `json:"tokenUser,omitempty"` + // Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again. + Token *string `json:"token,omitempty"` + // Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted. + EncryptedToken []string `json:"encryptedToken,omitempty"` + // Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. + Path *string `json:"path,omitempty"` +} + +// NewRepositoryGitRepositoryConfig creates a new RepositoryGitRepositoryConfig object. +func NewRepositoryGitRepositoryConfig() *RepositoryGitRepositoryConfig { + return &RepositoryGitRepositoryConfig{} +} + +// +k8s:openapi-gen=true +type RepositoryBitbucketRepositoryConfig struct { + // The repository URL (e.g. `https://bitbucket.org/example/test`). + Url *string `json:"url,omitempty"` + // The branch to use in the repository. + Branch string `json:"branch"` + // TokenUser is the user that will be used to access the repository if it's a personal access token. + TokenUser *string `json:"tokenUser,omitempty"` + // Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again. + Token *string `json:"token,omitempty"` + // Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted. + EncryptedToken []string `json:"encryptedToken,omitempty"` + // Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. + Path *string `json:"path,omitempty"` +} + +// NewRepositoryBitbucketRepositoryConfig creates a new RepositoryBitbucketRepositoryConfig object. +func NewRepositoryBitbucketRepositoryConfig() *RepositoryBitbucketRepositoryConfig { + return &RepositoryBitbucketRepositoryConfig{} +} + +// +k8s:openapi-gen=true +type RepositoryGitLabRepositoryConfig struct { + // The repository URL (e.g. `https://gitlab.com/example/test`). + Url *string `json:"url,omitempty"` + // The branch to use in the repository. + Branch string `json:"branch"` + // Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again. + Token *string `json:"token,omitempty"` + // Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted. + EncryptedToken []string `json:"encryptedToken,omitempty"` + // Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. + Path *string `json:"path,omitempty"` +} + +// NewRepositoryGitLabRepositoryConfig creates a new RepositoryGitLabRepositoryConfig object. +func NewRepositoryGitLabRepositoryConfig() *RepositoryGitLabRepositoryConfig { + return &RepositoryGitLabRepositoryConfig{} +} + +// +k8s:openapi-gen=true +type RepositorySpec struct { + // The repository display name (shown in the UI) + Title string `json:"title"` + // Repository description + Description *string `json:"description,omitempty"` + // UI driven Workflow that allow changes to the contends of the repository. + // The order is relevant for defining the precedence of the workflows. + // When empty, the repository does not support any edits (eg, readonly) + Workflows []string `json:"workflows,omitempty"` + // Sync settings -- how values are pulled from the repository into grafana + Sync RepositorySyncOptions `json:"sync"` + // The repository type. When selected oneOf the values below should be non-nil + Type RepositorySpecType `json:"type"` + // The repository on the local file system. + // Mutually exclusive with local | github. + Local *RepositoryLocalRepositoryConfig `json:"local,omitempty"` + // The repository on GitHub. + // Mutually exclusive with local | github | git. + Github *RepositoryGitHubRepositoryConfig `json:"github,omitempty"` + // The repository on Git. + // Mutually exclusive with local | github | git. + Git *RepositoryGitRepositoryConfig `json:"git,omitempty"` + // The repository on Bitbucket. + // Mutually exclusive with local | github | git. + Bitbucket *RepositoryBitbucketRepositoryConfig `json:"bitbucket,omitempty"` + // The repository on GitLab. + // Mutually exclusive with local | github | git. + Gitlab *RepositoryGitLabRepositoryConfig `json:"gitlab,omitempty"` +} + +// NewRepositorySpec creates a new RepositorySpec object. +func NewRepositorySpec() *RepositorySpec { + return &RepositorySpec{ + Sync: *NewRepositorySyncOptions(), + } +} + +// +k8s:openapi-gen=true +type RepositorySyncOptionsTarget string + +const ( + RepositorySyncOptionsTargetUnified RepositorySyncOptionsTarget = "unified" + RepositorySyncOptionsTargetLegacy RepositorySyncOptionsTarget = "legacy" +) + +// +k8s:openapi-gen=true +type RepositorySpecType string + +const ( + RepositorySpecTypeLocal RepositorySpecType = "local" + RepositorySpecTypeGithub RepositorySpecType = "github" + RepositorySpecTypeGit RepositorySpecType = "git" + RepositorySpecTypeBitbucket RepositorySpecType = "bitbucket" + RepositorySpecTypeGitlab RepositorySpecType = "gitlab" +) diff --git a/apps/provisioning/kinds/provisioning/v0alpha1/repository_status_gen.go b/apps/provisioning/kinds/provisioning/v0alpha1/repository_status_gen.go new file mode 100644 index 00000000000..c2512cc2851 --- /dev/null +++ b/apps/provisioning/kinds/provisioning/v0alpha1/repository_status_gen.go @@ -0,0 +1,137 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v0alpha1 + +// +k8s:openapi-gen=true +type RepositoryHealthStatus struct { + // When not healthy, requests will not be executed + Healthy bool `json:"healthy"` + // When the health was checked last time + Checked *int64 `json:"checked,omitempty"` + // Summary messages (can be shown to users) + // Will only be populated when not healthy + Message []string `json:"message,omitempty"` +} + +// NewRepositoryHealthStatus creates a new RepositoryHealthStatus object. +func NewRepositoryHealthStatus() *RepositoryHealthStatus { + return &RepositoryHealthStatus{} +} + +// +k8s:openapi-gen=true +type RepositorySyncStatus struct { + // pending, running, success, error + State RepositorySyncStatusState `json:"state"` + // The ID for the job that ran this sync + Job *string `json:"job,omitempty"` + // When the sync job started + Started *int64 `json:"started,omitempty"` + // When the sync job finished + Finished *int64 `json:"finished,omitempty"` + // When the next sync check is scheduled + Scheduled *int64 `json:"scheduled,omitempty"` + // Summary messages (will be shown to users) + Message []string `json:"message"` + // The repository ref when the last successful sync ran + LastRef *string `json:"lastRef,omitempty"` + // Incremental synchronization for versioned repositories + Incremental *bool `json:"incremental,omitempty"` +} + +// NewRepositorySyncStatus creates a new RepositorySyncStatus object. +func NewRepositorySyncStatus() *RepositorySyncStatus { + return &RepositorySyncStatus{ + Message: []string{}, + } +} + +// +k8s:openapi-gen=true +type RepositoryResourceCount struct { + Group string `json:"group"` + Resource string `json:"resource"` + Count int64 `json:"count"` +} + +// NewRepositoryResourceCount creates a new RepositoryResourceCount object. +func NewRepositoryResourceCount() *RepositoryResourceCount { + return &RepositoryResourceCount{} +} + +// +k8s:openapi-gen=true +type RepositorystatusOperatorState struct { + // lastEvaluation is the ResourceVersion last evaluated + LastEvaluation string `json:"lastEvaluation"` + // state describes the state of the lastEvaluation. + // It is limited to three possible states for machine evaluation. + State RepositoryStatusOperatorStateState `json:"state"` + // descriptiveState is an optional more descriptive state field which has no requirements on format + DescriptiveState *string `json:"descriptiveState,omitempty"` + // details contains any extra information that is operator-specific + Details map[string]interface{} `json:"details,omitempty"` +} + +// NewRepositorystatusOperatorState creates a new RepositorystatusOperatorState object. +func NewRepositorystatusOperatorState() *RepositorystatusOperatorState { + return &RepositorystatusOperatorState{} +} + +// +k8s:openapi-gen=true +type RepositoryWebhookStatus struct { + Id *int64 `json:"id,omitempty"` + Url *string `json:"url,omitempty"` + Secret *string `json:"secret,omitempty"` + EncryptedSecret []string `json:"encryptedSecret,omitempty"` + SubscribedEvents []string `json:"subscribedEvents,omitempty"` + LastEvent *int64 `json:"lastEvent,omitempty"` +} + +// NewRepositoryWebhookStatus creates a new RepositoryWebhookStatus object. +func NewRepositoryWebhookStatus() *RepositoryWebhookStatus { + return &RepositoryWebhookStatus{} +} + +// +k8s:openapi-gen=true +type RepositoryStatus struct { + // The generation of the spec last time reconciliation ran + ObservedGeneration *int64 `json:"observedGeneration,omitempty"` + // This will get updated with the current health status (and updated periodically) + Health RepositoryHealthStatus `json:"health"` + // Sync information with the last sync information + Sync RepositorySyncStatus `json:"sync"` + // The object count when sync last ran + Stats []RepositoryResourceCount `json:"stats,omitempty"` + // operatorStates is a map of operator ID to operator state evaluations. + // Any operator which consumes this kind SHOULD add its state evaluation information to this field. + OperatorStates map[string]RepositorystatusOperatorState `json:"operatorStates,omitempty"` + // Webhook Information (if applicable) + Webhook *RepositoryWebhookStatus `json:"webhook,omitempty"` + // additionalFields is reserved for future use + AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"` +} + +// NewRepositoryStatus creates a new RepositoryStatus object. +func NewRepositoryStatus() *RepositoryStatus { + return &RepositoryStatus{ + Health: *NewRepositoryHealthStatus(), + Sync: *NewRepositorySyncStatus(), + } +} + +// +k8s:openapi-gen=true +type RepositorySyncStatusState string + +const ( + RepositorySyncStatusStatePending RepositorySyncStatusState = "pending" + RepositorySyncStatusStateRunning RepositorySyncStatusState = "running" + RepositorySyncStatusStateSuccess RepositorySyncStatusState = "success" + RepositorySyncStatusStateError RepositorySyncStatusState = "error" +) + +// +k8s:openapi-gen=true +type RepositoryStatusOperatorStateState string + +const ( + RepositoryStatusOperatorStateStateSuccess RepositoryStatusOperatorStateState = "success" + RepositoryStatusOperatorStateStateInProgress RepositoryStatusOperatorStateState = "in_progress" + RepositoryStatusOperatorStateStateFailed RepositoryStatusOperatorStateState = "failed" +) diff --git a/apps/provisioning/kinds/provisioning/v0alpha1/zz_openapi_gen.go b/apps/provisioning/kinds/provisioning/v0alpha1/zz_openapi_gen.go new file mode 100644 index 00000000000..583d9f07f60 --- /dev/null +++ b/apps/provisioning/kinds/provisioning/v0alpha1/zz_openapi_gen.go @@ -0,0 +1,879 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by grafana-app-sdk. DO NOT EDIT. + +package v0alpha1 + +import ( + common "k8s.io/kube-openapi/pkg/common" + spec "k8s.io/kube-openapi/pkg/validation/spec" +) + +func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { + return map[string]common.OpenAPIDefinition{ + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.Repository": schema_provisioning_kinds_provisioning_v0alpha1_Repository(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryBitbucketRepositoryConfig": schema_provisioning_kinds_provisioning_v0alpha1_RepositoryBitbucketRepositoryConfig(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryGitHubRepositoryConfig": schema_provisioning_kinds_provisioning_v0alpha1_RepositoryGitHubRepositoryConfig(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryGitLabRepositoryConfig": schema_provisioning_kinds_provisioning_v0alpha1_RepositoryGitLabRepositoryConfig(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryGitRepositoryConfig": schema_provisioning_kinds_provisioning_v0alpha1_RepositoryGitRepositoryConfig(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryHealthStatus": schema_provisioning_kinds_provisioning_v0alpha1_RepositoryHealthStatus(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryList": schema_provisioning_kinds_provisioning_v0alpha1_RepositoryList(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryLocalRepositoryConfig": schema_provisioning_kinds_provisioning_v0alpha1_RepositoryLocalRepositoryConfig(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryResourceCount": schema_provisioning_kinds_provisioning_v0alpha1_RepositoryResourceCount(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositorySpec": schema_provisioning_kinds_provisioning_v0alpha1_RepositorySpec(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryStatus": schema_provisioning_kinds_provisioning_v0alpha1_RepositoryStatus(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositorySyncOptions": schema_provisioning_kinds_provisioning_v0alpha1_RepositorySyncOptions(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositorySyncStatus": schema_provisioning_kinds_provisioning_v0alpha1_RepositorySyncStatus(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryWebhookStatus": schema_provisioning_kinds_provisioning_v0alpha1_RepositoryWebhookStatus(ref), + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositorystatusOperatorState": schema_provisioning_kinds_provisioning_v0alpha1_RepositorystatusOperatorState(ref), + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_Repository(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "Spec is the spec of the Repository", + Default: map[string]interface{}{}, + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositorySpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryStatus"), + }, + }, + }, + Required: []string{"metadata", "spec", "status"}, + }, + }, + Dependencies: []string{ + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositorySpec", "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositoryBitbucketRepositoryConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "url": { + SchemaProps: spec.SchemaProps{ + Description: "The repository URL (e.g. `https://bitbucket.org/example/test`).", + Type: []string{"string"}, + Format: "", + }, + }, + "branch": { + SchemaProps: spec.SchemaProps{ + Description: "The branch to use in the repository.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "tokenUser": { + SchemaProps: spec.SchemaProps{ + Description: "TokenUser is the user that will be used to access the repository if it's a personal access token.", + Type: []string{"string"}, + Format: "", + }, + }, + "token": { + SchemaProps: spec.SchemaProps{ + Description: "Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again.", + Type: []string{"string"}, + Format: "", + }, + }, + "encryptedToken": { + SchemaProps: spec.SchemaProps{ + Description: "Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "path": { + SchemaProps: spec.SchemaProps{ + Description: "Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"branch"}, + }, + }, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositoryGitHubRepositoryConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "url": { + SchemaProps: spec.SchemaProps{ + Description: "The repository URL (e.g. `https://github.com/example/test`).", + Type: []string{"string"}, + Format: "", + }, + }, + "branch": { + SchemaProps: spec.SchemaProps{ + Description: "The branch to use in the repository.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "token": { + SchemaProps: spec.SchemaProps{ + Description: "Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again.", + Type: []string{"string"}, + Format: "", + }, + }, + "encryptedToken": { + SchemaProps: spec.SchemaProps{ + Description: "Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "generateDashboardPreviews": { + SchemaProps: spec.SchemaProps{ + Description: "Whether we should show dashboard previews for pull requests. By default, this is false (i.e. we will not create previews).", + Type: []string{"boolean"}, + Format: "", + }, + }, + "path": { + SchemaProps: spec.SchemaProps{ + Description: "Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"branch"}, + }, + }, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositoryGitLabRepositoryConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "url": { + SchemaProps: spec.SchemaProps{ + Description: "The repository URL (e.g. `https://gitlab.com/example/test`).", + Type: []string{"string"}, + Format: "", + }, + }, + "branch": { + SchemaProps: spec.SchemaProps{ + Description: "The branch to use in the repository.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "token": { + SchemaProps: spec.SchemaProps{ + Description: "Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again.", + Type: []string{"string"}, + Format: "", + }, + }, + "encryptedToken": { + SchemaProps: spec.SchemaProps{ + Description: "Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "path": { + SchemaProps: spec.SchemaProps{ + Description: "Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"branch"}, + }, + }, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositoryGitRepositoryConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "url": { + SchemaProps: spec.SchemaProps{ + Description: "The repository URL (e.g. `https://github.com/example/test.git`).", + Type: []string{"string"}, + Format: "", + }, + }, + "branch": { + SchemaProps: spec.SchemaProps{ + Description: "The branch to use in the repository.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "tokenUser": { + SchemaProps: spec.SchemaProps{ + Description: "TokenUser is the user that will be used to access the repository if it's a personal access token.", + Type: []string{"string"}, + Format: "", + }, + }, + "token": { + SchemaProps: spec.SchemaProps{ + Description: "Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again.", + Type: []string{"string"}, + Format: "", + }, + }, + "encryptedToken": { + SchemaProps: spec.SchemaProps{ + Description: "Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "path": { + SchemaProps: spec.SchemaProps{ + Description: "Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"branch"}, + }, + }, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositoryHealthStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "healthy": { + SchemaProps: spec.SchemaProps{ + Description: "When not healthy, requests will not be executed", + Default: false, + Type: []string{"boolean"}, + Format: "", + }, + }, + "checked": { + SchemaProps: spec.SchemaProps{ + Description: "When the health was checked last time", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "message": { + SchemaProps: spec.SchemaProps{ + Description: "Summary messages (can be shown to users) Will only be populated when not healthy", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + Required: []string{"healthy"}, + }, + }, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositoryList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.Repository"), + }, + }, + }, + }, + }, + }, + Required: []string{"metadata", "items"}, + }, + }, + Dependencies: []string{ + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.Repository", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositoryLocalRepositoryConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "path": { + SchemaProps: spec.SchemaProps{ + Description: "Path to the local repository", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"path"}, + }, + }, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositoryResourceCount(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "group": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "resource": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "count": { + SchemaProps: spec.SchemaProps{ + Default: 0, + Type: []string{"integer"}, + Format: "int64", + }, + }, + }, + Required: []string{"group", "resource", "count"}, + }, + }, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositorySpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "title": { + SchemaProps: spec.SchemaProps{ + Description: "The repository display name (shown in the UI)", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "description": { + SchemaProps: spec.SchemaProps{ + Description: "Repository description", + Type: []string{"string"}, + Format: "", + }, + }, + "workflows": { + SchemaProps: spec.SchemaProps{ + Description: "UI driven Workflow that allow changes to the contends of the repository. The order is relevant for defining the precedence of the workflows. When empty, the repository does not support any edits (eg, readonly)", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "sync": { + SchemaProps: spec.SchemaProps{ + Description: "Sync settings -- how values are pulled from the repository into grafana", + Default: map[string]interface{}{}, + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositorySyncOptions"), + }, + }, + "type": { + SchemaProps: spec.SchemaProps{ + Description: "The repository type. When selected oneOf the values below should be non-nil", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "local": { + SchemaProps: spec.SchemaProps{ + Description: "The repository on the local file system. Mutually exclusive with local | github.", + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryLocalRepositoryConfig"), + }, + }, + "github": { + SchemaProps: spec.SchemaProps{ + Description: "The repository on GitHub. Mutually exclusive with local | github | git.", + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryGitHubRepositoryConfig"), + }, + }, + "git": { + SchemaProps: spec.SchemaProps{ + Description: "The repository on Git. Mutually exclusive with local | github | git.", + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryGitRepositoryConfig"), + }, + }, + "bitbucket": { + SchemaProps: spec.SchemaProps{ + Description: "The repository on Bitbucket. Mutually exclusive with local | github | git.", + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryBitbucketRepositoryConfig"), + }, + }, + "gitlab": { + SchemaProps: spec.SchemaProps{ + Description: "The repository on GitLab. Mutually exclusive with local | github | git.", + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryGitLabRepositoryConfig"), + }, + }, + }, + Required: []string{"title", "sync", "type"}, + }, + }, + Dependencies: []string{ + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryBitbucketRepositoryConfig", "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryGitHubRepositoryConfig", "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryGitLabRepositoryConfig", "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryGitRepositoryConfig", "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryLocalRepositoryConfig", "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositorySyncOptions"}, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositoryStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "observedGeneration": { + SchemaProps: spec.SchemaProps{ + Description: "The generation of the spec last time reconciliation ran", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "health": { + SchemaProps: spec.SchemaProps{ + Description: "This will get updated with the current health status (and updated periodically)", + Default: map[string]interface{}{}, + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryHealthStatus"), + }, + }, + "sync": { + SchemaProps: spec.SchemaProps{ + Description: "Sync information with the last sync information", + Default: map[string]interface{}{}, + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositorySyncStatus"), + }, + }, + "stats": { + SchemaProps: spec.SchemaProps{ + Description: "The object count when sync last ran", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryResourceCount"), + }, + }, + }, + }, + }, + "operatorStates": { + SchemaProps: spec.SchemaProps{ + Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositorystatusOperatorState"), + }, + }, + }, + }, + }, + "webhook": { + SchemaProps: spec.SchemaProps{ + Description: "Webhook Information (if applicable)", + Ref: ref("github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryWebhookStatus"), + }, + }, + "additionalFields": { + SchemaProps: spec.SchemaProps{ + Description: "additionalFields is reserved for future use", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Format: "", + }, + }, + }, + }, + }, + }, + Required: []string{"health", "sync"}, + }, + }, + Dependencies: []string{ + "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryHealthStatus", "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryResourceCount", "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositorySyncStatus", "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositoryWebhookStatus", "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1.RepositorystatusOperatorState"}, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositorySyncOptions(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "enabled": { + SchemaProps: spec.SchemaProps{ + Description: "Enabled must be saved as true before any sync job will run", + Default: false, + Type: []string{"boolean"}, + Format: "", + }, + }, + "target": { + SchemaProps: spec.SchemaProps{ + Description: "Where values should be saved", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "intervalSeconds": { + SchemaProps: spec.SchemaProps{ + Description: "When non-zero, the sync will run periodically", + Type: []string{"integer"}, + Format: "int64", + }, + }, + }, + Required: []string{"enabled", "target"}, + }, + }, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositorySyncStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "state": { + SchemaProps: spec.SchemaProps{ + Description: "pending, running, success, error", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "job": { + SchemaProps: spec.SchemaProps{ + Description: "The ID for the job that ran this sync", + Type: []string{"string"}, + Format: "", + }, + }, + "started": { + SchemaProps: spec.SchemaProps{ + Description: "When the sync job started", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "finished": { + SchemaProps: spec.SchemaProps{ + Description: "When the sync job finished", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "scheduled": { + SchemaProps: spec.SchemaProps{ + Description: "When the next sync check is scheduled", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "message": { + SchemaProps: spec.SchemaProps{ + Description: "Summary messages (will be shown to users)", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "lastRef": { + SchemaProps: spec.SchemaProps{ + Description: "The repository ref when the last successful sync ran", + Type: []string{"string"}, + Format: "", + }, + }, + "incremental": { + SchemaProps: spec.SchemaProps{ + Description: "Incremental synchronization for versioned repositories", + Type: []string{"boolean"}, + Format: "", + }, + }, + }, + Required: []string{"state", "message"}, + }, + }, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositoryWebhookStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "id": { + SchemaProps: spec.SchemaProps{ + Type: []string{"integer"}, + Format: "int64", + }, + }, + "url": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "secret": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "encryptedSecret": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "subscribedEvents": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "lastEvent": { + SchemaProps: spec.SchemaProps{ + Type: []string{"integer"}, + Format: "int64", + }, + }, + }, + }, + }, + } +} + +func schema_provisioning_kinds_provisioning_v0alpha1_RepositorystatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "lastEvaluation": { + SchemaProps: spec.SchemaProps{ + Description: "lastEvaluation is the ResourceVersion last evaluated", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "state": { + SchemaProps: spec.SchemaProps{ + Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "descriptiveState": { + SchemaProps: spec.SchemaProps{ + Description: "descriptiveState is an optional more descriptive state field which has no requirements on format", + Type: []string{"string"}, + Format: "", + }, + }, + "details": { + SchemaProps: spec.SchemaProps{ + Description: "details contains any extra information that is operator-specific", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Format: "", + }, + }, + }, + }, + }, + }, + Required: []string{"lastEvaluation", "state"}, + }, + }, + } +} diff --git a/apps/provisioning/kinds/provisioning_manifest.go b/apps/provisioning/kinds/provisioning_manifest.go new file mode 100644 index 00000000000..677a17d8b55 --- /dev/null +++ b/apps/provisioning/kinds/provisioning_manifest.go @@ -0,0 +1,83 @@ +// +// This file is generated by grafana-app-sdk +// DO NOT EDIT +// + +package kinds + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/grafana/grafana-app-sdk/app" + "github.com/grafana/grafana-app-sdk/resource" + + v0alpha1 "github.com/grafana/grafana/apps/provisioning/kinds/provisioning/v0alpha1" +) + +var ( + rawSchemaRepositoryv0alpha1 = []byte(`{"spec":{"properties":{"bitbucket":{"description":"The repository on Bitbucket.\nMutually exclusive with local | github | git.","properties":{"branch":{"description":"The branch to use in the repository.","type":"string"},"encryptedToken":{"description":"Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted.","items":{"type":"string"},"type":"array"},"path":{"description":"Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository.","type":"string"},"token":{"description":"Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again.","type":"string"},"tokenUser":{"description":"TokenUser is the user that will be used to access the repository if it's a personal access token.","type":"string"},"url":{"description":"The repository URL (e.g. ` + "`" + `https://bitbucket.org/example/test` + "`" + `).","type":"string"}},"required":["branch"],"type":"object"},"description":{"description":"Repository description","type":"string"},"git":{"description":"The repository on Git.\nMutually exclusive with local | github | git.","properties":{"branch":{"description":"The branch to use in the repository.","type":"string"},"encryptedToken":{"description":"Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted.","items":{"type":"string"},"type":"array"},"path":{"description":"Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository.","type":"string"},"token":{"description":"Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again.","type":"string"},"tokenUser":{"description":"TokenUser is the user that will be used to access the repository if it's a personal access token.","type":"string"},"url":{"description":"The repository URL (e.g. ` + "`" + `https://github.com/example/test.git` + "`" + `).","type":"string"}},"required":["branch"],"type":"object"},"github":{"description":"The repository on GitHub.\nMutually exclusive with local | github | git.","properties":{"branch":{"description":"The branch to use in the repository.","type":"string"},"encryptedToken":{"description":"Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted.","items":{"type":"string"},"type":"array"},"generateDashboardPreviews":{"description":"Whether we should show dashboard previews for pull requests.\nBy default, this is false (i.e. we will not create previews).","type":"boolean"},"path":{"description":"Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository.","type":"string"},"token":{"description":"Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again.","type":"string"},"url":{"description":"The repository URL (e.g. ` + "`" + `https://github.com/example/test` + "`" + `).","type":"string"}},"required":["branch"],"type":"object"},"gitlab":{"description":"The repository on GitLab.\nMutually exclusive with local | github | git.","properties":{"branch":{"description":"The branch to use in the repository.","type":"string"},"encryptedToken":{"description":"Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted.","items":{"type":"string"},"type":"array"},"path":{"description":"Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository.","type":"string"},"token":{"description":"Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again.","type":"string"},"url":{"description":"The repository URL (e.g. ` + "`" + `https://gitlab.com/example/test` + "`" + `).","type":"string"}},"required":["branch"],"type":"object"},"local":{"description":"The repository on the local file system.\nMutually exclusive with local | github.","properties":{"path":{"description":"Path to the local repository","type":"string"}},"required":["path"],"type":"object"},"sync":{"description":"Sync settings -- how values are pulled from the repository into grafana","properties":{"enabled":{"description":"Enabled must be saved as true before any sync job will run","type":"boolean"},"intervalSeconds":{"description":"When non-zero, the sync will run periodically","type":"integer"},"target":{"description":"Where values should be saved","enum":["unified","legacy"],"type":"string"}},"required":["enabled","target"],"type":"object"},"title":{"description":"The repository display name (shown in the UI)","type":"string"},"type":{"description":"The repository type. When selected oneOf the values below should be non-nil","enum":["local","github","git","bitbucket","gitlab"],"type":"string"},"workflows":{"description":"UI driven Workflow that allow changes to the contends of the repository.\nThe order is relevant for defining the precedence of the workflows.\nWhen empty, the repository does not support any edits (eg, readonly)","items":{"type":"string"},"type":"array"}},"required":["title","sync","type"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"health":{"description":"This will get updated with the current health status (and updated periodically)","properties":{"checked":{"description":"When the health was checked last time","type":"integer"},"healthy":{"description":"When not healthy, requests will not be executed","type":"boolean"},"message":{"description":"Summary messages (can be shown to users)\nWill only be populated when not healthy","items":{"type":"string"},"type":"array"}},"required":["healthy"],"type":"object"},"observedGeneration":{"description":"The generation of the spec last time reconciliation ran","type":"integer"},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"},"stats":{"description":"The object count when sync last ran","items":{"properties":{"count":{"type":"integer"},"group":{"type":"string"},"resource":{"type":"string"}},"required":["group","resource","count"],"type":"object"},"type":"array"},"sync":{"description":"Sync information with the last sync information","properties":{"finished":{"description":"When the sync job finished","type":"integer"},"incremental":{"description":"Incremental synchronization for versioned repositories","type":"boolean"},"job":{"description":"The ID for the job that ran this sync","type":"string"},"lastRef":{"description":"The repository ref when the last successful sync ran","type":"string"},"message":{"description":"Summary messages (will be shown to users)","items":{"type":"string"},"type":"array"},"scheduled":{"description":"When the next sync check is scheduled","type":"integer"},"started":{"description":"When the sync job started","type":"integer"},"state":{"description":"pending, running, success, error","enum":["pending","running","success","error"],"type":"string"}},"required":["state","message"],"type":"object"},"webhook":{"description":"Webhook Information (if applicable)","properties":{"encryptedSecret":{"items":{"type":"string"},"type":"array"},"id":{"type":"integer"},"lastEvent":{"type":"integer"},"secret":{"type":"string"},"subscribedEvents":{"items":{"type":"string"},"type":"array"},"url":{"type":"string"}},"type":"object"}},"required":["health","sync"],"type":"object"}}`) + versionSchemaRepositoryv0alpha1 app.VersionSchema + _ = json.Unmarshal(rawSchemaRepositoryv0alpha1, &versionSchemaRepositoryv0alpha1) +) + +var appManifestData = app.ManifestData{ + AppName: "provisioning", + Group: "provisioning.grafana.app", + Versions: []app.ManifestVersion{ + { + Name: "v0alpha1", + Served: true, + Kinds: []app.ManifestVersionKind{ + { + Kind: "Repository", + Plural: "Repositories", + Scope: "Namespaced", + Conversion: false, + Admission: &app.AdmissionCapabilities{ + Validation: &app.ValidationCapability{ + Operations: []app.AdmissionOperation{ + app.AdmissionOperationCreate, + app.AdmissionOperationUpdate, + }, + }, + }, + Schema: &versionSchemaRepositoryv0alpha1, + }, + }, + }, + }, +} + +func LocalManifest() app.Manifest { + return app.NewEmbeddedManifest(appManifestData) +} + +func RemoteManifest() app.Manifest { + return app.NewAPIServerManifest("provisioning") +} + +var kindVersionToGoType = map[string]resource.Kind{ + "Repository/v0alpha1": v0alpha1.RepositoryKind(), +} + +// ManifestGoTypeAssociator returns the associated resource.Kind instance for a given Kind and Version, if one exists. +// If there is no association for the provided Kind and Version, exists will return false. +func ManifestGoTypeAssociator(kind, version string) (goType resource.Kind, exists bool) { + goType, exists = kindVersionToGoType[fmt.Sprintf("%s/%s", kind, version)] + return goType, exists +} + +var customRouteToGoResponseType = map[string]any{} + +// ManifestCustomRouteResponsesAssociator returns the associated response go type for a given kind, version, custom route path, and method, if one exists. +// kind may be empty for custom routes which are not kind subroutes. Leading slashes are removed from subroute paths. +// If there is no association for the provided kind, version, custom route path, and method, exists will return false. +func ManifestCustomRouteResponsesAssociator(kind, version, path, verb string) (goType any, exists bool) { + if len(path) > 0 && path[0] == '/' { + path = path[1:] + } + goType, exists = customRouteToGoResponseType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))] + return goType, exists +} diff --git a/apps/provisioning/kinds/repository.cue b/apps/provisioning/kinds/repository.cue new file mode 100644 index 00000000000..ba36b4b962f --- /dev/null +++ b/apps/provisioning/kinds/repository.cue @@ -0,0 +1,171 @@ +package repository + +repository: { + kind: "Repository" + pluralName: "Repositories" + current: "v0alpha1" + validation: { + operations: [ + "CREATE", + "UPDATE", + ] + } + versions: { + "v0alpha1": { + codegen: { + ts: {enabled: false} + go: {enabled: true} + } + schema: { + #LocalRepositoryConfig: { + // Path to the local repository + path: string + } + #GitHubRepositoryConfig: { + // The repository URL (e.g. `https://github.com/example/test`). + url?: string + // The branch to use in the repository. + branch: string + // Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again. + token?: string + // Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted. + encryptedToken?: [...string] + // Whether we should show dashboard previews for pull requests. + // By default, this is false (i.e. we will not create previews). + generateDashboardPreviews?: bool + // Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. + path?: string + } + #GitRepositoryConfig: { + // The repository URL (e.g. `https://github.com/example/test.git`). + url?: string + // The branch to use in the repository. + branch: string + // TokenUser is the user that will be used to access the repository if it's a personal access token. + tokenUser?: string + // Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again. + token?: string + // Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted. + encryptedToken?: [...string] + // Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. + path?: string + } + #BitbucketRepositoryConfig: { + // The repository URL (e.g. `https://bitbucket.org/example/test`). + url?: string + // The branch to use in the repository. + branch: string + // TokenUser is the user that will be used to access the repository if it's a personal access token. + tokenUser?: string + // Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again. + token?: string + // Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted. + encryptedToken?: [...string] + // Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. + path?: string + } + #GitLabRepositoryConfig: { + // The repository URL (e.g. `https://gitlab.com/example/test`). + url?: string + // The branch to use in the repository. + branch: string + // Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again. + token?: string + // Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted. + encryptedToken?: [...string] + // Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. + path?: string + } + #SyncOptions: { + // Enabled must be saved as true before any sync job will run + enabled: bool + // Where values should be saved + target: "unified" | "legacy" + // When non-zero, the sync will run periodically + intervalSeconds?: int + } + #HealthStatus: { + // When not healthy, requests will not be executed + healthy: bool + // When the health was checked last time + checked?: int + // Summary messages (can be shown to users) + // Will only be populated when not healthy + message?: [...string] + } + #SyncStatus: { + // pending, running, success, error + state: "pending" | "running" | "success" | "error" + // The ID for the job that ran this sync + job?: string + // When the sync job started + started?: int + // When the sync job finished + finished?: int + // When the next sync check is scheduled + scheduled?: int + // Summary messages (will be shown to users) + message: [...string] + // The repository ref when the last successful sync ran + lastRef?: string + // Incremental synchronization for versioned repositories + incremental?: bool + } + #ResourceCount: { + group: string + resource: string + count: int + } + #WebhookStatus: { + id?: int + url?: string + secret?: string + encryptedSecret?: [...string] + subscribedEvents?: [...string] + lastEvent?: int + } + spec: { + // The repository display name (shown in the UI) + title: string + // Repository description + description?: string + // UI driven Workflow that allow changes to the contends of the repository. + // The order is relevant for defining the precedence of the workflows. + // When empty, the repository does not support any edits (eg, readonly) + workflows?: [...string] + // Sync settings -- how values are pulled from the repository into grafana + sync: #SyncOptions + // The repository type. When selected oneOf the values below should be non-nil + type: "local" | "github" | "git" | "bitbucket" | "gitlab" + // The repository on the local file system. + // Mutually exclusive with local | github. + local?: #LocalRepositoryConfig + // The repository on GitHub. + // Mutually exclusive with local | github | git. + github?: #GitHubRepositoryConfig + // The repository on Git. + // Mutually exclusive with local | github | git. + git?: #GitRepositoryConfig + // The repository on Bitbucket. + // Mutually exclusive with local | github | git. + bitbucket?: #BitbucketRepositoryConfig + // The repository on GitLab. + // Mutually exclusive with local | github | git. + gitlab?: #GitLabRepositoryConfig + } + status: { + // The generation of the spec last time reconciliation ran + observedGeneration?: int + // This will get updated with the current health status (and updated periodically) + health: #HealthStatus + // Sync information with the last sync information + sync: #SyncStatus + // The object count when sync last ran + stats?: [...#ResourceCount] + // Webhook Information (if applicable) + webhook?: #WebhookStatus + } + } + } + } +} \ No newline at end of file diff --git a/pkg/apis/provisioning/v0alpha1/classic.go b/apps/provisioning/pkg/apis/provisioning/v0alpha1/classic.go similarity index 100% rename from pkg/apis/provisioning/v0alpha1/classic.go rename to apps/provisioning/pkg/apis/provisioning/v0alpha1/classic.go diff --git a/pkg/apis/provisioning/v0alpha1/doc.go b/apps/provisioning/pkg/apis/provisioning/v0alpha1/doc.go similarity index 54% rename from pkg/apis/provisioning/v0alpha1/doc.go rename to apps/provisioning/pkg/apis/provisioning/v0alpha1/doc.go index f24a3d11d11..4499de75b13 100644 --- a/pkg/apis/provisioning/v0alpha1/doc.go +++ b/apps/provisioning/pkg/apis/provisioning/v0alpha1/doc.go @@ -3,4 +3,4 @@ // +k8s:defaulter-gen=TypeMeta // +groupName=provisioning.grafana.app -package v0alpha1 // import "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" +package v0alpha1 // import "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" diff --git a/pkg/apis/provisioning/v0alpha1/jobs.go b/apps/provisioning/pkg/apis/provisioning/v0alpha1/jobs.go similarity index 100% rename from pkg/apis/provisioning/v0alpha1/jobs.go rename to apps/provisioning/pkg/apis/provisioning/v0alpha1/jobs.go diff --git a/pkg/apis/provisioning/v0alpha1/register.go b/apps/provisioning/pkg/apis/provisioning/v0alpha1/register.go similarity index 100% rename from pkg/apis/provisioning/v0alpha1/register.go rename to apps/provisioning/pkg/apis/provisioning/v0alpha1/register.go diff --git a/pkg/apis/provisioning/v0alpha1/settings.go b/apps/provisioning/pkg/apis/provisioning/v0alpha1/settings.go similarity index 100% rename from pkg/apis/provisioning/v0alpha1/settings.go rename to apps/provisioning/pkg/apis/provisioning/v0alpha1/settings.go diff --git a/pkg/apis/provisioning/v0alpha1/types.go b/apps/provisioning/pkg/apis/provisioning/v0alpha1/types.go similarity index 100% rename from pkg/apis/provisioning/v0alpha1/types.go rename to apps/provisioning/pkg/apis/provisioning/v0alpha1/types.go diff --git a/pkg/apis/provisioning/v0alpha1/types_test.go b/apps/provisioning/pkg/apis/provisioning/v0alpha1/types_test.go similarity index 91% rename from pkg/apis/provisioning/v0alpha1/types_test.go rename to apps/provisioning/pkg/apis/provisioning/v0alpha1/types_test.go index ef8643e2a1e..82421b7d611 100644 --- a/pkg/apis/provisioning/v0alpha1/types_test.go +++ b/apps/provisioning/pkg/apis/provisioning/v0alpha1/types_test.go @@ -3,7 +3,7 @@ package v0alpha1_test import ( "testing" - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) func TestRepositoryType_IsGit(t *testing.T) { diff --git a/pkg/apis/provisioning/v0alpha1/zz_generated.deepcopy.go b/apps/provisioning/pkg/apis/provisioning/v0alpha1/zz_generated.deepcopy.go similarity index 100% rename from pkg/apis/provisioning/v0alpha1/zz_generated.deepcopy.go rename to apps/provisioning/pkg/apis/provisioning/v0alpha1/zz_generated.deepcopy.go diff --git a/pkg/apis/provisioning/v0alpha1/zz_generated.defaults.go b/apps/provisioning/pkg/apis/provisioning/v0alpha1/zz_generated.defaults.go similarity index 100% rename from pkg/apis/provisioning/v0alpha1/zz_generated.defaults.go rename to apps/provisioning/pkg/apis/provisioning/v0alpha1/zz_generated.defaults.go diff --git a/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go b/apps/provisioning/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go similarity index 82% rename from pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go rename to apps/provisioning/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go index e6e9e4e9ab5..19911653735 100644 --- a/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go +++ b/apps/provisioning/pkg/apis/provisioning/v0alpha1/zz_generated.openapi.go @@ -14,53 +14,53 @@ import ( func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.Author": schema_pkg_apis_provisioning_v0alpha1_Author(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.BitbucketRepositoryConfig": schema_pkg_apis_provisioning_v0alpha1_BitbucketRepositoryConfig(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.DeleteJobOptions": schema_pkg_apis_provisioning_v0alpha1_DeleteJobOptions(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ErrorDetails": schema_pkg_apis_provisioning_v0alpha1_ErrorDetails(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ExportJobOptions": schema_pkg_apis_provisioning_v0alpha1_ExportJobOptions(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.FileItem": schema_pkg_apis_provisioning_v0alpha1_FileItem(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.FileList": schema_pkg_apis_provisioning_v0alpha1_FileList(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.GitHubRepositoryConfig": schema_pkg_apis_provisioning_v0alpha1_GitHubRepositoryConfig(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.GitLabRepositoryConfig": schema_pkg_apis_provisioning_v0alpha1_GitLabRepositoryConfig(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.GitRepositoryConfig": schema_pkg_apis_provisioning_v0alpha1_GitRepositoryConfig(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.HealthStatus": schema_pkg_apis_provisioning_v0alpha1_HealthStatus(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.HistoryItem": schema_pkg_apis_provisioning_v0alpha1_HistoryItem(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.HistoryList": schema_pkg_apis_provisioning_v0alpha1_HistoryList(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.Job": schema_pkg_apis_provisioning_v0alpha1_Job(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobList": schema_pkg_apis_provisioning_v0alpha1_JobList(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobResourceSummary": schema_pkg_apis_provisioning_v0alpha1_JobResourceSummary(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobSpec": schema_pkg_apis_provisioning_v0alpha1_JobSpec(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobStatus": schema_pkg_apis_provisioning_v0alpha1_JobStatus(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.LocalRepositoryConfig": schema_pkg_apis_provisioning_v0alpha1_LocalRepositoryConfig(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ManagerStats": schema_pkg_apis_provisioning_v0alpha1_ManagerStats(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.MigrateJobOptions": schema_pkg_apis_provisioning_v0alpha1_MigrateJobOptions(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.MoveJobOptions": schema_pkg_apis_provisioning_v0alpha1_MoveJobOptions(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.PullRequestJobOptions": schema_pkg_apis_provisioning_v0alpha1_PullRequestJobOptions(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RefItem": schema_pkg_apis_provisioning_v0alpha1_RefItem(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RefList": schema_pkg_apis_provisioning_v0alpha1_RefList(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.Repository": schema_pkg_apis_provisioning_v0alpha1_Repository(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositoryList": schema_pkg_apis_provisioning_v0alpha1_RepositoryList(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositorySpec": schema_pkg_apis_provisioning_v0alpha1_RepositorySpec(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositoryStatus": schema_pkg_apis_provisioning_v0alpha1_RepositoryStatus(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositoryView": schema_pkg_apis_provisioning_v0alpha1_RepositoryView(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositoryViewList": schema_pkg_apis_provisioning_v0alpha1_RepositoryViewList(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceCount": schema_pkg_apis_provisioning_v0alpha1_ResourceCount(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceList": schema_pkg_apis_provisioning_v0alpha1_ResourceList(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceListItem": schema_pkg_apis_provisioning_v0alpha1_ResourceListItem(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceObjects": schema_pkg_apis_provisioning_v0alpha1_ResourceObjects(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceRef": schema_pkg_apis_provisioning_v0alpha1_ResourceRef(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceRepositoryInfo": schema_pkg_apis_provisioning_v0alpha1_ResourceRepositoryInfo(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceStats": schema_pkg_apis_provisioning_v0alpha1_ResourceStats(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceType": schema_pkg_apis_provisioning_v0alpha1_ResourceType(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceURLs": schema_pkg_apis_provisioning_v0alpha1_ResourceURLs(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceWrapper": schema_pkg_apis_provisioning_v0alpha1_ResourceWrapper(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.SyncJobOptions": schema_pkg_apis_provisioning_v0alpha1_SyncJobOptions(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.SyncOptions": schema_pkg_apis_provisioning_v0alpha1_SyncOptions(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.SyncStatus": schema_pkg_apis_provisioning_v0alpha1_SyncStatus(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.TestResults": schema_pkg_apis_provisioning_v0alpha1_TestResults(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.WebhookResponse": schema_pkg_apis_provisioning_v0alpha1_WebhookResponse(ref), - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.WebhookStatus": schema_pkg_apis_provisioning_v0alpha1_WebhookStatus(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.Author": schema_pkg_apis_provisioning_v0alpha1_Author(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.BitbucketRepositoryConfig": schema_pkg_apis_provisioning_v0alpha1_BitbucketRepositoryConfig(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.DeleteJobOptions": schema_pkg_apis_provisioning_v0alpha1_DeleteJobOptions(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ErrorDetails": schema_pkg_apis_provisioning_v0alpha1_ErrorDetails(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ExportJobOptions": schema_pkg_apis_provisioning_v0alpha1_ExportJobOptions(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.FileItem": schema_pkg_apis_provisioning_v0alpha1_FileItem(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.FileList": schema_pkg_apis_provisioning_v0alpha1_FileList(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.GitHubRepositoryConfig": schema_pkg_apis_provisioning_v0alpha1_GitHubRepositoryConfig(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.GitLabRepositoryConfig": schema_pkg_apis_provisioning_v0alpha1_GitLabRepositoryConfig(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.GitRepositoryConfig": schema_pkg_apis_provisioning_v0alpha1_GitRepositoryConfig(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.HealthStatus": schema_pkg_apis_provisioning_v0alpha1_HealthStatus(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.HistoryItem": schema_pkg_apis_provisioning_v0alpha1_HistoryItem(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.HistoryList": schema_pkg_apis_provisioning_v0alpha1_HistoryList(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.Job": schema_pkg_apis_provisioning_v0alpha1_Job(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobList": schema_pkg_apis_provisioning_v0alpha1_JobList(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobResourceSummary": schema_pkg_apis_provisioning_v0alpha1_JobResourceSummary(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobSpec": schema_pkg_apis_provisioning_v0alpha1_JobSpec(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobStatus": schema_pkg_apis_provisioning_v0alpha1_JobStatus(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.LocalRepositoryConfig": schema_pkg_apis_provisioning_v0alpha1_LocalRepositoryConfig(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ManagerStats": schema_pkg_apis_provisioning_v0alpha1_ManagerStats(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.MigrateJobOptions": schema_pkg_apis_provisioning_v0alpha1_MigrateJobOptions(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.MoveJobOptions": schema_pkg_apis_provisioning_v0alpha1_MoveJobOptions(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.PullRequestJobOptions": schema_pkg_apis_provisioning_v0alpha1_PullRequestJobOptions(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RefItem": schema_pkg_apis_provisioning_v0alpha1_RefItem(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RefList": schema_pkg_apis_provisioning_v0alpha1_RefList(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.Repository": schema_pkg_apis_provisioning_v0alpha1_Repository(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryList": schema_pkg_apis_provisioning_v0alpha1_RepositoryList(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositorySpec": schema_pkg_apis_provisioning_v0alpha1_RepositorySpec(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryStatus": schema_pkg_apis_provisioning_v0alpha1_RepositoryStatus(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryView": schema_pkg_apis_provisioning_v0alpha1_RepositoryView(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryViewList": schema_pkg_apis_provisioning_v0alpha1_RepositoryViewList(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceCount": schema_pkg_apis_provisioning_v0alpha1_ResourceCount(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceList": schema_pkg_apis_provisioning_v0alpha1_ResourceList(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceListItem": schema_pkg_apis_provisioning_v0alpha1_ResourceListItem(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceObjects": schema_pkg_apis_provisioning_v0alpha1_ResourceObjects(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceRef": schema_pkg_apis_provisioning_v0alpha1_ResourceRef(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceRepositoryInfo": schema_pkg_apis_provisioning_v0alpha1_ResourceRepositoryInfo(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceStats": schema_pkg_apis_provisioning_v0alpha1_ResourceStats(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceType": schema_pkg_apis_provisioning_v0alpha1_ResourceType(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceURLs": schema_pkg_apis_provisioning_v0alpha1_ResourceURLs(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceWrapper": schema_pkg_apis_provisioning_v0alpha1_ResourceWrapper(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.SyncJobOptions": schema_pkg_apis_provisioning_v0alpha1_SyncJobOptions(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.SyncOptions": schema_pkg_apis_provisioning_v0alpha1_SyncOptions(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.SyncStatus": schema_pkg_apis_provisioning_v0alpha1_SyncStatus(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.TestResults": schema_pkg_apis_provisioning_v0alpha1_TestResults(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.WebhookResponse": schema_pkg_apis_provisioning_v0alpha1_WebhookResponse(ref), + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.WebhookStatus": schema_pkg_apis_provisioning_v0alpha1_WebhookStatus(ref), } } @@ -194,7 +194,7 @@ func schema_pkg_apis_provisioning_v0alpha1_DeleteJobOptions(ref common.Reference Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceRef"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceRef"), }, }, }, @@ -204,7 +204,7 @@ func schema_pkg_apis_provisioning_v0alpha1_DeleteJobOptions(ref common.Reference }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceRef"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceRef"}, } } @@ -363,7 +363,7 @@ func schema_pkg_apis_provisioning_v0alpha1_FileList(ref common.ReferenceCallback Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.FileItem"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.FileItem"), }, }, }, @@ -374,7 +374,7 @@ func schema_pkg_apis_provisioning_v0alpha1_FileList(ref common.ReferenceCallback }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.FileItem", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.FileItem", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, } } @@ -634,7 +634,7 @@ func schema_pkg_apis_provisioning_v0alpha1_HistoryItem(ref common.ReferenceCallb Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.Author"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.Author"), }, }, }, @@ -652,7 +652,7 @@ func schema_pkg_apis_provisioning_v0alpha1_HistoryItem(ref common.ReferenceCallb }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.Author"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.Author"}, } } @@ -695,7 +695,7 @@ func schema_pkg_apis_provisioning_v0alpha1_HistoryList(ref common.ReferenceCallb Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.HistoryItem"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.HistoryItem"), }, }, }, @@ -706,7 +706,7 @@ func schema_pkg_apis_provisioning_v0alpha1_HistoryList(ref common.ReferenceCallb }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.HistoryItem", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.HistoryItem", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, } } @@ -740,20 +740,20 @@ func schema_pkg_apis_provisioning_v0alpha1_Job(ref common.ReferenceCallback) com "spec": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobSpec"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobSpec"), }, }, "status": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobStatus"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobStatus"), }, }, }, }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobSpec", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobSpec", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, } } @@ -790,7 +790,7 @@ func schema_pkg_apis_provisioning_v0alpha1_JobList(ref common.ReferenceCallback) Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.Job"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.Job"), }, }, }, @@ -801,7 +801,7 @@ func schema_pkg_apis_provisioning_v0alpha1_JobList(ref common.ReferenceCallback) }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.Job", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.Job", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, } } @@ -912,44 +912,44 @@ func schema_pkg_apis_provisioning_v0alpha1_JobSpec(ref common.ReferenceCallback) "pr": { SchemaProps: spec.SchemaProps{ Description: "Pull request options", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.PullRequestJobOptions"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.PullRequestJobOptions"), }, }, "push": { SchemaProps: spec.SchemaProps{ Description: "Required when the action is `push`", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ExportJobOptions"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ExportJobOptions"), }, }, "pull": { SchemaProps: spec.SchemaProps{ Description: "Required when the action is `pull`", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.SyncJobOptions"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.SyncJobOptions"), }, }, "migrate": { SchemaProps: spec.SchemaProps{ Description: "Required when the action is `migrate`", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.MigrateJobOptions"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.MigrateJobOptions"), }, }, "delete": { SchemaProps: spec.SchemaProps{ Description: "Delete when the action is `delete`", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.DeleteJobOptions"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.DeleteJobOptions"), }, }, "move": { SchemaProps: spec.SchemaProps{ Description: "Move when the action is `move`", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.MoveJobOptions"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.MoveJobOptions"), }, }, }, }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.DeleteJobOptions", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ExportJobOptions", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.MigrateJobOptions", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.MoveJobOptions", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.PullRequestJobOptions", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.SyncJobOptions"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.DeleteJobOptions", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ExportJobOptions", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.MigrateJobOptions", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.MoveJobOptions", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.PullRequestJobOptions", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.SyncJobOptions"}, } } @@ -1014,7 +1014,7 @@ func schema_pkg_apis_provisioning_v0alpha1_JobStatus(ref common.ReferenceCallbac Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobResourceSummary"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobResourceSummary"), }, }, }, @@ -1024,7 +1024,7 @@ func schema_pkg_apis_provisioning_v0alpha1_JobStatus(ref common.ReferenceCallbac }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobResourceSummary"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobResourceSummary"}, } } @@ -1074,7 +1074,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ManagerStats(ref common.ReferenceCall Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceCount"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceCount"), }, }, }, @@ -1085,7 +1085,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ManagerStats(ref common.ReferenceCall }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceCount"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceCount"}, } } @@ -1158,7 +1158,7 @@ func schema_pkg_apis_provisioning_v0alpha1_MoveJobOptions(ref common.ReferenceCa Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceRef"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceRef"), }, }, }, @@ -1168,7 +1168,7 @@ func schema_pkg_apis_provisioning_v0alpha1_MoveJobOptions(ref common.ReferenceCa }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceRef"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceRef"}, } } @@ -1285,7 +1285,7 @@ func schema_pkg_apis_provisioning_v0alpha1_RefList(ref common.ReferenceCallback) Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RefItem"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RefItem"), }, }, }, @@ -1296,7 +1296,7 @@ func schema_pkg_apis_provisioning_v0alpha1_RefList(ref common.ReferenceCallback) }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RefItem", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RefItem", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, } } @@ -1330,20 +1330,20 @@ func schema_pkg_apis_provisioning_v0alpha1_Repository(ref common.ReferenceCallba "spec": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositorySpec"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositorySpec"), }, }, "status": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositoryStatus"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryStatus"), }, }, }, }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositorySpec", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositoryStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositorySpec", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, } } @@ -1385,7 +1385,7 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositoryList(ref common.ReferenceCa Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.Repository"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.Repository"), }, }, }, @@ -1396,7 +1396,7 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositoryList(ref common.ReferenceCa }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.Repository", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.Repository", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, } } @@ -1441,7 +1441,7 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositorySpec(ref common.ReferenceCa SchemaProps: spec.SchemaProps{ Description: "Sync settings -- how values are pulled from the repository into grafana", Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.SyncOptions"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.SyncOptions"), }, }, "type": { @@ -1456,31 +1456,31 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositorySpec(ref common.ReferenceCa "local": { SchemaProps: spec.SchemaProps{ Description: "The repository on the local file system. Mutually exclusive with local | github.", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.LocalRepositoryConfig"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.LocalRepositoryConfig"), }, }, "github": { SchemaProps: spec.SchemaProps{ Description: "The repository on GitHub. Mutually exclusive with local | github | git.", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.GitHubRepositoryConfig"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.GitHubRepositoryConfig"), }, }, "git": { SchemaProps: spec.SchemaProps{ Description: "The repository on Git. Mutually exclusive with local | github | git.", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.GitRepositoryConfig"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.GitRepositoryConfig"), }, }, "bitbucket": { SchemaProps: spec.SchemaProps{ Description: "The repository on Bitbucket. Mutually exclusive with local | github | git.", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.BitbucketRepositoryConfig"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.BitbucketRepositoryConfig"), }, }, "gitlab": { SchemaProps: spec.SchemaProps{ Description: "The repository on GitLab. Mutually exclusive with local | github | git.", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.GitLabRepositoryConfig"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.GitLabRepositoryConfig"), }, }, }, @@ -1488,7 +1488,7 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositorySpec(ref common.ReferenceCa }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.BitbucketRepositoryConfig", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.GitHubRepositoryConfig", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.GitLabRepositoryConfig", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.GitRepositoryConfig", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.LocalRepositoryConfig", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.SyncOptions"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.BitbucketRepositoryConfig", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.GitHubRepositoryConfig", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.GitLabRepositoryConfig", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.GitRepositoryConfig", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.LocalRepositoryConfig", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.SyncOptions"}, } } @@ -1511,14 +1511,14 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositoryStatus(ref common.Reference SchemaProps: spec.SchemaProps{ Description: "This will get updated with the current health status (and updated periodically)", Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.HealthStatus"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.HealthStatus"), }, }, "sync": { SchemaProps: spec.SchemaProps{ Description: "Sync information with the last sync information", Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.SyncStatus"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.SyncStatus"), }, }, "stats": { @@ -1534,7 +1534,7 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositoryStatus(ref common.Reference Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceCount"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceCount"), }, }, }, @@ -1543,7 +1543,7 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositoryStatus(ref common.Reference "webhook": { SchemaProps: spec.SchemaProps{ Description: "Webhook Information (if applicable)", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.WebhookStatus"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.WebhookStatus"), }, }, }, @@ -1551,7 +1551,7 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositoryStatus(ref common.Reference }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.HealthStatus", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceCount", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.SyncStatus", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.WebhookStatus"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.HealthStatus", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceCount", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.SyncStatus", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.WebhookStatus"}, } } @@ -1681,7 +1681,7 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositoryViewList(ref common.Referen Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositoryView"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryView"), }, }, }, @@ -1692,7 +1692,7 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositoryViewList(ref common.Referen }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.RepositoryView"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.RepositoryView"}, } } @@ -1769,7 +1769,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceList(ref common.ReferenceCall Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceListItem"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceListItem"), }, }, }, @@ -1780,7 +1780,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceList(ref common.ReferenceCall }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceListItem", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceListItem", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, } } @@ -1861,7 +1861,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceObjects(ref common.ReferenceC SchemaProps: spec.SchemaProps{ Description: "The identified type for this object", Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceType"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceType"), }, }, "file": { @@ -1901,7 +1901,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceObjects(ref common.ReferenceC }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.Unstructured", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceType"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceType", "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.Unstructured"}, } } @@ -2024,7 +2024,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceStats(ref common.ReferenceCal Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceCount"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceCount"), }, }, }, @@ -2043,7 +2043,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceStats(ref common.ReferenceCal Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ManagerStats"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ManagerStats"), }, }, }, @@ -2053,7 +2053,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceStats(ref common.ReferenceCal }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ManagerStats", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceCount", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ManagerStats", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceCount", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, } } @@ -2187,13 +2187,13 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceWrapper(ref common.ReferenceC SchemaProps: spec.SchemaProps{ Description: "Basic repository info", Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceRepositoryInfo"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceRepositoryInfo"), }, }, "urls": { SchemaProps: spec.SchemaProps{ Description: "Typed links for this file (only supported by external systems, github etc)", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceURLs"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceURLs"), }, }, "timestamp": { @@ -2206,7 +2206,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceWrapper(ref common.ReferenceC SchemaProps: spec.SchemaProps{ Description: "Different flavors of the same object", Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceObjects"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceObjects"), }, }, "errors": { @@ -2234,7 +2234,7 @@ func schema_pkg_apis_provisioning_v0alpha1_ResourceWrapper(ref common.ReferenceC }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceObjects", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceRepositoryInfo", "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ResourceURLs", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceObjects", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceRepositoryInfo", "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ResourceURLs", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, } } @@ -2425,7 +2425,7 @@ func schema_pkg_apis_provisioning_v0alpha1_TestResults(ref common.ReferenceCallb Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ErrorDetails"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ErrorDetails"), }, }, }, @@ -2436,7 +2436,7 @@ func schema_pkg_apis_provisioning_v0alpha1_TestResults(ref common.ReferenceCallb }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.ErrorDetails"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.ErrorDetails"}, } } @@ -2477,14 +2477,14 @@ func schema_pkg_apis_provisioning_v0alpha1_WebhookResponse(ref common.ReferenceC "job": { SchemaProps: spec.SchemaProps{ Description: "Jobs to be processed When the response is 202 (Accepted) the queued jobs will be returned", - Ref: ref("github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobSpec"), + Ref: ref("github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobSpec"), }, }, }, }, }, Dependencies: []string{ - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1.JobSpec"}, + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1.JobSpec"}, } } diff --git a/apps/provisioning/pkg/apis/provisioning/v0alpha1/zz_generated.openapi_violation_exceptions.list b/apps/provisioning/pkg/apis/provisioning/v0alpha1/zz_generated.openapi_violation_exceptions.list new file mode 100644 index 00000000000..a92f95837a2 --- /dev/null +++ b/apps/provisioning/pkg/apis/provisioning/v0alpha1/zz_generated.openapi_violation_exceptions.list @@ -0,0 +1,26 @@ +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,DeleteJobOptions,Paths +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,DeleteJobOptions,Resources +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,FileList,Items +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,HistoryList,Items +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,JobResourceSummary,Errors +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,JobStatus,Errors +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,JobStatus,Summary +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,ManagerStats,Stats +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,MoveJobOptions,Paths +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,MoveJobOptions,Resources +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,RefList,Items +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,RepositoryList,Items +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,RepositorySpec,Workflows +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,RepositoryView,Workflows +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,RepositoryViewList,AvailableRepositoryTypes +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,RepositoryViewList,Items +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,ResourceList,Items +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,TestResults,Errors +API rule violation: list_type_missing,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,WebhookStatus,SubscribedEvents +API rule violation: names_match,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,JobSpec,PullRequest +API rule violation: names_match,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,ManagerStats,Identity +API rule violation: names_match,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,RepositorySpec,GitHub +API rule violation: names_match,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,RepositorySpec,GitLab +API rule violation: names_match,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,ResourceWrapper,URLs +API rule violation: names_match,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,SyncStatus,JobID +API rule violation: names_match,github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1,WebhookResponse,Message diff --git a/apps/provisioning/pkg/generated/applyconfiguration/internal/internal.go b/apps/provisioning/pkg/generated/applyconfiguration/internal/internal.go new file mode 100644 index 00000000000..ddd9f734c85 --- /dev/null +++ b/apps/provisioning/pkg/generated/applyconfiguration/internal/internal.go @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package internal + +import ( + fmt "fmt" + sync "sync" + + typed "sigs.k8s.io/structured-merge-diff/v4/typed" +) + +func Parser() *typed.Parser { + parserOnce.Do(func() { + var err error + parser, err = typed.NewParser(schemaYAML) + if err != nil { + panic(fmt.Sprintf("Failed to parse schema: %v", err)) + } + }) + return parser +} + +var parserOnce sync.Once +var parser *typed.Parser +var schemaYAML = typed.YAMLObject(`types: +- name: __untyped_atomic_ + scalar: untyped + list: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic + map: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic +- name: __untyped_deduced_ + scalar: untyped + list: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic + map: + elementType: + namedType: __untyped_deduced_ + elementRelationship: separable +`) diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/bitbucketrepositoryconfig.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/bitbucketrepositoryconfig.go similarity index 100% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/bitbucketrepositoryconfig.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/bitbucketrepositoryconfig.go diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/githubrepositoryconfig.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/githubrepositoryconfig.go similarity index 100% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/githubrepositoryconfig.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/githubrepositoryconfig.go diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/gitlabrepositoryconfig.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/gitlabrepositoryconfig.go similarity index 100% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/gitlabrepositoryconfig.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/gitlabrepositoryconfig.go diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/gitrepositoryconfig.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/gitrepositoryconfig.go similarity index 100% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/gitrepositoryconfig.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/gitrepositoryconfig.go diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/healthstatus.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/healthstatus.go similarity index 100% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/healthstatus.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/healthstatus.go diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/localrepositoryconfig.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/localrepositoryconfig.go similarity index 100% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/localrepositoryconfig.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/localrepositoryconfig.go diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/repository.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/repository.go similarity index 100% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/repository.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/repository.go diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/repositoryspec.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/repositoryspec.go similarity index 98% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/repositoryspec.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/repositoryspec.go index 13d9e45d582..6fff6f2de42 100644 --- a/pkg/generated/applyconfiguration/provisioning/v0alpha1/repositoryspec.go +++ b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/repositoryspec.go @@ -5,7 +5,7 @@ package v0alpha1 import ( - provisioningv0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // RepositorySpecApplyConfiguration represents a declarative configuration of the RepositorySpec type for use diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/repositorystatus.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/repositorystatus.go similarity index 100% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/repositorystatus.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/repositorystatus.go diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/resourcecount.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/resourcecount.go similarity index 100% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/resourcecount.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/resourcecount.go diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/syncoptions.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/syncoptions.go similarity index 95% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/syncoptions.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/syncoptions.go index 837b071930f..05e7396e536 100644 --- a/pkg/generated/applyconfiguration/provisioning/v0alpha1/syncoptions.go +++ b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/syncoptions.go @@ -5,7 +5,7 @@ package v0alpha1 import ( - provisioningv0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // SyncOptionsApplyConfiguration represents a declarative configuration of the SyncOptions type for use diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/syncstatus.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/syncstatus.go similarity index 97% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/syncstatus.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/syncstatus.go index 6b8f5abbac1..408e452f9a1 100644 --- a/pkg/generated/applyconfiguration/provisioning/v0alpha1/syncstatus.go +++ b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/syncstatus.go @@ -5,7 +5,7 @@ package v0alpha1 import ( - provisioningv0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // SyncStatusApplyConfiguration represents a declarative configuration of the SyncStatus type for use diff --git a/pkg/generated/applyconfiguration/provisioning/v0alpha1/webhookstatus.go b/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/webhookstatus.go similarity index 100% rename from pkg/generated/applyconfiguration/provisioning/v0alpha1/webhookstatus.go rename to apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1/webhookstatus.go diff --git a/apps/provisioning/pkg/generated/applyconfiguration/utils.go b/apps/provisioning/pkg/generated/applyconfiguration/utils.go new file mode 100644 index 00000000000..29392ef2f2a --- /dev/null +++ b/apps/provisioning/pkg/generated/applyconfiguration/utils.go @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package applyconfiguration + +import ( + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + internal "github.com/grafana/grafana/apps/provisioning/pkg/generated/applyconfiguration/internal" + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + testing "k8s.io/client-go/testing" +) + +// ForKind returns an apply configuration type for the given GroupVersionKind, or nil if no +// apply configuration type exists for the given GroupVersionKind. +func ForKind(kind schema.GroupVersionKind) interface{} { + switch kind { + // Group=provisioning.grafana.app, Version=v0alpha1 + case v0alpha1.SchemeGroupVersion.WithKind("BitbucketRepositoryConfig"): + return &provisioningv0alpha1.BitbucketRepositoryConfigApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("GitHubRepositoryConfig"): + return &provisioningv0alpha1.GitHubRepositoryConfigApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("GitLabRepositoryConfig"): + return &provisioningv0alpha1.GitLabRepositoryConfigApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("GitRepositoryConfig"): + return &provisioningv0alpha1.GitRepositoryConfigApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("HealthStatus"): + return &provisioningv0alpha1.HealthStatusApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("LocalRepositoryConfig"): + return &provisioningv0alpha1.LocalRepositoryConfigApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("Repository"): + return &provisioningv0alpha1.RepositoryApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("RepositorySpec"): + return &provisioningv0alpha1.RepositorySpecApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("RepositoryStatus"): + return &provisioningv0alpha1.RepositoryStatusApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("ResourceCount"): + return &provisioningv0alpha1.ResourceCountApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("SyncOptions"): + return &provisioningv0alpha1.SyncOptionsApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("SyncStatus"): + return &provisioningv0alpha1.SyncStatusApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("WebhookStatus"): + return &provisioningv0alpha1.WebhookStatusApplyConfiguration{} + + } + return nil +} + +func NewTypeConverter(scheme *runtime.Scheme) *testing.TypeConverter { + return &testing.TypeConverter{Scheme: scheme, TypeResolver: internal.Parser()} +} diff --git a/apps/provisioning/pkg/generated/clientset/versioned/clientset.go b/apps/provisioning/pkg/generated/clientset/versioned/clientset.go new file mode 100644 index 00000000000..f38fb19e56e --- /dev/null +++ b/apps/provisioning/pkg/generated/clientset/versioned/clientset.go @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +// Code generated by client-gen. DO NOT EDIT. + +package versioned + +import ( + fmt "fmt" + http "net/http" + + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" + discovery "k8s.io/client-go/discovery" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + ProvisioningV0alpha1() provisioningv0alpha1.ProvisioningV0alpha1Interface +} + +// Clientset contains the clients for groups. +type Clientset struct { + *discovery.DiscoveryClient + provisioningV0alpha1 *provisioningv0alpha1.ProvisioningV0alpha1Client +} + +// ProvisioningV0alpha1 retrieves the ProvisioningV0alpha1Client +func (c *Clientset) ProvisioningV0alpha1() provisioningv0alpha1.ProvisioningV0alpha1Interface { + return c.provisioningV0alpha1 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfig will generate a rate-limiter in configShallowCopy. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + + if configShallowCopy.UserAgent == "" { + configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent() + } + + // share the transport between all clients + httpClient, err := rest.HTTPClientFor(&configShallowCopy) + if err != nil { + return nil, err + } + + return NewForConfigAndClient(&configShallowCopy, httpClient) +} + +// NewForConfigAndClient creates a new Clientset for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfigAndClient will generate a rate-limiter in configShallowCopy. +func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + if configShallowCopy.Burst <= 0 { + return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") + } + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + + var cs Clientset + var err error + cs.provisioningV0alpha1, err = provisioningv0alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + cs, err := NewForConfig(c) + if err != nil { + panic(err) + } + return cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.provisioningV0alpha1 = provisioningv0alpha1.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/apps/provisioning/pkg/generated/clientset/versioned/fake/clientset_generated.go b/apps/provisioning/pkg/generated/clientset/versioned/fake/clientset_generated.go new file mode 100644 index 00000000000..bcb742b634e --- /dev/null +++ b/apps/provisioning/pkg/generated/clientset/versioned/fake/clientset_generated.go @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + applyconfiguration "github.com/grafana/grafana/apps/provisioning/pkg/generated/applyconfiguration" + clientset "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned" + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" + fakeprovisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/discovery" + fakediscovery "k8s.io/client-go/discovery/fake" + "k8s.io/client-go/testing" +) + +// NewSimpleClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any field management, validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +// +// DEPRECATED: NewClientset replaces this with support for field management, which significantly improves +// server side apply testing. NewClientset is only available when apply configurations are generated (e.g. +// via --with-applyconfig). +func NewSimpleClientset(objects ...runtime.Object) *Clientset { + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{tracker: o} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + var opts metav1.ListOptions + if watchActcion, ok := action.(testing.WatchActionImpl); ok { + opts = watchActcion.ListOptions + } + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns, opts) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.Interface. Meant to be embedded into a +// struct to get a default implementation. This makes faking out just the method +// you want to test easier. +type Clientset struct { + testing.Fake + discovery *fakediscovery.FakeDiscovery + tracker testing.ObjectTracker +} + +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} + +func (c *Clientset) Tracker() testing.ObjectTracker { + return c.tracker +} + +// NewClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +func NewClientset(objects ...runtime.Object) *Clientset { + o := testing.NewFieldManagedObjectTracker( + scheme, + codecs.UniversalDecoder(), + applyconfiguration.NewTypeConverter(scheme), + ) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{tracker: o} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + var opts metav1.ListOptions + if watchActcion, ok := action.(testing.WatchActionImpl); ok { + opts = watchActcion.ListOptions + } + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns, opts) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +var ( + _ clientset.Interface = &Clientset{} + _ testing.FakeClient = &Clientset{} +) + +// ProvisioningV0alpha1 retrieves the ProvisioningV0alpha1Client +func (c *Clientset) ProvisioningV0alpha1() provisioningv0alpha1.ProvisioningV0alpha1Interface { + return &fakeprovisioningv0alpha1.FakeProvisioningV0alpha1{Fake: &c.Fake} +} diff --git a/apps/provisioning/pkg/generated/clientset/versioned/fake/doc.go b/apps/provisioning/pkg/generated/clientset/versioned/fake/doc.go new file mode 100644 index 00000000000..bc6b017db1b --- /dev/null +++ b/apps/provisioning/pkg/generated/clientset/versioned/fake/doc.go @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated fake clientset. +package fake diff --git a/apps/provisioning/pkg/generated/clientset/versioned/fake/register.go b/apps/provisioning/pkg/generated/clientset/versioned/fake/register.go new file mode 100644 index 00000000000..840c9e7813b --- /dev/null +++ b/apps/provisioning/pkg/generated/clientset/versioned/fake/register.go @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var scheme = runtime.NewScheme() +var codecs = serializer.NewCodecFactory(scheme) + +var localSchemeBuilder = runtime.SchemeBuilder{ + provisioningv0alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(scheme)) +} diff --git a/apps/provisioning/pkg/generated/clientset/versioned/scheme/doc.go b/apps/provisioning/pkg/generated/clientset/versioned/scheme/doc.go new file mode 100644 index 00000000000..b69e1aef906 --- /dev/null +++ b/apps/provisioning/pkg/generated/clientset/versioned/scheme/doc.go @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +// Code generated by client-gen. DO NOT EDIT. + +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/apps/provisioning/pkg/generated/clientset/versioned/scheme/register.go b/apps/provisioning/pkg/generated/clientset/versioned/scheme/register.go new file mode 100644 index 00000000000..133c9b3f74f --- /dev/null +++ b/apps/provisioning/pkg/generated/clientset/versioned/scheme/register.go @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +// Code generated by client-gen. DO NOT EDIT. + +package scheme + +import ( + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + provisioningv0alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/doc.go b/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/doc.go similarity index 100% rename from pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/doc.go rename to apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/doc.go diff --git a/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/doc.go b/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/doc.go similarity index 100% rename from pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/doc.go rename to apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/doc.go diff --git a/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_provisioning_client.go b/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_provisioning_client.go similarity index 83% rename from pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_provisioning_client.go rename to apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_provisioning_client.go index eb97df6de39..19a9c803579 100644 --- a/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_provisioning_client.go +++ b/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_provisioning_client.go @@ -5,7 +5,7 @@ package fake import ( - v0alpha1 "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" rest "k8s.io/client-go/rest" testing "k8s.io/client-go/testing" ) diff --git a/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_repository.go b/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_repository.go similarity index 79% rename from pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_repository.go rename to apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_repository.go index 3991d3c4ea8..15d0d1bf749 100644 --- a/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_repository.go +++ b/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake/fake_repository.go @@ -5,9 +5,9 @@ package fake import ( - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" - provisioningv0alpha1 "github.com/grafana/grafana/pkg/generated/applyconfiguration/provisioning/v0alpha1" - typedprovisioningv0alpha1 "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1" + typedprovisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" gentype "k8s.io/client-go/gentype" ) diff --git a/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/generated_expansion.go b/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/generated_expansion.go similarity index 100% rename from pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/generated_expansion.go rename to apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/generated_expansion.go diff --git a/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/provisioning_client.go b/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/provisioning_client.go similarity index 92% rename from pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/provisioning_client.go rename to apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/provisioning_client.go index 27363d30e99..75998b83300 100644 --- a/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/provisioning_client.go +++ b/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/provisioning_client.go @@ -7,8 +7,8 @@ package v0alpha1 import ( http "net/http" - provisioningv0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" - scheme "github.com/grafana/grafana/pkg/generated/clientset/versioned/scheme" + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + scheme "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/scheme" rest "k8s.io/client-go/rest" ) diff --git a/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/repository.go b/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/repository.go similarity index 91% rename from pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/repository.go rename to apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/repository.go index 9425083857b..98e7b47f40b 100644 --- a/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/repository.go +++ b/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/repository.go @@ -7,9 +7,9 @@ package v0alpha1 import ( context "context" - provisioningv0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" - applyconfigurationprovisioningv0alpha1 "github.com/grafana/grafana/pkg/generated/applyconfiguration/provisioning/v0alpha1" - scheme "github.com/grafana/grafana/pkg/generated/clientset/versioned/scheme" + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + applyconfigurationprovisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/generated/applyconfiguration/provisioning/v0alpha1" + scheme "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/scheme" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/apps/provisioning/pkg/generated/informers/externalversions/factory.go b/apps/provisioning/pkg/generated/informers/externalversions/factory.go new file mode 100644 index 00000000000..fb8443331f2 --- /dev/null +++ b/apps/provisioning/pkg/generated/informers/externalversions/factory.go @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + reflect "reflect" + sync "sync" + time "time" + + versioned "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned" + internalinterfaces "github.com/grafana/grafana/apps/provisioning/pkg/generated/informers/externalversions/internalinterfaces" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/generated/informers/externalversions/provisioning" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + transform cache.TransformFunc + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool + // wg tracks how many goroutines were started. + wg sync.WaitGroup + // shuttingDown is true when Shutdown has been called. It may still be running + // because it needs to wait for goroutines. + shuttingDown bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// WithTransform sets a transform on all informers. +func WithTransform(transform cache.TransformFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.transform = transform + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + if f.shuttingDown { + return + } + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + f.wg.Add(1) + // We need a new variable in each loop iteration, + // otherwise the goroutine would use the loop variable + // and that keeps changing. + informer := informer + go func() { + defer f.wg.Done() + informer.Run(stopCh) + }() + f.startedInformers[informerType] = true + } + } +} + +func (f *sharedInformerFactory) Shutdown() { + f.lock.Lock() + f.shuttingDown = true + f.lock.Unlock() + + // Will return immediately if there is nothing to wait for. + f.wg.Wait() +} + +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + informer.SetTransform(f.transform) + f.informers[informerType] = informer + + return informer +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +// +// It is typically used like this: +// +// ctx, cancel := context.Background() +// defer cancel() +// factory := NewSharedInformerFactory(client, resyncPeriod) +// defer factory.WaitForStop() // Returns immediately if nothing was started. +// genericInformer := factory.ForResource(resource) +// typedInformer := factory.SomeAPIGroup().V1().SomeType() +// factory.Start(ctx.Done()) // Start processing these informers. +// synced := factory.WaitForCacheSync(ctx.Done()) +// for v, ok := range synced { +// if !ok { +// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) +// return +// } +// } +// +// // Creating informers can also be created after Start, but then +// // Start must be called again: +// anotherGenericInformer := factory.ForResource(resource) +// factory.Start(ctx.Done()) +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + + // Start initializes all requested informers. They are handled in goroutines + // which run until the stop channel gets closed. + // Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync. + Start(stopCh <-chan struct{}) + + // Shutdown marks a factory as shutting down. At that point no new + // informers can be started anymore and Start will return without + // doing anything. + // + // In addition, Shutdown blocks until all goroutines have terminated. For that + // to happen, the close channel(s) that they were started with must be closed, + // either before Shutdown gets called or while it is waiting. + // + // Shutdown may be called multiple times, even concurrently. All such calls will + // block until all goroutines have terminated. + Shutdown() + + // WaitForCacheSync blocks until all started informers' caches were synced + // or the stop channel gets closed. + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + // ForResource gives generic access to a shared informer of the matching type. + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // InformerFor returns the SharedIndexInformer for obj using an internal + // client. + InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer + + Provisioning() provisioning.Interface +} + +func (f *sharedInformerFactory) Provisioning() provisioning.Interface { + return provisioning.New(f, f.namespace, f.tweakListOptions) +} diff --git a/apps/provisioning/pkg/generated/informers/externalversions/generic.go b/apps/provisioning/pkg/generated/informers/externalversions/generic.go new file mode 100644 index 00000000000..d4b7d049e54 --- /dev/null +++ b/apps/provisioning/pkg/generated/informers/externalversions/generic.go @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + fmt "fmt" + + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=provisioning.grafana.app, Version=v0alpha1 + case v0alpha1.SchemeGroupVersion.WithResource("repositories"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Provisioning().V0alpha1().Repositories().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/apps/provisioning/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go b/apps/provisioning/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go new file mode 100644 index 00000000000..06fe98fc993 --- /dev/null +++ b/apps/provisioning/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +// Code generated by informer-gen. DO NOT EDIT. + +package internalinterfaces + +import ( + time "time" + + versioned "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + cache "k8s.io/client-go/tools/cache" +) + +// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. +type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer + +// SharedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer +} + +// TweakListOptionsFunc is a function that transforms a v1.ListOptions. +type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/pkg/generated/informers/externalversions/provisioning/interface.go b/apps/provisioning/pkg/generated/informers/externalversions/provisioning/interface.go similarity index 78% rename from pkg/generated/informers/externalversions/provisioning/interface.go rename to apps/provisioning/pkg/generated/informers/externalversions/provisioning/interface.go index 851568050e0..7961fd26712 100644 --- a/pkg/generated/informers/externalversions/provisioning/interface.go +++ b/apps/provisioning/pkg/generated/informers/externalversions/provisioning/interface.go @@ -5,8 +5,8 @@ package provisioning import ( - internalinterfaces "github.com/grafana/grafana/pkg/generated/informers/externalversions/internalinterfaces" - v0alpha1 "github.com/grafana/grafana/pkg/generated/informers/externalversions/provisioning/v0alpha1" + internalinterfaces "github.com/grafana/grafana/apps/provisioning/pkg/generated/informers/externalversions/internalinterfaces" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/generated/informers/externalversions/provisioning/v0alpha1" ) // Interface provides access to each of this group's versions. diff --git a/pkg/generated/informers/externalversions/provisioning/v0alpha1/interface.go b/apps/provisioning/pkg/generated/informers/externalversions/provisioning/v0alpha1/interface.go similarity index 88% rename from pkg/generated/informers/externalversions/provisioning/v0alpha1/interface.go rename to apps/provisioning/pkg/generated/informers/externalversions/provisioning/v0alpha1/interface.go index 51060296a02..b358790c61e 100644 --- a/pkg/generated/informers/externalversions/provisioning/v0alpha1/interface.go +++ b/apps/provisioning/pkg/generated/informers/externalversions/provisioning/v0alpha1/interface.go @@ -5,7 +5,7 @@ package v0alpha1 import ( - internalinterfaces "github.com/grafana/grafana/pkg/generated/informers/externalversions/internalinterfaces" + internalinterfaces "github.com/grafana/grafana/apps/provisioning/pkg/generated/informers/externalversions/internalinterfaces" ) // Interface provides access to all the informers in this group version. diff --git a/pkg/generated/informers/externalversions/provisioning/v0alpha1/repository.go b/apps/provisioning/pkg/generated/informers/externalversions/provisioning/v0alpha1/repository.go similarity index 88% rename from pkg/generated/informers/externalversions/provisioning/v0alpha1/repository.go rename to apps/provisioning/pkg/generated/informers/externalversions/provisioning/v0alpha1/repository.go index 58df4bad73d..025ce07d20f 100644 --- a/pkg/generated/informers/externalversions/provisioning/v0alpha1/repository.go +++ b/apps/provisioning/pkg/generated/informers/externalversions/provisioning/v0alpha1/repository.go @@ -8,10 +8,10 @@ import ( context "context" time "time" - apisprovisioningv0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" - versioned "github.com/grafana/grafana/pkg/generated/clientset/versioned" - internalinterfaces "github.com/grafana/grafana/pkg/generated/informers/externalversions/internalinterfaces" - provisioningv0alpha1 "github.com/grafana/grafana/pkg/generated/listers/provisioning/v0alpha1" + apisprovisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + versioned "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned" + internalinterfaces "github.com/grafana/grafana/apps/provisioning/pkg/generated/informers/externalversions/internalinterfaces" + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/generated/listers/provisioning/v0alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/generated/listers/provisioning/v0alpha1/expansion_generated.go b/apps/provisioning/pkg/generated/listers/provisioning/v0alpha1/expansion_generated.go similarity index 100% rename from pkg/generated/listers/provisioning/v0alpha1/expansion_generated.go rename to apps/provisioning/pkg/generated/listers/provisioning/v0alpha1/expansion_generated.go diff --git a/pkg/generated/listers/provisioning/v0alpha1/repository.go b/apps/provisioning/pkg/generated/listers/provisioning/v0alpha1/repository.go similarity index 95% rename from pkg/generated/listers/provisioning/v0alpha1/repository.go rename to apps/provisioning/pkg/generated/listers/provisioning/v0alpha1/repository.go index 969cb034e88..4196743bc1b 100644 --- a/pkg/generated/listers/provisioning/v0alpha1/repository.go +++ b/apps/provisioning/pkg/generated/listers/provisioning/v0alpha1/repository.go @@ -5,7 +5,7 @@ package v0alpha1 import ( - provisioningv0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioningv0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" labels "k8s.io/apimachinery/pkg/labels" listers "k8s.io/client-go/listers" cache "k8s.io/client-go/tools/cache" diff --git a/go.work b/go.work index 2735423d372..a3bb9e88c39 100644 --- a/go.work +++ b/go.work @@ -12,6 +12,7 @@ use ( ./apps/iam ./apps/investigations ./apps/playlist + ./apps/provisioning ./apps/secret ./pkg/aggregator ./pkg/apimachinery diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index aec836f5e3e..2e432ac72e4 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -87,6 +87,7 @@ grafana::codegen:run pkg grafana::codegen:run pkg/apimachinery grafana::codegen:run pkg/aggregator grafana::codegen:run apps/dashboard/pkg +grafana::codegen:run apps/provisioning/pkg grafana::codegen:run apps/folder/pkg if [ -d "pkg/extensions/apis" ]; then diff --git a/pkg/apis/provisioning/v0alpha1/zz_generated.openapi_violation_exceptions.list b/pkg/apis/provisioning/v0alpha1/zz_generated.openapi_violation_exceptions.list deleted file mode 100644 index 49a2170ce4e..00000000000 --- a/pkg/apis/provisioning/v0alpha1/zz_generated.openapi_violation_exceptions.list +++ /dev/null @@ -1,26 +0,0 @@ -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,DeleteJobOptions,Paths -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,DeleteJobOptions,Resources -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,FileList,Items -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,HistoryList,Items -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,JobResourceSummary,Errors -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,JobStatus,Errors -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,JobStatus,Summary -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,ManagerStats,Stats -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,MoveJobOptions,Paths -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,MoveJobOptions,Resources -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,RefList,Items -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,RepositoryList,Items -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,RepositorySpec,Workflows -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,RepositoryView,Workflows -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,RepositoryViewList,AvailableRepositoryTypes -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,RepositoryViewList,Items -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,ResourceList,Items -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,TestResults,Errors -API rule violation: list_type_missing,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,WebhookStatus,SubscribedEvents -API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,JobSpec,PullRequest -API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,ManagerStats,Identity -API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,RepositorySpec,GitHub -API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,RepositorySpec,GitLab -API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,ResourceWrapper,URLs -API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,SyncStatus,JobID -API rule violation: names_match,github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1,WebhookResponse,Message diff --git a/pkg/generated/applyconfiguration/utils.go b/pkg/generated/applyconfiguration/utils.go index a512116f25c..d792c0be680 100644 --- a/pkg/generated/applyconfiguration/utils.go +++ b/pkg/generated/applyconfiguration/utils.go @@ -5,11 +5,9 @@ package applyconfiguration import ( - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" - servicev0alpha1 "github.com/grafana/grafana/pkg/apis/service/v0alpha1" + v0alpha1 "github.com/grafana/grafana/pkg/apis/service/v0alpha1" internal "github.com/grafana/grafana/pkg/generated/applyconfiguration/internal" - provisioningv0alpha1 "github.com/grafana/grafana/pkg/generated/applyconfiguration/provisioning/v0alpha1" - applyconfigurationservicev0alpha1 "github.com/grafana/grafana/pkg/generated/applyconfiguration/service/v0alpha1" + servicev0alpha1 "github.com/grafana/grafana/pkg/generated/applyconfiguration/service/v0alpha1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" testing "k8s.io/client-go/testing" @@ -19,39 +17,11 @@ import ( // apply configuration type exists for the given GroupVersionKind. func ForKind(kind schema.GroupVersionKind) interface{} { switch kind { - // Group=provisioning.grafana.app, Version=v0alpha1 - case v0alpha1.SchemeGroupVersion.WithKind("BitbucketRepositoryConfig"): - return &provisioningv0alpha1.BitbucketRepositoryConfigApplyConfiguration{} - case v0alpha1.SchemeGroupVersion.WithKind("GitHubRepositoryConfig"): - return &provisioningv0alpha1.GitHubRepositoryConfigApplyConfiguration{} - case v0alpha1.SchemeGroupVersion.WithKind("GitLabRepositoryConfig"): - return &provisioningv0alpha1.GitLabRepositoryConfigApplyConfiguration{} - case v0alpha1.SchemeGroupVersion.WithKind("GitRepositoryConfig"): - return &provisioningv0alpha1.GitRepositoryConfigApplyConfiguration{} - case v0alpha1.SchemeGroupVersion.WithKind("HealthStatus"): - return &provisioningv0alpha1.HealthStatusApplyConfiguration{} - case v0alpha1.SchemeGroupVersion.WithKind("LocalRepositoryConfig"): - return &provisioningv0alpha1.LocalRepositoryConfigApplyConfiguration{} - case v0alpha1.SchemeGroupVersion.WithKind("Repository"): - return &provisioningv0alpha1.RepositoryApplyConfiguration{} - case v0alpha1.SchemeGroupVersion.WithKind("RepositorySpec"): - return &provisioningv0alpha1.RepositorySpecApplyConfiguration{} - case v0alpha1.SchemeGroupVersion.WithKind("RepositoryStatus"): - return &provisioningv0alpha1.RepositoryStatusApplyConfiguration{} - case v0alpha1.SchemeGroupVersion.WithKind("ResourceCount"): - return &provisioningv0alpha1.ResourceCountApplyConfiguration{} - case v0alpha1.SchemeGroupVersion.WithKind("SyncOptions"): - return &provisioningv0alpha1.SyncOptionsApplyConfiguration{} - case v0alpha1.SchemeGroupVersion.WithKind("SyncStatus"): - return &provisioningv0alpha1.SyncStatusApplyConfiguration{} - case v0alpha1.SchemeGroupVersion.WithKind("WebhookStatus"): - return &provisioningv0alpha1.WebhookStatusApplyConfiguration{} - - // Group=service.grafana.app, Version=v0alpha1 - case servicev0alpha1.SchemeGroupVersion.WithKind("ExternalName"): - return &applyconfigurationservicev0alpha1.ExternalNameApplyConfiguration{} - case servicev0alpha1.SchemeGroupVersion.WithKind("ExternalNameSpec"): - return &applyconfigurationservicev0alpha1.ExternalNameSpecApplyConfiguration{} + // Group=service.grafana.app, Version=v0alpha1 + case v0alpha1.SchemeGroupVersion.WithKind("ExternalName"): + return &servicev0alpha1.ExternalNameApplyConfiguration{} + case v0alpha1.SchemeGroupVersion.WithKind("ExternalNameSpec"): + return &servicev0alpha1.ExternalNameSpecApplyConfiguration{} } return nil diff --git a/pkg/generated/clientset/versioned/clientset.go b/pkg/generated/clientset/versioned/clientset.go index ad40ccbcfed..972fed70d47 100644 --- a/pkg/generated/clientset/versioned/clientset.go +++ b/pkg/generated/clientset/versioned/clientset.go @@ -8,7 +8,6 @@ import ( fmt "fmt" http "net/http" - provisioningv0alpha1 "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" servicev0alpha1 "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/service/v0alpha1" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" @@ -17,20 +16,13 @@ import ( type Interface interface { Discovery() discovery.DiscoveryInterface - ProvisioningV0alpha1() provisioningv0alpha1.ProvisioningV0alpha1Interface ServiceV0alpha1() servicev0alpha1.ServiceV0alpha1Interface } // Clientset contains the clients for groups. type Clientset struct { *discovery.DiscoveryClient - provisioningV0alpha1 *provisioningv0alpha1.ProvisioningV0alpha1Client - serviceV0alpha1 *servicev0alpha1.ServiceV0alpha1Client -} - -// ProvisioningV0alpha1 retrieves the ProvisioningV0alpha1Client -func (c *Clientset) ProvisioningV0alpha1() provisioningv0alpha1.ProvisioningV0alpha1Interface { - return c.provisioningV0alpha1 + serviceV0alpha1 *servicev0alpha1.ServiceV0alpha1Client } // ServiceV0alpha1 retrieves the ServiceV0alpha1Client @@ -82,10 +74,6 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, var cs Clientset var err error - cs.provisioningV0alpha1, err = provisioningv0alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) - if err != nil { - return nil, err - } cs.serviceV0alpha1, err = servicev0alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) if err != nil { return nil, err @@ -111,7 +99,6 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { // New creates a new Clientset for the given RESTClient. func New(c rest.Interface) *Clientset { var cs Clientset - cs.provisioningV0alpha1 = provisioningv0alpha1.New(c) cs.serviceV0alpha1 = servicev0alpha1.New(c) cs.DiscoveryClient = discovery.NewDiscoveryClient(c) diff --git a/pkg/generated/clientset/versioned/fake/clientset_generated.go b/pkg/generated/clientset/versioned/fake/clientset_generated.go index a68ce76d23c..7b3cf0c1dad 100644 --- a/pkg/generated/clientset/versioned/fake/clientset_generated.go +++ b/pkg/generated/clientset/versioned/fake/clientset_generated.go @@ -7,8 +7,6 @@ package fake import ( applyconfiguration "github.com/grafana/grafana/pkg/generated/applyconfiguration" clientset "github.com/grafana/grafana/pkg/generated/clientset/versioned" - provisioningv0alpha1 "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" - fakeprovisioningv0alpha1 "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake" servicev0alpha1 "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/service/v0alpha1" fakeservicev0alpha1 "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/service/v0alpha1/fake" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -113,11 +111,6 @@ var ( _ testing.FakeClient = &Clientset{} ) -// ProvisioningV0alpha1 retrieves the ProvisioningV0alpha1Client -func (c *Clientset) ProvisioningV0alpha1() provisioningv0alpha1.ProvisioningV0alpha1Interface { - return &fakeprovisioningv0alpha1.FakeProvisioningV0alpha1{Fake: &c.Fake} -} - // ServiceV0alpha1 retrieves the ServiceV0alpha1Client func (c *Clientset) ServiceV0alpha1() servicev0alpha1.ServiceV0alpha1Interface { return &fakeservicev0alpha1.FakeServiceV0alpha1{Fake: &c.Fake} diff --git a/pkg/generated/clientset/versioned/fake/register.go b/pkg/generated/clientset/versioned/fake/register.go index d64a8572697..bbf12658e76 100644 --- a/pkg/generated/clientset/versioned/fake/register.go +++ b/pkg/generated/clientset/versioned/fake/register.go @@ -5,7 +5,6 @@ package fake import ( - provisioningv0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" servicev0alpha1 "github.com/grafana/grafana/pkg/apis/service/v0alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" @@ -18,7 +17,6 @@ var scheme = runtime.NewScheme() var codecs = serializer.NewCodecFactory(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ - provisioningv0alpha1.AddToScheme, servicev0alpha1.AddToScheme, } diff --git a/pkg/generated/clientset/versioned/scheme/register.go b/pkg/generated/clientset/versioned/scheme/register.go index 0aa0fb1be43..dd6e9619160 100644 --- a/pkg/generated/clientset/versioned/scheme/register.go +++ b/pkg/generated/clientset/versioned/scheme/register.go @@ -5,7 +5,6 @@ package scheme import ( - provisioningv0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" servicev0alpha1 "github.com/grafana/grafana/pkg/apis/service/v0alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" @@ -18,7 +17,6 @@ var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) var localSchemeBuilder = runtime.SchemeBuilder{ - provisioningv0alpha1.AddToScheme, servicev0alpha1.AddToScheme, } diff --git a/pkg/generated/informers/externalversions/factory.go b/pkg/generated/informers/externalversions/factory.go index 86ef036dae3..93a498c5d2a 100644 --- a/pkg/generated/informers/externalversions/factory.go +++ b/pkg/generated/informers/externalversions/factory.go @@ -11,7 +11,6 @@ import ( versioned "github.com/grafana/grafana/pkg/generated/clientset/versioned" internalinterfaces "github.com/grafana/grafana/pkg/generated/informers/externalversions/internalinterfaces" - provisioning "github.com/grafana/grafana/pkg/generated/informers/externalversions/provisioning" service "github.com/grafana/grafana/pkg/generated/informers/externalversions/service" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" @@ -241,14 +240,9 @@ type SharedInformerFactory interface { // client. InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer - Provisioning() provisioning.Interface Service() service.Interface } -func (f *sharedInformerFactory) Provisioning() provisioning.Interface { - return provisioning.New(f, f.namespace, f.tweakListOptions) -} - func (f *sharedInformerFactory) Service() service.Interface { return service.New(f, f.namespace, f.tweakListOptions) } diff --git a/pkg/generated/informers/externalversions/generic.go b/pkg/generated/informers/externalversions/generic.go index 676e6b91f8d..9731bd8cbf2 100644 --- a/pkg/generated/informers/externalversions/generic.go +++ b/pkg/generated/informers/externalversions/generic.go @@ -7,8 +7,7 @@ package externalversions import ( fmt "fmt" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" - servicev0alpha1 "github.com/grafana/grafana/pkg/apis/service/v0alpha1" + v0alpha1 "github.com/grafana/grafana/pkg/apis/service/v0alpha1" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" ) @@ -39,12 +38,8 @@ func (f *genericInformer) Lister() cache.GenericLister { // TODO extend this to unknown resources with a client pool func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { - // Group=provisioning.grafana.app, Version=v0alpha1 - case v0alpha1.SchemeGroupVersion.WithResource("repositories"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Provisioning().V0alpha1().Repositories().Informer()}, nil - - // Group=service.grafana.app, Version=v0alpha1 - case servicev0alpha1.SchemeGroupVersion.WithResource("externalnames"): + // Group=service.grafana.app, Version=v0alpha1 + case v0alpha1.SchemeGroupVersion.WithResource("externalnames"): return &genericInformer{resource: resource.GroupResource(), informer: f.Service().V0alpha1().ExternalNames().Informer()}, nil } diff --git a/pkg/registry/apis/provisioning/controller/finalizers.go b/pkg/registry/apis/provisioning/controller/finalizers.go index 554baa86ca9..b30e670a80f 100644 --- a/pkg/registry/apis/provisioning/controller/finalizers.go +++ b/pkg/registry/apis/provisioning/controller/finalizers.go @@ -12,8 +12,8 @@ import ( "github.com/grafana/grafana-app-sdk/logging" folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" ) diff --git a/pkg/registry/apis/provisioning/controller/repository.go b/pkg/registry/apis/provisioning/controller/repository.go index 4b673907e0f..ef5578b1455 100644 --- a/pkg/registry/apis/provisioning/controller/repository.go +++ b/pkg/registry/apis/provisioning/controller/repository.go @@ -17,11 +17,11 @@ import ( "k8s.io/client-go/util/workqueue" "github.com/grafana/grafana-app-sdk/logging" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + client "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" + informer "github.com/grafana/grafana/apps/provisioning/pkg/generated/informers/externalversions/provisioning/v0alpha1" + listers "github.com/grafana/grafana/apps/provisioning/pkg/generated/listers/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/identity" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" - client "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" - informer "github.com/grafana/grafana/pkg/generated/informers/externalversions/provisioning/v0alpha1" - listers "github.com/grafana/grafana/pkg/generated/listers/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" @@ -239,7 +239,7 @@ func (rc *RepositoryController) handleDelete(ctx context.Context, obj *provision Patch(ctx, obj.Name, types.JSONPatchType, []byte(`[ { "op": "remove", "path": "/metadata/finalizers" } ]`), v1.PatchOptions{ - FieldManager: "repository-controller", + FieldManager: "provisioning-controller", }) return err // delete will be called again } diff --git a/pkg/registry/apis/provisioning/controller/status.go b/pkg/registry/apis/provisioning/controller/status.go index 1cbedf57c9b..40ed29624c1 100644 --- a/pkg/registry/apis/provisioning/controller/status.go +++ b/pkg/registry/apis/provisioning/controller/status.go @@ -5,8 +5,8 @@ import ( "encoding/json" "fmt" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" - client "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + client "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ) diff --git a/pkg/registry/apis/provisioning/controller/status_test.go b/pkg/registry/apis/provisioning/controller/status_test.go index 56354c2c165..77e7f737ea5 100644 --- a/pkg/registry/apis/provisioning/controller/status_test.go +++ b/pkg/registry/apis/provisioning/controller/status_test.go @@ -6,8 +6,8 @@ import ( "fmt" "testing" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" - "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1/fake" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/pkg/registry/apis/provisioning/extra.go b/pkg/registry/apis/provisioning/extra.go index 0c5f9e921dd..e7f888a914b 100644 --- a/pkg/registry/apis/provisioning/extra.go +++ b/pkg/registry/apis/provisioning/extra.go @@ -3,7 +3,7 @@ package provisioning import ( "context" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/controller" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" diff --git a/pkg/registry/apis/provisioning/files.go b/pkg/registry/apis/provisioning/files.go index 4dd6604c989..1df860b9738 100644 --- a/pkg/registry/apis/provisioning/files.go +++ b/pkg/registry/apis/provisioning/files.go @@ -12,8 +12,8 @@ import ( authlib "github.com/grafana/authlib/types" "github.com/grafana/grafana-app-sdk/logging" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/identity" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" "github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath" diff --git a/pkg/registry/apis/provisioning/history.go b/pkg/registry/apis/provisioning/history.go index e177295ca23..7770e44fe6d 100644 --- a/pkg/registry/apis/provisioning/history.go +++ b/pkg/registry/apis/provisioning/history.go @@ -11,7 +11,7 @@ import ( "k8s.io/apiserver/pkg/registry/rest" "github.com/grafana/grafana-app-sdk/logging" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath" ) diff --git a/pkg/registry/apis/provisioning/jobs.go b/pkg/registry/apis/provisioning/jobs.go index d19dd61722c..e563cc94fa9 100644 --- a/pkg/registry/apis/provisioning/jobs.go +++ b/pkg/registry/apis/provisioning/jobs.go @@ -11,7 +11,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/rest" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" ) diff --git a/pkg/registry/apis/provisioning/jobs/delete/worker.go b/pkg/registry/apis/provisioning/jobs/delete/worker.go index c1f6739405e..63db00ef224 100644 --- a/pkg/registry/apis/provisioning/jobs/delete/worker.go +++ b/pkg/registry/apis/provisioning/jobs/delete/worker.go @@ -8,7 +8,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/delete/worker_test.go b/pkg/registry/apis/provisioning/jobs/delete/worker_test.go index 5d63687dd2c..7f2fa3c22bb 100644 --- a/pkg/registry/apis/provisioning/jobs/delete/worker_test.go +++ b/pkg/registry/apis/provisioning/jobs/delete/worker_test.go @@ -9,7 +9,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/driver.go b/pkg/registry/apis/provisioning/jobs/driver.go index 8d31d1dde1a..988422aacff 100644 --- a/pkg/registry/apis/provisioning/jobs/driver.go +++ b/pkg/registry/apis/provisioning/jobs/driver.go @@ -9,8 +9,8 @@ import ( "k8s.io/apiserver/pkg/endpoints/request" "github.com/grafana/grafana-app-sdk/logging" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/identity" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/apifmt" ) diff --git a/pkg/registry/apis/provisioning/jobs/export/all.go b/pkg/registry/apis/provisioning/jobs/export/all.go index 1010c02f630..c2cb0f85eb5 100644 --- a/pkg/registry/apis/provisioning/jobs/export/all.go +++ b/pkg/registry/apis/provisioning/jobs/export/all.go @@ -3,7 +3,7 @@ package export import ( "context" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" ) diff --git a/pkg/registry/apis/provisioning/jobs/export/folders.go b/pkg/registry/apis/provisioning/jobs/export/folders.go index c8b108d6023..48a4f7839ae 100644 --- a/pkg/registry/apis/provisioning/jobs/export/folders.go +++ b/pkg/registry/apis/provisioning/jobs/export/folders.go @@ -8,8 +8,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/client-go/dynamic" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/export/folders_test.go b/pkg/registry/apis/provisioning/jobs/export/folders_test.go index 49c07a64347..2eaeeabd373 100644 --- a/pkg/registry/apis/provisioning/jobs/export/folders_test.go +++ b/pkg/registry/apis/provisioning/jobs/export/folders_test.go @@ -6,8 +6,8 @@ import ( "fmt" "testing" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/utils" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/export/mock_export_fn.go b/pkg/registry/apis/provisioning/jobs/export/mock_export_fn.go index e861e7da3c3..e748228da2b 100644 --- a/pkg/registry/apis/provisioning/jobs/export/mock_export_fn.go +++ b/pkg/registry/apis/provisioning/jobs/export/mock_export_fn.go @@ -10,7 +10,7 @@ import ( resources "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockExportFn is an autogenerated mock type for the ExportFn type diff --git a/pkg/registry/apis/provisioning/jobs/export/resources.go b/pkg/registry/apis/provisioning/jobs/export/resources.go index 54805784cee..8b1baff08ca 100644 --- a/pkg/registry/apis/provisioning/jobs/export/resources.go +++ b/pkg/registry/apis/provisioning/jobs/export/resources.go @@ -10,8 +10,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/client-go/dynamic" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/export/resources_test.go b/pkg/registry/apis/provisioning/jobs/export/resources_test.go index e77ae6105ed..8be32cebed9 100644 --- a/pkg/registry/apis/provisioning/jobs/export/resources_test.go +++ b/pkg/registry/apis/provisioning/jobs/export/resources_test.go @@ -11,7 +11,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" - provisioningV0 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioningV0 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/export/worker.go b/pkg/registry/apis/provisioning/jobs/export/worker.go index 13536a62aa5..524b01dce4c 100644 --- a/pkg/registry/apis/provisioning/jobs/export/worker.go +++ b/pkg/registry/apis/provisioning/jobs/export/worker.go @@ -6,7 +6,7 @@ import ( "fmt" "time" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/export/worker_test.go b/pkg/registry/apis/provisioning/jobs/export/worker_test.go index 930b5f051a9..d78b0ec5b8b 100644 --- a/pkg/registry/apis/provisioning/jobs/export/worker_test.go +++ b/pkg/registry/apis/provisioning/jobs/export/worker_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/history.go b/pkg/registry/apis/provisioning/jobs/history.go index 88351e12bad..0a7897319f9 100644 --- a/pkg/registry/apis/provisioning/jobs/history.go +++ b/pkg/registry/apis/provisioning/jobs/history.go @@ -7,7 +7,7 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // History keeps track of completed jobs diff --git a/pkg/registry/apis/provisioning/jobs/history_mock.go b/pkg/registry/apis/provisioning/jobs/history_mock.go index dbb61568566..f6697d33bcf 100644 --- a/pkg/registry/apis/provisioning/jobs/history_mock.go +++ b/pkg/registry/apis/provisioning/jobs/history_mock.go @@ -5,7 +5,7 @@ package jobs import ( context "context" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" mock "github.com/stretchr/testify/mock" ) diff --git a/pkg/registry/apis/provisioning/jobs/job_progress_recorder_mock.go b/pkg/registry/apis/provisioning/jobs/job_progress_recorder_mock.go index 54b07e6a38a..be0b6d3d9b0 100644 --- a/pkg/registry/apis/provisioning/jobs/job_progress_recorder_mock.go +++ b/pkg/registry/apis/provisioning/jobs/job_progress_recorder_mock.go @@ -5,7 +5,7 @@ package jobs import ( context "context" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" mock "github.com/stretchr/testify/mock" ) diff --git a/pkg/registry/apis/provisioning/jobs/migrate/legacy.go b/pkg/registry/apis/provisioning/jobs/migrate/legacy.go index 8b253bebd7f..929c7a6b9cf 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/legacy.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/legacy.go @@ -7,7 +7,7 @@ import ( "time" "github.com/grafana/grafana-app-sdk/logging" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/jobs/migrate/legacy_resources.go b/pkg/registry/apis/provisioning/jobs/migrate/legacy_resources.go index 34391f3e56f..03711c485d6 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/legacy_resources.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/legacy_resources.go @@ -6,8 +6,8 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/dashboard/legacy" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs/export" diff --git a/pkg/registry/apis/provisioning/jobs/migrate/legacy_resources_test.go b/pkg/registry/apis/provisioning/jobs/migrate/legacy_resources_test.go index aff308a4a9b..88e60341f6b 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/legacy_resources_test.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/legacy_resources_test.go @@ -13,8 +13,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/dashboard/legacy" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs/export" diff --git a/pkg/registry/apis/provisioning/jobs/migrate/legacy_test.go b/pkg/registry/apis/provisioning/jobs/migrate/legacy_test.go index 3b25de7aeaf..319984391d6 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/legacy_test.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/legacy_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/jobs/migrate/mock_legacy_resources_migrator.go b/pkg/registry/apis/provisioning/jobs/migrate/mock_legacy_resources_migrator.go index 4a0d27fafb5..4e70afef693 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/mock_legacy_resources_migrator.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/mock_legacy_resources_migrator.go @@ -10,7 +10,7 @@ import ( repository "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockLegacyResourcesMigrator is an autogenerated mock type for the LegacyResourcesMigrator type diff --git a/pkg/registry/apis/provisioning/jobs/migrate/mock_migrator.go b/pkg/registry/apis/provisioning/jobs/migrate/mock_migrator.go index 0128ce741f4..685c5ab7c47 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/mock_migrator.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/mock_migrator.go @@ -10,7 +10,7 @@ import ( repository "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockMigrator is an autogenerated mock type for the Migrator type diff --git a/pkg/registry/apis/provisioning/jobs/migrate/unifiedstorage.go b/pkg/registry/apis/provisioning/jobs/migrate/unifiedstorage.go index 4f9f33b96ec..aa6ce0b596d 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/unifiedstorage.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/unifiedstorage.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/jobs/migrate/unifiedstorage_test.go b/pkg/registry/apis/provisioning/jobs/migrate/unifiedstorage_test.go index 3cb48119842..5bc028f138d 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/unifiedstorage_test.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/unifiedstorage_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/registry/apis/provisioning/jobs/migrate/worker.go b/pkg/registry/apis/provisioning/jobs/migrate/worker.go index 625b49ea32c..1293f18afa4 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/worker.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/worker.go @@ -4,7 +4,7 @@ import ( "context" "errors" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/storage/legacysql/dualwrite" diff --git a/pkg/registry/apis/provisioning/jobs/migrate/worker_test.go b/pkg/registry/apis/provisioning/jobs/migrate/worker_test.go index e7d8c7c6175..3993b422492 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/worker_test.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/worker_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository/local" diff --git a/pkg/registry/apis/provisioning/jobs/move/worker.go b/pkg/registry/apis/provisioning/jobs/move/worker.go index 5c2bba7e4e4..b2ff1912bd5 100644 --- a/pkg/registry/apis/provisioning/jobs/move/worker.go +++ b/pkg/registry/apis/provisioning/jobs/move/worker.go @@ -9,7 +9,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/move/worker_test.go b/pkg/registry/apis/provisioning/jobs/move/worker_test.go index 3be6d2d4619..c398cedc830 100644 --- a/pkg/registry/apis/provisioning/jobs/move/worker_test.go +++ b/pkg/registry/apis/provisioning/jobs/move/worker_test.go @@ -11,7 +11,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/persistentstore.go b/pkg/registry/apis/provisioning/jobs/persistentstore.go index abfdf2cecc7..e172e106ecf 100644 --- a/pkg/registry/apis/provisioning/jobs/persistentstore.go +++ b/pkg/registry/apis/provisioning/jobs/persistentstore.go @@ -18,8 +18,8 @@ import ( "k8s.io/apiserver/pkg/registry/rest" "github.com/grafana/grafana-app-sdk/logging" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/identity" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/apifmt" ) diff --git a/pkg/registry/apis/provisioning/jobs/progress.go b/pkg/registry/apis/provisioning/jobs/progress.go index 081ac9a3b86..4f7bb2ad53d 100644 --- a/pkg/registry/apis/provisioning/jobs/progress.go +++ b/pkg/registry/apis/provisioning/jobs/progress.go @@ -7,7 +7,7 @@ import ( "time" "github.com/grafana/grafana-app-sdk/logging" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/jobs/progress_fn_mock.go b/pkg/registry/apis/provisioning/jobs/progress_fn_mock.go index fd634d60844..8c68bec33f7 100644 --- a/pkg/registry/apis/provisioning/jobs/progress_fn_mock.go +++ b/pkg/registry/apis/provisioning/jobs/progress_fn_mock.go @@ -5,7 +5,7 @@ package jobs import ( context "context" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" mock "github.com/stretchr/testify/mock" ) diff --git a/pkg/registry/apis/provisioning/jobs/queue.go b/pkg/registry/apis/provisioning/jobs/queue.go index 32b935e4be8..3a9757d93a1 100644 --- a/pkg/registry/apis/provisioning/jobs/queue.go +++ b/pkg/registry/apis/provisioning/jobs/queue.go @@ -3,7 +3,7 @@ package jobs import ( "context" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/jobs/queue_mock.go b/pkg/registry/apis/provisioning/jobs/queue_mock.go index 41552749cad..37fd66f214b 100644 --- a/pkg/registry/apis/provisioning/jobs/queue_mock.go +++ b/pkg/registry/apis/provisioning/jobs/queue_mock.go @@ -5,7 +5,7 @@ package jobs import ( context "context" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" mock "github.com/stretchr/testify/mock" ) diff --git a/pkg/registry/apis/provisioning/jobs/store_mock.go b/pkg/registry/apis/provisioning/jobs/store_mock.go index 8a6bb364f80..114a621561e 100644 --- a/pkg/registry/apis/provisioning/jobs/store_mock.go +++ b/pkg/registry/apis/provisioning/jobs/store_mock.go @@ -5,7 +5,7 @@ package jobs import ( context "context" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" mock "github.com/stretchr/testify/mock" ) diff --git a/pkg/registry/apis/provisioning/jobs/sync/changes.go b/pkg/registry/apis/provisioning/jobs/sync/changes.go index 4c1f5db9136..4555e670a47 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/changes.go +++ b/pkg/registry/apis/provisioning/jobs/sync/changes.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" "github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath" diff --git a/pkg/registry/apis/provisioning/jobs/sync/changes_test.go b/pkg/registry/apis/provisioning/jobs/sync/changes_test.go index d2a31696688..d14e9f0c872 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/changes_test.go +++ b/pkg/registry/apis/provisioning/jobs/sync/changes_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" ) diff --git a/pkg/registry/apis/provisioning/jobs/sync/full_test.go b/pkg/registry/apis/provisioning/jobs/sync/full_test.go index 7524fe27f2a..3885700b331 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/full_test.go +++ b/pkg/registry/apis/provisioning/jobs/sync/full_test.go @@ -6,7 +6,7 @@ import ( "fmt" "testing" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/sync/repository_patch_fn_mock.go b/pkg/registry/apis/provisioning/jobs/sync/repository_patch_fn_mock.go index fb44f7eda29..97a5c70c05b 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/repository_patch_fn_mock.go +++ b/pkg/registry/apis/provisioning/jobs/sync/repository_patch_fn_mock.go @@ -5,7 +5,7 @@ package sync import ( context "context" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" mock "github.com/stretchr/testify/mock" ) diff --git a/pkg/registry/apis/provisioning/jobs/sync/sync.go b/pkg/registry/apis/provisioning/jobs/sync/sync.go index 9aca33ebcd3..a82423ecbd7 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/sync.go +++ b/pkg/registry/apis/provisioning/jobs/sync/sync.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/sync/sync_test.go b/pkg/registry/apis/provisioning/jobs/sync/sync_test.go index f7bb4e0c961..c0398925b04 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/sync_test.go +++ b/pkg/registry/apis/provisioning/jobs/sync/sync_test.go @@ -5,7 +5,7 @@ import ( "fmt" "testing" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/sync/syncer_mock.go b/pkg/registry/apis/provisioning/jobs/sync/syncer_mock.go index 3eb3e4de7bb..0dedab34cc1 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/syncer_mock.go +++ b/pkg/registry/apis/provisioning/jobs/sync/syncer_mock.go @@ -12,7 +12,7 @@ import ( resources "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockSyncer is an autogenerated mock type for the Syncer type diff --git a/pkg/registry/apis/provisioning/jobs/sync/worker.go b/pkg/registry/apis/provisioning/jobs/sync/worker.go index 5b8eb701b34..66e96673051 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/worker.go +++ b/pkg/registry/apis/provisioning/jobs/sync/worker.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/grafana/grafana-app-sdk/logging" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/sync/worker_test.go b/pkg/registry/apis/provisioning/jobs/sync/worker_test.go index 02e152afb6a..5b8bf67166f 100644 --- a/pkg/registry/apis/provisioning/jobs/sync/worker_test.go +++ b/pkg/registry/apis/provisioning/jobs/sync/worker_test.go @@ -5,7 +5,7 @@ import ( "errors" "testing" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/jobs/worker_mock.go b/pkg/registry/apis/provisioning/jobs/worker_mock.go index b264b258d1c..60a710016d5 100644 --- a/pkg/registry/apis/provisioning/jobs/worker_mock.go +++ b/pkg/registry/apis/provisioning/jobs/worker_mock.go @@ -8,7 +8,7 @@ import ( repository "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" mock "github.com/stretchr/testify/mock" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockWorker is an autogenerated mock type for the Worker type diff --git a/pkg/registry/apis/provisioning/list.go b/pkg/registry/apis/provisioning/list.go index 202a063736f..ddd851b1bb7 100644 --- a/pkg/registry/apis/provisioning/list.go +++ b/pkg/registry/apis/provisioning/list.go @@ -10,7 +10,7 @@ import ( "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" ) diff --git a/pkg/registry/apis/provisioning/refs.go b/pkg/registry/apis/provisioning/refs.go index 47fe2b24324..8eed640fdd1 100644 --- a/pkg/registry/apis/provisioning/refs.go +++ b/pkg/registry/apis/provisioning/refs.go @@ -9,7 +9,7 @@ import ( "k8s.io/apiserver/pkg/registry/rest" "github.com/grafana/grafana-app-sdk/logging" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/register.go b/pkg/registry/apis/provisioning/register.go index 9bccd675dd5..48656eba416 100644 --- a/pkg/registry/apis/provisioning/register.go +++ b/pkg/registry/apis/provisioning/register.go @@ -29,15 +29,15 @@ import ( "github.com/grafana/grafana-app-sdk/logging" dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1" folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + clientset "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned" + client "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" + informers "github.com/grafana/grafana/apps/provisioning/pkg/generated/informers/externalversions" + listers "github.com/grafana/grafana/apps/provisioning/pkg/generated/listers/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/identity" apiutils "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apiserver/readonly" grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic" - clientset "github.com/grafana/grafana/pkg/generated/clientset/versioned" - client "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" - informers "github.com/grafana/grafana/pkg/generated/informers/externalversions" - listers "github.com/grafana/grafana/pkg/generated/listers/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/registry/apis/dashboard/legacy" @@ -680,7 +680,7 @@ func (b *APIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.OpenAPI, err repoprefix := root + "namespaces/{namespace}/repositories/{name}" defs := b.GetOpenAPIDefinitions()(func(path string) spec.Ref { return spec.Ref{} }) - defsBase := "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1." + defsBase := "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1." refsBase := "com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1." sub := oas.Paths.Paths[repoprefix+"/test"] diff --git a/pkg/registry/apis/provisioning/repository/config_repository_mock.go b/pkg/registry/apis/provisioning/repository/config_repository_mock.go index 40ea3dcd3de..38d2f4617ca 100644 --- a/pkg/registry/apis/provisioning/repository/config_repository_mock.go +++ b/pkg/registry/apis/provisioning/repository/config_repository_mock.go @@ -8,7 +8,7 @@ import ( mock "github.com/stretchr/testify/mock" field "k8s.io/apimachinery/pkg/util/validation/field" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockConfigRepository is an autogenerated mock type for the Repository type diff --git a/pkg/registry/apis/provisioning/repository/git/git_repository_mock.go b/pkg/registry/apis/provisioning/repository/git/git_repository_mock.go index 4b914b50f19..81b4eecf671 100644 --- a/pkg/registry/apis/provisioning/repository/git/git_repository_mock.go +++ b/pkg/registry/apis/provisioning/repository/git/git_repository_mock.go @@ -10,7 +10,7 @@ import ( repository "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockGitRepository is an autogenerated mock type for the GitRepository type diff --git a/pkg/registry/apis/provisioning/repository/git/mutator.go b/pkg/registry/apis/provisioning/repository/git/mutator.go index e68940fafb8..c4eded27f44 100644 --- a/pkg/registry/apis/provisioning/repository/git/mutator.go +++ b/pkg/registry/apis/provisioning/repository/git/mutator.go @@ -7,7 +7,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/controller" "github.com/grafana/grafana/pkg/registry/apis/provisioning/secrets" ) diff --git a/pkg/registry/apis/provisioning/repository/git/mutator_test.go b/pkg/registry/apis/provisioning/repository/git/mutator_test.go index 87196d6bcb0..de52ab0c0f6 100644 --- a/pkg/registry/apis/provisioning/repository/git/mutator_test.go +++ b/pkg/registry/apis/provisioning/repository/git/mutator_test.go @@ -5,7 +5,7 @@ import ( "errors" "testing" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/secrets" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/registry/apis/provisioning/repository/git/repository.go b/pkg/registry/apis/provisioning/repository/git/repository.go index 7ca9ed8998e..41c3a328788 100644 --- a/pkg/registry/apis/provisioning/repository/git/repository.go +++ b/pkg/registry/apis/provisioning/repository/git/repository.go @@ -16,7 +16,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" "github.com/grafana/grafana-app-sdk/logging" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath" "github.com/grafana/grafana/pkg/registry/apis/provisioning/secrets" diff --git a/pkg/registry/apis/provisioning/repository/git/repository_test.go b/pkg/registry/apis/provisioning/repository/git/repository_test.go index f70346825f6..4236352f94c 100644 --- a/pkg/registry/apis/provisioning/repository/git/repository_test.go +++ b/pkg/registry/apis/provisioning/repository/git/repository_test.go @@ -12,7 +12,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/validation/field" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/secrets" "github.com/grafana/nanogit" diff --git a/pkg/registry/apis/provisioning/repository/git/staged_test.go b/pkg/registry/apis/provisioning/repository/git/staged_test.go index 77c1d8b5edb..2b18fd3445f 100644 --- a/pkg/registry/apis/provisioning/repository/git/staged_test.go +++ b/pkg/registry/apis/provisioning/repository/git/staged_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/nanogit" "github.com/grafana/nanogit/mocks" diff --git a/pkg/registry/apis/provisioning/repository/github/github_repository_mock.go b/pkg/registry/apis/provisioning/repository/github/github_repository_mock.go index 5ccd5d2e319..7b5509935f1 100644 --- a/pkg/registry/apis/provisioning/repository/github/github_repository_mock.go +++ b/pkg/registry/apis/provisioning/repository/github/github_repository_mock.go @@ -10,7 +10,7 @@ import ( repository "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockGithubRepository is an autogenerated mock type for the GithubRepository type diff --git a/pkg/registry/apis/provisioning/repository/github/mutator.go b/pkg/registry/apis/provisioning/repository/github/mutator.go index 4aec95aa7d6..b0ee0e54a24 100644 --- a/pkg/registry/apis/provisioning/repository/github/mutator.go +++ b/pkg/registry/apis/provisioning/repository/github/mutator.go @@ -6,7 +6,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/controller" "github.com/grafana/grafana/pkg/registry/apis/provisioning/secrets" ) diff --git a/pkg/registry/apis/provisioning/repository/github/mutator_test.go b/pkg/registry/apis/provisioning/repository/github/mutator_test.go index a6bbbe22c11..5094ed07206 100644 --- a/pkg/registry/apis/provisioning/repository/github/mutator_test.go +++ b/pkg/registry/apis/provisioning/repository/github/mutator_test.go @@ -5,7 +5,7 @@ import ( "errors" "testing" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/secrets" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/registry/apis/provisioning/repository/github/repository.go b/pkg/registry/apis/provisioning/repository/github/repository.go index d2da1de41d1..ac95e54312f 100644 --- a/pkg/registry/apis/provisioning/repository/github/repository.go +++ b/pkg/registry/apis/provisioning/repository/github/repository.go @@ -10,7 +10,7 @@ import ( "github.com/grafana/grafana-app-sdk/logging" "k8s.io/apimachinery/pkg/util/validation/field" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository/git" "github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath" diff --git a/pkg/registry/apis/provisioning/repository/github/repository_test.go b/pkg/registry/apis/provisioning/repository/github/repository_test.go index 962a7a4e2b1..3a11127e9da 100644 --- a/pkg/registry/apis/provisioning/repository/github/repository_test.go +++ b/pkg/registry/apis/provisioning/repository/github/repository_test.go @@ -14,7 +14,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" field "k8s.io/apimachinery/pkg/util/validation/field" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository/git" "github.com/grafana/grafana/pkg/registry/apis/provisioning/secrets" diff --git a/pkg/registry/apis/provisioning/repository/local/local.go b/pkg/registry/apis/provisioning/repository/local/local.go index 0ab620e6639..98413cc1094 100644 --- a/pkg/registry/apis/provisioning/repository/local/local.go +++ b/pkg/registry/apis/provisioning/repository/local/local.go @@ -22,7 +22,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath" ) diff --git a/pkg/registry/apis/provisioning/repository/local/local_test.go b/pkg/registry/apis/provisioning/repository/local/local_test.go index 77a0b99fa09..378a3170478 100644 --- a/pkg/registry/apis/provisioning/repository/local/local_test.go +++ b/pkg/registry/apis/provisioning/repository/local/local_test.go @@ -18,7 +18,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" field "k8s.io/apimachinery/pkg/util/validation/field" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/repository/reader_mock.go b/pkg/registry/apis/provisioning/repository/reader_mock.go index dd6a73ab567..c7f56f5847c 100644 --- a/pkg/registry/apis/provisioning/repository/reader_mock.go +++ b/pkg/registry/apis/provisioning/repository/reader_mock.go @@ -8,7 +8,7 @@ import ( mock "github.com/stretchr/testify/mock" field "k8s.io/apimachinery/pkg/util/validation/field" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockReader is an autogenerated mock type for the Reader type diff --git a/pkg/registry/apis/provisioning/repository/repository.go b/pkg/registry/apis/provisioning/repository/repository.go index 718660c9fab..5608366060b 100644 --- a/pkg/registry/apis/provisioning/repository/repository.go +++ b/pkg/registry/apis/provisioning/repository/repository.go @@ -8,7 +8,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/validation/field" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // FIXME: the name of the mock is different because there is another generated mock for Repository diff --git a/pkg/registry/apis/provisioning/repository/repository_mock.go b/pkg/registry/apis/provisioning/repository/repository_mock.go index 05fc5a3832a..e78a7467884 100644 --- a/pkg/registry/apis/provisioning/repository/repository_mock.go +++ b/pkg/registry/apis/provisioning/repository/repository_mock.go @@ -10,7 +10,7 @@ import ( mock "github.com/stretchr/testify/mock" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockRepository is an autogenerated mock type for the Repository type diff --git a/pkg/registry/apis/provisioning/repository/staged_repository_mock.go b/pkg/registry/apis/provisioning/repository/staged_repository_mock.go index 85bfb4f3012..bd5b8785326 100644 --- a/pkg/registry/apis/provisioning/repository/staged_repository_mock.go +++ b/pkg/registry/apis/provisioning/repository/staged_repository_mock.go @@ -8,7 +8,7 @@ import ( mock "github.com/stretchr/testify/mock" field "k8s.io/apimachinery/pkg/util/validation/field" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockStagedRepository is an autogenerated mock type for the StagedRepository type diff --git a/pkg/registry/apis/provisioning/repository/test.go b/pkg/registry/apis/provisioning/repository/test.go index f8b72d5b2af..403ac24fa38 100644 --- a/pkg/registry/apis/provisioning/repository/test.go +++ b/pkg/registry/apis/provisioning/repository/test.go @@ -9,7 +9,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/validation/field" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // Tester is a struct that implements the Tester interface diff --git a/pkg/registry/apis/provisioning/repository/test_test.go b/pkg/registry/apis/provisioning/repository/test_test.go index 9168d529ea0..56d73e13a90 100644 --- a/pkg/registry/apis/provisioning/repository/test_test.go +++ b/pkg/registry/apis/provisioning/repository/test_test.go @@ -11,7 +11,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/validation/field" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) func TestValidateRepository(t *testing.T) { diff --git a/pkg/registry/apis/provisioning/repository/versioned_mock.go b/pkg/registry/apis/provisioning/repository/versioned_mock.go index dc711f10f30..36ef2fe9a96 100644 --- a/pkg/registry/apis/provisioning/repository/versioned_mock.go +++ b/pkg/registry/apis/provisioning/repository/versioned_mock.go @@ -5,7 +5,7 @@ package repository import ( context "context" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" mock "github.com/stretchr/testify/mock" ) diff --git a/pkg/registry/apis/provisioning/repository/workflows.go b/pkg/registry/apis/provisioning/repository/workflows.go index 9750bde0962..48ba1319a62 100644 --- a/pkg/registry/apis/provisioning/repository/workflows.go +++ b/pkg/registry/apis/provisioning/repository/workflows.go @@ -3,7 +3,7 @@ package repository import ( apierrors "k8s.io/apimachinery/pkg/api/errors" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) func IsWriteAllowed(repo *provisioning.Repository, ref string) error { diff --git a/pkg/registry/apis/provisioning/repository/workflows_test.go b/pkg/registry/apis/provisioning/repository/workflows_test.go index 6f2e337494d..995c85e0eb5 100644 --- a/pkg/registry/apis/provisioning/repository/workflows_test.go +++ b/pkg/registry/apis/provisioning/repository/workflows_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" apierrors "k8s.io/apimachinery/pkg/api/errors" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) func TestIsWriteAllowed(t *testing.T) { diff --git a/pkg/registry/apis/provisioning/resources/dualwriter.go b/pkg/registry/apis/provisioning/resources/dualwriter.go index 50efaa13048..78042c35a12 100644 --- a/pkg/registry/apis/provisioning/resources/dualwriter.go +++ b/pkg/registry/apis/provisioning/resources/dualwriter.go @@ -10,10 +10,10 @@ import ( authlib "github.com/grafana/authlib/types" "github.com/grafana/grafana-app-sdk/logging" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath" ) diff --git a/pkg/registry/apis/provisioning/resources/fileformat.go b/pkg/registry/apis/provisioning/resources/fileformat.go index 0ed0b287199..b35afd74781 100644 --- a/pkg/registry/apis/provisioning/resources/fileformat.go +++ b/pkg/registry/apis/provisioning/resources/fileformat.go @@ -14,7 +14,7 @@ import ( "github.com/grafana/grafana-app-sdk/logging" dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/resources/fileformat_test.go b/pkg/registry/apis/provisioning/resources/fileformat_test.go index 611578abb45..3013927edc9 100644 --- a/pkg/registry/apis/provisioning/resources/fileformat_test.go +++ b/pkg/registry/apis/provisioning/resources/fileformat_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/runtime/schema" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/resources/id.go b/pkg/registry/apis/provisioning/resources/id.go index b32355b4b5f..2ffaa0cc5bc 100644 --- a/pkg/registry/apis/provisioning/resources/id.go +++ b/pkg/registry/apis/provisioning/resources/id.go @@ -5,7 +5,7 @@ import ( "encoding/base64" "strings" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath" ) diff --git a/pkg/registry/apis/provisioning/resources/object.go b/pkg/registry/apis/provisioning/resources/object.go index 9faa4412fce..a30694417bb 100644 --- a/pkg/registry/apis/provisioning/resources/object.go +++ b/pkg/registry/apis/provisioning/resources/object.go @@ -8,8 +8,8 @@ import ( dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1" folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/dashboard/legacy" "github.com/grafana/grafana/pkg/storage/legacysql/dualwrite" "github.com/grafana/grafana/pkg/storage/unified/resource" diff --git a/pkg/registry/apis/provisioning/resources/parser.go b/pkg/registry/apis/provisioning/resources/parser.go index 352e92fa27a..2b3f0c2deac 100644 --- a/pkg/registry/apis/provisioning/resources/parser.go +++ b/pkg/registry/apis/provisioning/resources/parser.go @@ -16,10 +16,10 @@ import ( "github.com/grafana/grafana-app-sdk/logging" dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath" "github.com/grafana/grafana/pkg/util" diff --git a/pkg/registry/apis/provisioning/resources/parser_test.go b/pkg/registry/apis/provisioning/resources/parser_test.go index d718445fc57..61f374a8e05 100644 --- a/pkg/registry/apis/provisioning/resources/parser_test.go +++ b/pkg/registry/apis/provisioning/resources/parser_test.go @@ -9,7 +9,7 @@ import ( dashboardV0 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1" dashboardV1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/resources/repository.go b/pkg/registry/apis/provisioning/resources/repository.go index d12747b7bc8..12747b9834d 100644 --- a/pkg/registry/apis/provisioning/resources/repository.go +++ b/pkg/registry/apis/provisioning/resources/repository.go @@ -9,8 +9,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath" ) diff --git a/pkg/registry/apis/provisioning/resources/repository_resources_mock.go b/pkg/registry/apis/provisioning/resources/repository_resources_mock.go index 9ff7171f68c..978d91f1d4d 100644 --- a/pkg/registry/apis/provisioning/resources/repository_resources_mock.go +++ b/pkg/registry/apis/provisioning/resources/repository_resources_mock.go @@ -10,7 +10,7 @@ import ( unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockRepositoryResources is an autogenerated mock type for the RepositoryResources type diff --git a/pkg/registry/apis/provisioning/resources/resource_lister_mock.go b/pkg/registry/apis/provisioning/resources/resource_lister_mock.go index 29fb1712f51..2bf441cd93d 100644 --- a/pkg/registry/apis/provisioning/resources/resource_lister_mock.go +++ b/pkg/registry/apis/provisioning/resources/resource_lister_mock.go @@ -5,7 +5,7 @@ package resources import ( context "context" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" mock "github.com/stretchr/testify/mock" ) diff --git a/pkg/registry/apis/provisioning/resources/tree.go b/pkg/registry/apis/provisioning/resources/tree.go index 427384e8753..ce92f104b8b 100644 --- a/pkg/registry/apis/provisioning/resources/tree.go +++ b/pkg/registry/apis/provisioning/resources/tree.go @@ -7,8 +7,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/safepath" ) diff --git a/pkg/registry/apis/provisioning/routes.go b/pkg/registry/apis/provisioning/routes.go index 5e222882bd0..749c4a8d2ed 100644 --- a/pkg/registry/apis/provisioning/routes.go +++ b/pkg/registry/apis/provisioning/routes.go @@ -12,7 +12,7 @@ import ( "k8s.io/kube-openapi/pkg/validation/spec" authlib "github.com/grafana/authlib/types" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/services/apiserver/builder" "github.com/grafana/grafana/pkg/storage/legacysql/dualwrite" "github.com/grafana/grafana/pkg/util/errhttp" diff --git a/pkg/registry/apis/provisioning/secrets/repository.go b/pkg/registry/apis/provisioning/secrets/repository.go index 29a470dd993..09ba78e1389 100644 --- a/pkg/registry/apis/provisioning/secrets/repository.go +++ b/pkg/registry/apis/provisioning/secrets/repository.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/grafana/grafana-app-sdk/logging" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/secret" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/services/featuremgmt" diff --git a/pkg/registry/apis/provisioning/secrets/repository_secrets_mock.go b/pkg/registry/apis/provisioning/secrets/repository_secrets_mock.go index 763422ef7c5..7108be570f2 100644 --- a/pkg/registry/apis/provisioning/secrets/repository_secrets_mock.go +++ b/pkg/registry/apis/provisioning/secrets/repository_secrets_mock.go @@ -5,7 +5,7 @@ package secrets import ( context "context" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" mock "github.com/stretchr/testify/mock" ) diff --git a/pkg/registry/apis/provisioning/secrets/repository_test.go b/pkg/registry/apis/provisioning/secrets/repository_test.go index 028efd10853..bd53089fc75 100644 --- a/pkg/registry/apis/provisioning/secrets/repository_test.go +++ b/pkg/registry/apis/provisioning/secrets/repository_test.go @@ -5,7 +5,7 @@ import ( "errors" "testing" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/stretchr/testify/assert" diff --git a/pkg/registry/apis/provisioning/test.go b/pkg/registry/apis/provisioning/test.go index 9813c37a0ad..9abb1d38a7f 100644 --- a/pkg/registry/apis/provisioning/test.go +++ b/pkg/registry/apis/provisioning/test.go @@ -13,8 +13,8 @@ import ( "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" - client "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + client "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/types.go b/pkg/registry/apis/provisioning/types.go index d804643cd21..8c030b652e1 100644 --- a/pkg/registry/apis/provisioning/types.go +++ b/pkg/registry/apis/provisioning/types.go @@ -3,8 +3,8 @@ package provisioning import ( "context" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" - client "github.com/grafana/grafana/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" + client "github.com/grafana/grafana/apps/provisioning/pkg/generated/clientset/versioned/typed/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/usage/usage.go b/pkg/registry/apis/provisioning/usage/usage.go index 485c9fe19e4..b9a1ed938c9 100644 --- a/pkg/registry/apis/provisioning/usage/usage.go +++ b/pkg/registry/apis/provisioning/usage/usage.go @@ -9,8 +9,8 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apiserver/pkg/endpoints/request" + listers "github.com/grafana/grafana/apps/provisioning/pkg/generated/listers/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/identity" - listers "github.com/grafana/grafana/pkg/generated/listers/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/storage/unified/resource" diff --git a/pkg/registry/apis/provisioning/webhooks/mutator.go b/pkg/registry/apis/provisioning/webhooks/mutator.go index 10ad8288503..b93677228b0 100644 --- a/pkg/registry/apis/provisioning/webhooks/mutator.go +++ b/pkg/registry/apis/provisioning/webhooks/mutator.go @@ -3,7 +3,7 @@ package webhooks import ( "context" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/controller" "github.com/grafana/grafana/pkg/registry/apis/provisioning/secrets" "k8s.io/apimachinery/pkg/runtime" diff --git a/pkg/registry/apis/provisioning/webhooks/mutator_test.go b/pkg/registry/apis/provisioning/webhooks/mutator_test.go index 07581398fdc..209d95d5284 100644 --- a/pkg/registry/apis/provisioning/webhooks/mutator_test.go +++ b/pkg/registry/apis/provisioning/webhooks/mutator_test.go @@ -5,7 +5,7 @@ import ( "errors" "testing" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/secrets" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/changes.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/changes.go index 4bd6d5bf844..12bc6815085 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/changes.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/changes.go @@ -9,7 +9,7 @@ import ( "github.com/grafana/grafana-app-sdk/logging" dashboard "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" "github.com/grafana/grafana/pkg/infra/slugify" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/changes_test.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/changes_test.go index d31198eb595..6692d6248f3 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/changes_test.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/changes_test.go @@ -13,8 +13,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/comment_test.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/comment_test.go index fdd8e3f6dd4..e7f1d686f9f 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/comment_test.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/comment_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/runtime/schema" - "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" ) diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_evaluator.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_evaluator.go index 9d328127af4..e0f57d8ce0d 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_evaluator.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_evaluator.go @@ -10,7 +10,7 @@ import ( repository "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockEvaluator is an autogenerated mock type for the Evaluator type diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_pullrequest_repo.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_pullrequest_repo.go index f8c4b9ba5a9..6803341ecbc 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_pullrequest_repo.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/mock_pullrequest_repo.go @@ -8,7 +8,7 @@ import ( repository "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" mock "github.com/stretchr/testify/mock" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockPullRequestRepo is an autogenerated mock type for the PullRequestRepo type diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/render.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/render.go index 897f73a2e74..a6de6435c7a 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/render.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/render.go @@ -10,8 +10,8 @@ import ( "strings" "time" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/identity" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/rendering" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/render_mock.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/render_mock.go index e2a4ed6db94..3c099d6e543 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/render_mock.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/render_mock.go @@ -8,7 +8,7 @@ import ( mock "github.com/stretchr/testify/mock" - v0alpha1 "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + v0alpha1 "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" ) // MockScreenshotRenderer is an autogenerated mock type for the ScreenshotRenderer type diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/render_test.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/render_test.go index 3cb2ac1c3c8..a54d12af1b6 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/render_test.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/render_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/rendering" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/worker.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/worker.go index b52c4854b2a..1d838faa0d4 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/worker.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/worker.go @@ -8,7 +8,7 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" "github.com/grafana/grafana-app-sdk/logging" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/resources" diff --git a/pkg/registry/apis/provisioning/webhooks/pullrequest/worker_test.go b/pkg/registry/apis/provisioning/webhooks/pullrequest/worker_test.go index 4ba1cae7cb3..858a3675bfa 100644 --- a/pkg/registry/apis/provisioning/webhooks/pullrequest/worker_test.go +++ b/pkg/registry/apis/provisioning/webhooks/pullrequest/worker_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" ) diff --git a/pkg/registry/apis/provisioning/webhooks/register.go b/pkg/registry/apis/provisioning/webhooks/register.go index 0452030f27f..7de867fed9a 100644 --- a/pkg/registry/apis/provisioning/webhooks/register.go +++ b/pkg/registry/apis/provisioning/webhooks/register.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/grafana/grafana-app-sdk/logging" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" provisioningapis "github.com/grafana/grafana/pkg/registry/apis/provisioning" "github.com/grafana/grafana/pkg/registry/apis/provisioning/controller" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" diff --git a/pkg/registry/apis/provisioning/webhooks/render.go b/pkg/registry/apis/provisioning/webhooks/render.go index 06a19923a8c..77cda32198e 100644 --- a/pkg/registry/apis/provisioning/webhooks/render.go +++ b/pkg/registry/apis/provisioning/webhooks/render.go @@ -15,7 +15,7 @@ import ( "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kube-openapi/pkg/spec3" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" provisioningapis "github.com/grafana/grafana/pkg/registry/apis/provisioning" "github.com/grafana/grafana/pkg/storage/unified/resource" diff --git a/pkg/registry/apis/provisioning/webhooks/repository.go b/pkg/registry/apis/provisioning/webhooks/repository.go index 4e08111dec5..c122bdba2f4 100644 --- a/pkg/registry/apis/provisioning/webhooks/repository.go +++ b/pkg/registry/apis/provisioning/webhooks/repository.go @@ -11,7 +11,7 @@ import ( "github.com/google/go-github/v70/github" "github.com/google/uuid" "github.com/grafana/grafana-app-sdk/logging" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" pgh "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository/github" "github.com/grafana/grafana/pkg/registry/apis/provisioning/secrets" diff --git a/pkg/registry/apis/provisioning/webhooks/repository_test.go b/pkg/registry/apis/provisioning/webhooks/repository_test.go index 76de9f50f02..38b561fe0eb 100644 --- a/pkg/registry/apis/provisioning/webhooks/repository_test.go +++ b/pkg/registry/apis/provisioning/webhooks/repository_test.go @@ -14,7 +14,7 @@ import ( "strings" "testing" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository/github" "github.com/grafana/grafana/pkg/registry/apis/provisioning/secrets" "github.com/stretchr/testify/mock" diff --git a/pkg/registry/apis/provisioning/webhooks/webhook.go b/pkg/registry/apis/provisioning/webhooks/webhook.go index 4c1ef54ddfe..bf239f31e24 100644 --- a/pkg/registry/apis/provisioning/webhooks/webhook.go +++ b/pkg/registry/apis/provisioning/webhooks/webhook.go @@ -14,8 +14,8 @@ import ( "k8s.io/kube-openapi/pkg/spec3" "github.com/grafana/grafana-app-sdk/logging" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/identity" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" provisioningapis "github.com/grafana/grafana/pkg/registry/apis/provisioning" "github.com/grafana/grafana/pkg/registry/apis/provisioning/repository" "github.com/grafana/grafana/pkg/registry/apis/provisioning/webhooks/pullrequest" diff --git a/pkg/services/authn/clients/provisioning.go b/pkg/services/authn/clients/provisioning.go index d50a0ff600c..21031ea1031 100644 --- a/pkg/services/authn/clients/provisioning.go +++ b/pkg/services/authn/clients/provisioning.go @@ -7,7 +7,7 @@ import ( "time" claims "github.com/grafana/authlib/types" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/services/authn" ) diff --git a/pkg/services/authn/clients/provisioning_test.go b/pkg/services/authn/clients/provisioning_test.go index 065e24a7343..02afae68347 100644 --- a/pkg/services/authn/clients/provisioning_test.go +++ b/pkg/services/authn/clients/provisioning_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/authlib/types" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/services/authn" ) diff --git a/pkg/services/live/features/watch.go b/pkg/services/live/features/watch.go index 05a7f875518..51e6253ac17 100644 --- a/pkg/services/live/features/watch.go +++ b/pkg/services/live/features/watch.go @@ -11,7 +11,7 @@ import ( "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/dynamic" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/authlib/types" "github.com/grafana/grafana-app-sdk/logging" diff --git a/pkg/tests/apis/openapi_snapshots/provisioning.grafana.app-v0alpha1.json b/pkg/tests/apis/openapi_snapshots/provisioning.grafana.app-v0alpha1.json index 4aa160ab2e9..ab1e77d03b9 100644 --- a/pkg/tests/apis/openapi_snapshots/provisioning.grafana.app-v0alpha1.json +++ b/pkg/tests/apis/openapi_snapshots/provisioning.grafana.app-v0alpha1.json @@ -49,27 +49,27 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobList" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobList" } }, "application/json;stream=watch": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobList" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobList" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobList" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobList" } }, "application/vnd.kubernetes.protobuf;stream=watch": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobList" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobList" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobList" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobList" } } } @@ -207,17 +207,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Job" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Job" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Job" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Job" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Job" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Job" } } } @@ -367,27 +367,27 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.RepositoryList" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositoryList" } }, "application/json;stream=watch": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.RepositoryList" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositoryList" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.RepositoryList" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositoryList" } }, "application/vnd.kubernetes.protobuf;stream=watch": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.RepositoryList" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositoryList" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.RepositoryList" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositoryList" } } } @@ -439,17 +439,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } }, @@ -461,17 +461,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -481,17 +481,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -501,17 +501,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -713,17 +713,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -775,17 +775,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } }, @@ -797,17 +797,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -817,17 +817,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -1017,17 +1017,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -1037,17 +1037,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -1225,7 +1225,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceWrapper" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceWrapper" } } } @@ -1337,7 +1337,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceWrapper" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceWrapper" } } } @@ -1449,7 +1449,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceWrapper" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceWrapper" } } } @@ -1521,7 +1521,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceWrapper" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceWrapper" } } } @@ -2024,7 +2024,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceList" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceList" } } } @@ -2073,17 +2073,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -2135,17 +2135,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } }, @@ -2157,17 +2157,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -2177,17 +2177,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -2275,17 +2275,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -2295,17 +2295,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/vnd.kubernetes.protobuf": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } }, "application/yaml": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" } } } @@ -2392,7 +2392,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.TestResults" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.TestResults" } } } @@ -2441,7 +2441,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.WebhookResponse" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.WebhookResponse" } } } @@ -2466,7 +2466,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.WebhookResponse" + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.WebhookResponse" } } } @@ -2571,6 +2571,1432 @@ }, "components": { "schemas": { + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.BitbucketRepositoryConfig": { + "type": "object", + "required": [ + "branch" + ], + "properties": { + "branch": { + "description": "The branch to use in the repository.", + "type": "string", + "default": "" + }, + "encryptedToken": { + "description": "Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted.", + "type": "string", + "format": "byte", + "x-kubernetes-list-type": "atomic" + }, + "path": { + "description": "Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. This is usually something like `grafana/`. Trailing and leading slash are not required. They are always added when needed. The path is relative to the root of the repository, regardless of the leading slash.\n\nWhen specifying something like `grafana-`, we will not look for `grafana-*`; we will only look for files under the directory `/grafana-/`. That means `/grafana-example.json` would not be found.", + "type": "string" + }, + "token": { + "description": "Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again.", + "type": "string" + }, + "tokenUser": { + "description": "TokenUser is the user that will be used to access the repository if it's a personal access token.", + "type": "string" + }, + "url": { + "description": "The repository URL (e.g. `https://bitbucket.org/example/test`).", + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.DeleteJobOptions": { + "type": "object", + "properties": { + "paths": { + "description": "Paths to be deleted. Examples: - dashboard.json (for a file) - a/b/c/other-dashboard.json (for a file) - nested/deep/ (for a directory) FIXME: we should validate this in admission hooks", + "type": "array", + "items": { + "type": "string", + "default": "" + } + }, + "ref": { + "description": "Ref to the branch or commit hash to delete from", + "type": "string" + }, + "resources": { + "description": "Resources to delete This option has been created because currently the frontend does not use standarized app platform APIs. For performance and API consistency reasons, the preferred option is it to use the paths.", + "type": "array", + "items": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceRef" + } + ] + } + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ErrorDetails": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "detail": { + "type": "string" + }, + "field": { + "type": "string" + }, + "type": { + "type": "string", + "default": "" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ExportJobOptions": { + "type": "object", + "properties": { + "branch": { + "description": "FIXME: we should validate this in admission hooks Target branch for export (only git)", + "type": "string" + }, + "folder": { + "description": "The source folder (or empty) to export", + "type": "string" + }, + "message": { + "description": "Message to use when committing the changes in a single commit", + "type": "string" + }, + "path": { + "description": "FIXME: we should validate this in admission hooks Prefix in target file system", + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.GitHubRepositoryConfig": { + "type": "object", + "required": [ + "branch" + ], + "properties": { + "branch": { + "description": "The branch to use in the repository.", + "type": "string", + "default": "" + }, + "encryptedToken": { + "description": "Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted.", + "type": "string", + "format": "byte", + "x-kubernetes-list-type": "atomic" + }, + "generateDashboardPreviews": { + "description": "Whether we should show dashboard previews for pull requests. By default, this is false (i.e. we will not create previews).", + "type": "boolean" + }, + "path": { + "description": "Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. This is usually something like `grafana/`. Trailing and leading slash are not required. They are always added when needed. The path is relative to the root of the repository, regardless of the leading slash.\n\nWhen specifying something like `grafana-`, we will not look for `grafana-*`; we will only look for files under the directory `/grafana-/`. That means `/grafana-example.json` would not be found.", + "type": "string" + }, + "token": { + "description": "Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again.", + "type": "string" + }, + "url": { + "description": "The repository URL (e.g. `https://github.com/example/test`).", + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.GitLabRepositoryConfig": { + "type": "object", + "required": [ + "branch" + ], + "properties": { + "branch": { + "description": "The branch to use in the repository.", + "type": "string", + "default": "" + }, + "encryptedToken": { + "description": "Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted.", + "type": "string", + "format": "byte", + "x-kubernetes-list-type": "atomic" + }, + "path": { + "description": "Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. This is usually something like `grafana/`. Trailing and leading slash are not required. They are always added when needed. The path is relative to the root of the repository, regardless of the leading slash.\n\nWhen specifying something like `grafana-`, we will not look for `grafana-*`; we will only look for files under the directory `/grafana-/`. That means `/grafana-example.json` would not be found.", + "type": "string" + }, + "token": { + "description": "Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again.", + "type": "string" + }, + "url": { + "description": "The repository URL (e.g. `https://gitlab.com/example/test`).", + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.GitRepositoryConfig": { + "type": "object", + "required": [ + "branch" + ], + "properties": { + "branch": { + "description": "The branch to use in the repository.", + "type": "string", + "default": "" + }, + "encryptedToken": { + "description": "Token for accessing the repository, but encrypted. This is not possible to read back to a user decrypted.", + "type": "string", + "format": "byte", + "x-kubernetes-list-type": "atomic" + }, + "path": { + "description": "Path is the subdirectory for the Grafana data. If specified, Grafana will ignore anything that is outside this directory in the repository. This is usually something like `grafana/`. Trailing and leading slash are not required. They are always added when needed. The path is relative to the root of the repository, regardless of the leading slash.\n\nWhen specifying something like `grafana-`, we will not look for `grafana-*`; we will only look for files under the directory `/grafana-/`. That means `/grafana-example.json` would not be found.", + "type": "string" + }, + "token": { + "description": "Token for accessing the repository. If set, it will be encrypted into encryptedToken, then set to an empty string again.", + "type": "string" + }, + "tokenUser": { + "description": "TokenUser is the user that will be used to access the repository if it's a personal access token.", + "type": "string" + }, + "url": { + "description": "The repository URL (e.g. `https://github.com/example/test.git`).", + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.HealthStatus": { + "type": "object", + "required": [ + "healthy" + ], + "properties": { + "checked": { + "description": "When the health was checked last time", + "type": "integer", + "format": "int64" + }, + "healthy": { + "description": "When not healthy, requests will not be executed", + "type": "boolean", + "default": false + }, + "message": { + "description": "Summary messages (can be shown to users) Will only be populated when not healthy", + "type": "array", + "items": { + "type": "string", + "default": "" + }, + "x-kubernetes-list-type": "atomic" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Job": { + "description": "The repository name and type are stored as labels", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + } + ] + }, + "spec": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobSpec" + } + ] + }, + "status": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobStatus" + } + ] + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "provisioning.grafana.app", + "kind": "Job", + "version": "v0alpha1" + } + ] + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobList": { + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "items": { + "type": "array", + "items": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Job" + } + ] + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + ] + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "provisioning.grafana.app", + "kind": "JobList", + "version": "v0alpha1" + } + ] + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobResourceSummary": { + "type": "object", + "properties": { + "create": { + "type": "integer", + "format": "int64" + }, + "delete": { + "type": "integer", + "format": "int64" + }, + "error": { + "description": "Create or update (export)", + "type": "integer", + "format": "int64" + }, + "errors": { + "description": "Report errors for this resource type This may not be an exhaustive list and recommend looking at the logs for more info", + "type": "array", + "items": { + "type": "string", + "default": "" + } + }, + "group": { + "type": "string" + }, + "noop": { + "description": "No action required (useful for sync)", + "type": "integer", + "format": "int64" + }, + "resource": { + "type": "string" + }, + "total": { + "type": "integer", + "format": "int64" + }, + "update": { + "type": "integer", + "format": "int64" + }, + "write": { + "type": "integer", + "format": "int64" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobSpec": { + "type": "object", + "properties": { + "action": { + "description": "Possible enum values:\n - `\"delete\"` deletes files in the remote repository\n - `\"migrate\"` acts like JobActionExport, then JobActionPull. It also tries to preserve the history.\n - `\"move\"` moves files in the remote repository\n - `\"pr\"` adds additional useful information to a PR, such as comments with preview links and rendered images.\n - `\"pull\"` replicates the remote branch in the local copy of the repository.\n - `\"push\"` replicates the local copy of the repository in the remote branch.", + "type": "string", + "enum": [ + "delete", + "migrate", + "move", + "pr", + "pull", + "push" + ] + }, + "delete": { + "description": "Delete when the action is `delete`", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.DeleteJobOptions" + } + ] + }, + "migrate": { + "description": "Required when the action is `migrate`", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.MigrateJobOptions" + } + ] + }, + "move": { + "description": "Move when the action is `move`", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.MoveJobOptions" + } + ] + }, + "pr": { + "description": "Pull request options", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.PullRequestJobOptions" + } + ] + }, + "pull": { + "description": "Required when the action is `pull`", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.SyncJobOptions" + } + ] + }, + "push": { + "description": "Required when the action is `push`", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ExportJobOptions" + } + ] + }, + "repository": { + "description": "The the repository reference (for now also in labels) This value is required, but will be popuplated from the job making the request", + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobStatus": { + "description": "The job status", + "type": "object", + "properties": { + "errors": { + "type": "array", + "items": { + "type": "string", + "default": "" + } + }, + "finished": { + "type": "integer", + "format": "int64" + }, + "message": { + "type": "string" + }, + "progress": { + "description": "Optional value 0-100 that can be set while running", + "type": "number", + "format": "double" + }, + "started": { + "type": "integer", + "format": "int64" + }, + "state": { + "description": "Possible enum values:\n - `\"error\"` Finished with errors\n - `\"pending\"` Job has been submitted, but not processed yet\n - `\"success\"` Finished with success\n - `\"warning\"` Finished with some non-critical errors\n - `\"working\"` The job is running", + "type": "string", + "enum": [ + "error", + "pending", + "success", + "warning", + "working" + ] + }, + "summary": { + "description": "Summary of processed actions", + "type": "array", + "items": { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobResourceSummary" + } + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.LocalRepositoryConfig": { + "type": "object", + "properties": { + "path": { + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.MigrateJobOptions": { + "type": "object", + "properties": { + "history": { + "description": "Preserve history (if possible)", + "type": "boolean" + }, + "message": { + "description": "Message to use when committing the changes in a single commit", + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.MoveJobOptions": { + "type": "object", + "properties": { + "paths": { + "description": "Paths to be deleted. Examples: - dashboard.json (for a file) - a/b/c/other-dashboard.json (for a file) - nested/deep/ (for a directory) FIXME: we should validate this in admission hooks", + "type": "array", + "items": { + "type": "string", + "default": "" + } + }, + "ref": { + "description": "Ref to the branch or commit hash that should move", + "type": "string" + }, + "resources": { + "description": "Resources to move This option has been created because currently the frontend does not use standarized app platform APIs. For performance and API consistency reasons, the preferred option is it to use the paths.", + "type": "array", + "items": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceRef" + } + ] + } + }, + "targetPath": { + "description": "Destination path for the move (e.g. \"new-location/\")", + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.PullRequestJobOptions": { + "type": "object", + "properties": { + "hash": { + "description": "The specific commit hash that triggered this notice", + "type": "string" + }, + "pr": { + "description": "Pull request number (when appropriate)", + "type": "integer", + "format": "int32" + }, + "ref": { + "description": "The branch of commit hash", + "type": "string" + }, + "url": { + "description": "URL to the originator (eg, PR URL)", + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RefItem": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "hash": { + "description": "The SHA hash of the commit this ref points to", + "type": "string" + }, + "name": { + "description": "The name of the reference (branch or tag)", + "type": "string", + "default": "" + }, + "refURL": { + "description": "The URL to the reference (branch or tag)", + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RefList": { + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "items": { + "type": "array", + "items": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RefItem" + } + ] + }, + "x-kubernetes-list-type": "atomic" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + ] + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "provisioning.grafana.app", + "kind": "RefList", + "version": "v0alpha1" + } + ] + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository": { + "description": "When this code is changed, make sure to update the code generation. As of writing, this can be done via the hack dir in the root of the repo: ./hack/update-codegen.sh provisioning If you've opened the generated files in this dir at some point in VSCode, you may also have to re-open them to clear errors.", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + } + ] + }, + "spec": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositorySpec" + } + ] + }, + "status": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositoryStatus" + } + ] + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "provisioning.grafana.app", + "kind": "Repository", + "version": "v0alpha1" + } + ] + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositoryList": { + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "items": { + "type": "array", + "items": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.Repository" + } + ] + }, + "x-kubernetes-list-type": "atomic" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + ] + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "provisioning.grafana.app", + "kind": "RepositoryList", + "version": "v0alpha1" + } + ] + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositorySpec": { + "type": "object", + "required": [ + "title", + "workflows", + "sync", + "type" + ], + "properties": { + "bitbucket": { + "description": "The repository on Bitbucket. Mutually exclusive with local | github | git.", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.BitbucketRepositoryConfig" + } + ] + }, + "description": { + "description": "Repository description", + "type": "string" + }, + "git": { + "description": "The repository on Git. Mutually exclusive with local | github | git.", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.GitRepositoryConfig" + } + ] + }, + "github": { + "description": "The repository on GitHub. Mutually exclusive with local | github | git.", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.GitHubRepositoryConfig" + } + ] + }, + "gitlab": { + "description": "The repository on GitLab. Mutually exclusive with local | github | git.", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.GitLabRepositoryConfig" + } + ] + }, + "local": { + "description": "The repository on the local file system. Mutually exclusive with local | github.", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.LocalRepositoryConfig" + } + ] + }, + "sync": { + "description": "Sync settings -- how values are pulled from the repository into grafana", + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.SyncOptions" + } + ] + }, + "title": { + "description": "The repository display name (shown in the UI)", + "type": "string", + "default": "" + }, + "type": { + "description": "The repository type. When selected oneOf the values below should be non-nil\n\nPossible enum values:\n - `\"bitbucket\"`\n - `\"git\"`\n - `\"github\"`\n - `\"gitlab\"`\n - `\"local\"`", + "type": "string", + "default": "", + "enum": [ + "bitbucket", + "git", + "github", + "gitlab", + "local" + ] + }, + "workflows": { + "description": "UI driven Workflow that allow changes to the contends of the repository. The order is relevant for defining the precedence of the workflows. When empty, the repository does not support any edits (eg, readonly)", + "type": "array", + "items": { + "type": "string", + "default": "", + "enum": [ + "branch", + "write" + ] + } + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.RepositoryStatus": { + "description": "The status of a Repository. This is expected never to be created by a kubectl call or similar, and is expected to rarely (if ever) be edited manually. As such, it is also a little less well structured than the spec, such as conditional-but-ever-present fields.", + "type": "object", + "required": [ + "observedGeneration", + "health", + "sync", + "webhook" + ], + "properties": { + "health": { + "description": "This will get updated with the current health status (and updated periodically)", + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.HealthStatus" + } + ] + }, + "observedGeneration": { + "description": "The generation of the spec last time reconciliation ran", + "type": "integer", + "format": "int64", + "default": 0 + }, + "stats": { + "description": "The object count when sync last ran", + "type": "array", + "items": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceCount" + } + ] + }, + "x-kubernetes-list-type": "atomic" + }, + "sync": { + "description": "Sync information with the last sync information", + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.SyncStatus" + } + ] + }, + "webhook": { + "description": "Webhook Information (if applicable)", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.WebhookStatus" + } + ] + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceCount": { + "type": "object", + "required": [ + "group", + "resource", + "count" + ], + "properties": { + "count": { + "type": "integer", + "format": "int64", + "default": 0 + }, + "group": { + "type": "string", + "default": "" + }, + "resource": { + "type": "string", + "default": "" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceList": { + "description": "Information we can get just from the file listing", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "items": { + "type": "array", + "items": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceListItem" + } + ] + }, + "x-kubernetes-list-type": "atomic" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + ] + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "provisioning.grafana.app", + "kind": "ResourceList", + "version": "v0alpha1" + } + ] + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceListItem": { + "type": "object", + "required": [ + "path", + "group", + "resource", + "name", + "hash" + ], + "properties": { + "folder": { + "type": "string" + }, + "group": { + "type": "string", + "default": "" + }, + "hash": { + "description": "the k8s identifier", + "type": "string", + "default": "" + }, + "name": { + "type": "string", + "default": "" + }, + "path": { + "type": "string", + "default": "" + }, + "resource": { + "type": "string", + "default": "" + }, + "time": { + "type": "integer", + "format": "int64" + }, + "title": { + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceObjects": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "action": { + "description": "The action required/used for dryRun\n\nPossible enum values:\n - `\"create\"`\n - `\"delete\"`\n - `\"move\"`\n - `\"update\"`", + "type": "string", + "enum": [ + "create", + "delete", + "move", + "update" + ] + }, + "dryRun": { + "description": "The value returned from a dryRun request", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured" + } + ] + }, + "existing": { + "description": "The same value, currently saved in the grafana database", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured" + } + ] + }, + "file": { + "description": "The resource from the repository with all modifications applied eg, the name, folder etc will all be applied to this object", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured" + } + ] + }, + "type": { + "description": "The identified type for this object", + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceType" + } + ] + }, + "upsert": { + "description": "For write events, this will return the value that was added or updated", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured" + } + ] + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceRef": { + "type": "object", + "properties": { + "group": { + "description": "Group is the group of the resource, such as \"dashboard.grafana.app\".", + "type": "string" + }, + "kind": { + "description": "Kind is the type of resource, for example, \"Dashboard\".", + "type": "string" + }, + "name": { + "description": "Name is the name of the resource, such as a dashboard UID.", + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceRepositoryInfo": { + "type": "object", + "required": [ + "type", + "title", + "namespace", + "name" + ], + "properties": { + "name": { + "description": "The name (identifier)", + "type": "string", + "default": "" + }, + "namespace": { + "description": "The namespace this belongs to", + "type": "string", + "default": "" + }, + "title": { + "description": "The display name for this repository", + "type": "string", + "default": "" + }, + "type": { + "description": "The repository type\n\nPossible enum values:\n - `\"bitbucket\"`\n - `\"git\"`\n - `\"github\"`\n - `\"gitlab\"`\n - `\"local\"`", + "type": "string", + "default": "", + "enum": [ + "bitbucket", + "git", + "github", + "gitlab", + "local" + ] + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceType": { + "type": "object", + "properties": { + "classic": { + "description": "For non-k8s native formats, what did this start as\n\nPossible enum values:\n - `\"access-control\"` Access control https://github.com/grafana/grafana/blob/v11.3.1/conf/provisioning/access-control/sample.yaml\n - `\"alerting\"` Alert configuration https://github.com/grafana/grafana/blob/v11.3.1/conf/provisioning/alerting/sample.yaml\n - `\"dashboard\"` Dashboard JSON\n - `\"datasources\"` Datasource definitions eg: https://github.com/grafana/grafana/blob/v11.3.1/conf/provisioning/datasources/sample.yaml", + "type": "string", + "enum": [ + "access-control", + "alerting", + "dashboard", + "datasources" + ] + }, + "group": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceURLs": { + "type": "object", + "properties": { + "compareURL": { + "description": "Compare this version to the target branch", + "type": "string" + }, + "newPullRequestURL": { + "description": "A URL that will create a new pull requeset for this branch", + "type": "string" + }, + "repositoryURL": { + "description": "A URL pointing to the repository this lives in", + "type": "string" + }, + "sourceURL": { + "description": "A URL pointing to the this file in the repository", + "type": "string" + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceWrapper": { + "description": "This is a container type for any resource type", + "type": "object", + "required": [ + "repository", + "resource" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "errors": { + "description": "If errors exist, show them here", + "type": "array", + "items": { + "type": "string", + "default": "" + }, + "x-kubernetes-list-type": "atomic" + }, + "hash": { + "description": "The repo hash value", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "path": { + "description": "Path to the remote file", + "type": "string" + }, + "ref": { + "description": "The request ref (or branch if exists)", + "type": "string" + }, + "repository": { + "description": "Basic repository info", + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceRepositoryInfo" + } + ] + }, + "resource": { + "description": "Different flavors of the same object", + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceObjects" + } + ] + }, + "timestamp": { + "description": "The modified time in the remote file system", + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Time" + } + ] + }, + "urls": { + "description": "Typed links for this file (only supported by external systems, github etc)", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ResourceURLs" + } + ] + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "provisioning.grafana.app", + "kind": "ResourceWrapper", + "version": "v0alpha1" + } + ] + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.SyncJobOptions": { + "type": "object", + "required": [ + "incremental" + ], + "properties": { + "incremental": { + "description": "Incremental synchronization for versioned repositories", + "type": "boolean", + "default": false + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.SyncOptions": { + "type": "object", + "required": [ + "enabled", + "target" + ], + "properties": { + "enabled": { + "description": "Enabled must be saved as true before any sync job will run", + "type": "boolean", + "default": false + }, + "intervalSeconds": { + "description": "When non-zero, the sync will run periodically", + "type": "integer", + "format": "int64" + }, + "target": { + "description": "Where values should be saved\n\nPossible enum values:\n - `\"folder\"` Resources will be saved into a folder managed by this repository It will contain a copy of everything from the remote The folder k8s name will be the same as the repository k8s name\n - `\"instance\"` Resources are saved in the global context Only one repository may specify the `instance` target When this exists, the UI will promote writing to the instance repo rather than the grafana database (where possible)", + "type": "string", + "default": "", + "enum": [ + "folder", + "instance" + ] + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.SyncStatus": { + "type": "object", + "required": [ + "state", + "message" + ], + "properties": { + "finished": { + "description": "When the sync job finished", + "type": "integer", + "format": "int64" + }, + "incremental": { + "description": "Incremental synchronization for versioned repositories", + "type": "boolean" + }, + "job": { + "description": "The ID for the job that ran this sync", + "type": "string" + }, + "lastRef": { + "description": "The repository ref when the last successful sync ran", + "type": "string" + }, + "message": { + "description": "Summary messages (will be shown to users)", + "type": "array", + "items": { + "type": "string", + "default": "" + }, + "x-kubernetes-list-type": "atomic" + }, + "scheduled": { + "description": "When the next sync check is scheduled", + "type": "integer", + "format": "int64" + }, + "started": { + "description": "When the sync job started", + "type": "integer", + "format": "int64" + }, + "state": { + "description": "pending, running, success, error\n\nPossible enum values:\n - `\"error\"` Finished with errors\n - `\"pending\"` Job has been submitted, but not processed yet\n - `\"success\"` Finished with success\n - `\"warning\"` Finished with some non-critical errors\n - `\"working\"` The job is running", + "type": "string", + "default": "", + "enum": [ + "error", + "pending", + "success", + "warning", + "working" + ] + } + } + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.TestResults": { + "description": "HistoryList is a list of versions of a resource", + "type": "object", + "required": [ + "code", + "success" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "code": { + "description": "HTTP status code", + "type": "integer", + "format": "int32", + "default": 0 + }, + "errors": { + "description": "Field related errors", + "type": "array", + "items": { + "default": {}, + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.ErrorDetails" + } + ] + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "success": { + "description": "Is the connection healthy", + "type": "boolean", + "default": false + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "provisioning.grafana.app", + "kind": "TestResults", + "version": "v0alpha1" + } + ] + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.WebhookResponse": { + "type": "object", + "properties": { + "added": { + "description": "Optional message", + "type": "string" + }, + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "code": { + "description": "HTTP Status code 200 implies that the payload was understood but nothing is required 202 implies that an async job has been scheduled to handle the request", + "type": "integer", + "format": "int32" + }, + "job": { + "description": "Jobs to be processed When the response is 202 (Accepted) the queued jobs will be returned", + "allOf": [ + { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.JobSpec" + } + ] + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + } + }, + "x-kubernetes-group-version-kind": [ + { + "group": "provisioning.grafana.app", + "kind": "WebhookResponse", + "version": "v0alpha1" + } + ] + }, + "com.github.grafana.grafana.apps.provisioning.pkg.apis.provisioning.v0alpha1.WebhookStatus": { + "type": "object", + "properties": { + "encryptedSecret": { + "type": "string", + "format": "byte" + }, + "id": { + "type": "integer", + "format": "int64" + }, + "lastEvent": { + "type": "integer", + "format": "int64" + }, + "secret": { + "type": "string" + }, + "subscribedEvents": { + "type": "array", + "items": { + "type": "string", + "default": "" + } + }, + "url": { + "type": "string" + } + } + }, "com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured": { "type": "object", "additionalProperties": true, @@ -2650,12 +4076,7 @@ "description": "Resources to delete This option has been created because currently the frontend does not use standarized app platform APIs. For performance and API consistency reasons, the preferred option is it to use the paths.", "type": "array", "items": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceRef" - } - ] + "default": {} } } } @@ -2951,37 +4372,15 @@ "type": "string" }, "metadata": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" - } - ] + "default": {} }, "spec": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobSpec" - } - ] + "default": {} }, "status": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobStatus" - } - ] + "default": {} } - }, - "x-kubernetes-group-version-kind": [ - { - "group": "provisioning.grafana.app", - "kind": "Job", - "version": "v0alpha1" - } - ] + } }, "com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobList": { "type": "object", @@ -2996,12 +4395,7 @@ "items": { "type": "array", "items": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Job" - } - ] + "default": {} } }, "kind": { @@ -3009,21 +4403,9 @@ "type": "string" }, "metadata": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" - } - ] + "default": {} } - }, - "x-kubernetes-group-version-kind": [ - { - "group": "provisioning.grafana.app", - "kind": "JobList", - "version": "v0alpha1" - } - ] + } }, "com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobResourceSummary": { "type": "object", @@ -3090,52 +4472,22 @@ ] }, "delete": { - "description": "Delete when the action is `delete`", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.DeleteJobOptions" - } - ] + "description": "Delete when the action is `delete`" }, "migrate": { - "description": "Required when the action is `migrate`", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.MigrateJobOptions" - } - ] + "description": "Required when the action is `migrate`" }, "move": { - "description": "Move when the action is `move`", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.MoveJobOptions" - } - ] + "description": "Move when the action is `move`" }, "pr": { - "description": "Pull request options", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.PullRequestJobOptions" - } - ] + "description": "Pull request options" }, "pull": { - "description": "Required when the action is `pull`", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.SyncJobOptions" - } - ] + "description": "Required when the action is `pull`" }, "push": { - "description": "Required when the action is `push`", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ExportJobOptions" - } - ] + "description": "Required when the action is `push`" }, "repository": { "description": "The the repository reference (for now also in labels) This value is required, but will be popuplated from the job making the request", @@ -3184,9 +4536,7 @@ "summary": { "description": "Summary of processed actions", "type": "array", - "items": { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobResourceSummary" - } + "items": {} } } }, @@ -3257,12 +4607,7 @@ "description": "Resources to move This option has been created because currently the frontend does not use standarized app platform APIs. For performance and API consistency reasons, the preferred option is it to use the paths.", "type": "array", "items": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceRef" - } - ] + "default": {} } }, "targetPath": { @@ -3327,12 +4672,7 @@ "items": { "type": "array", "items": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.RefItem" - } - ] + "default": {} }, "x-kubernetes-list-type": "atomic" }, @@ -3341,21 +4681,9 @@ "type": "string" }, "metadata": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" - } - ] + "default": {} } - }, - "x-kubernetes-group-version-kind": [ - { - "group": "provisioning.grafana.app", - "kind": "RefList", - "version": "v0alpha1" - } - ] + } }, "com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository": { "description": "When this code is changed, make sure to update the code generation. As of writing, this can be done via the hack dir in the root of the repo: ./hack/update-codegen.sh provisioning If you've opened the generated files in this dir at some point in VSCode, you may also have to re-open them to clear errors.", @@ -3370,37 +4698,15 @@ "type": "string" }, "metadata": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" - } - ] + "default": {} }, "spec": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.RepositorySpec" - } - ] + "default": {} }, "status": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.RepositoryStatus" - } - ] + "default": {} } - }, - "x-kubernetes-group-version-kind": [ - { - "group": "provisioning.grafana.app", - "kind": "Repository", - "version": "v0alpha1" - } - ] + } }, "com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.RepositoryList": { "type": "object", @@ -3415,12 +4721,7 @@ "items": { "type": "array", "items": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.Repository" - } - ] + "default": {} }, "x-kubernetes-list-type": "atomic" }, @@ -3429,21 +4730,9 @@ "type": "string" }, "metadata": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" - } - ] + "default": {} } - }, - "x-kubernetes-group-version-kind": [ - { - "group": "provisioning.grafana.app", - "kind": "RepositoryList", - "version": "v0alpha1" - } - ] + } }, "com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.RepositorySpec": { "type": "object", @@ -3455,57 +4744,27 @@ ], "properties": { "bitbucket": { - "description": "The repository on Bitbucket. Mutually exclusive with local | github | git.", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.BitbucketRepositoryConfig" - } - ] + "description": "The repository on Bitbucket. Mutually exclusive with local | github | git." }, "description": { "description": "Repository description", "type": "string" }, "git": { - "description": "The repository on Git. Mutually exclusive with local | github | git.", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.GitRepositoryConfig" - } - ] + "description": "The repository on Git. Mutually exclusive with local | github | git." }, "github": { - "description": "The repository on GitHub. Mutually exclusive with local | github | git.", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.GitHubRepositoryConfig" - } - ] + "description": "The repository on GitHub. Mutually exclusive with local | github | git." }, "gitlab": { - "description": "The repository on GitLab. Mutually exclusive with local | github | git.", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.GitLabRepositoryConfig" - } - ] + "description": "The repository on GitLab. Mutually exclusive with local | github | git." }, "local": { - "description": "The repository on the local file system. Mutually exclusive with local | github.", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.LocalRepositoryConfig" - } - ] + "description": "The repository on the local file system. Mutually exclusive with local | github." }, "sync": { "description": "Sync settings -- how values are pulled from the repository into grafana", - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.SyncOptions" - } - ] + "default": {} }, "title": { "description": "The repository display name (shown in the UI)", @@ -3550,12 +4809,7 @@ "properties": { "health": { "description": "This will get updated with the current health status (and updated periodically)", - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.HealthStatus" - } - ] + "default": {} }, "observedGeneration": { "description": "The generation of the spec last time reconciliation ran", @@ -3567,31 +4821,16 @@ "description": "The object count when sync last ran", "type": "array", "items": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceCount" - } - ] + "default": {} }, "x-kubernetes-list-type": "atomic" }, "sync": { "description": "Sync information with the last sync information", - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.SyncStatus" - } - ] + "default": {} }, "webhook": { - "description": "Webhook Information (if applicable)", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.WebhookStatus" - } - ] + "description": "Webhook Information (if applicable)" } } }, @@ -3738,12 +4977,7 @@ "items": { "type": "array", "items": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceListItem" - } - ] + "default": {} }, "x-kubernetes-list-type": "atomic" }, @@ -3752,21 +4986,9 @@ "type": "string" }, "metadata": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" - } - ] + "default": {} } - }, - "x-kubernetes-group-version-kind": [ - { - "group": "provisioning.grafana.app", - "kind": "ResourceList", - "version": "v0alpha1" - } - ] + } }, "com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceListItem": { "type": "object", @@ -3828,45 +5050,20 @@ ] }, "dryRun": { - "description": "The value returned from a dryRun request", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured" - } - ] + "description": "The value returned from a dryRun request" }, "existing": { - "description": "The same value, currently saved in the grafana database", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured" - } - ] + "description": "The same value, currently saved in the grafana database" }, "file": { - "description": "The resource from the repository with all modifications applied eg, the name, folder etc will all be applied to this object", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured" - } - ] + "description": "The resource from the repository with all modifications applied eg, the name, folder etc will all be applied to this object" }, "type": { "description": "The identified type for this object", - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceType" - } - ] + "default": {} }, "upsert": { - "description": "For write events, this will return the value that was added or updated", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured" - } - ] + "description": "For write events, this will return the value that was added or updated" } } }, @@ -4053,46 +5250,19 @@ }, "repository": { "description": "Basic repository info", - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceRepositoryInfo" - } - ] + "default": {} }, "resource": { "description": "Different flavors of the same object", - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceObjects" - } - ] + "default": {} }, "timestamp": { - "description": "The modified time in the remote file system", - "allOf": [ - { - "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Time" - } - ] + "description": "The modified time in the remote file system" }, "urls": { - "description": "Typed links for this file (only supported by external systems, github etc)", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ResourceURLs" - } - ] + "description": "Typed links for this file (only supported by external systems, github etc)" } - }, - "x-kubernetes-group-version-kind": [ - { - "group": "provisioning.grafana.app", - "kind": "ResourceWrapper", - "version": "v0alpha1" - } - ] + } }, "com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.SyncJobOptions": { "type": "object", @@ -4214,12 +5384,7 @@ "description": "Field related errors", "type": "array", "items": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.ErrorDetails" - } - ] + "default": {} } }, "kind": { @@ -4231,14 +5396,7 @@ "type": "boolean", "default": false } - }, - "x-kubernetes-group-version-kind": [ - { - "group": "provisioning.grafana.app", - "kind": "TestResults", - "version": "v0alpha1" - } - ] + } }, "com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.WebhookResponse": { "type": "object", @@ -4257,25 +5415,13 @@ "format": "int32" }, "job": { - "description": "Jobs to be processed When the response is 202 (Accepted) the queued jobs will be returned", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.JobSpec" - } - ] + "description": "Jobs to be processed When the response is 202 (Accepted) the queued jobs will be returned" }, "kind": { "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", "type": "string" } - }, - "x-kubernetes-group-version-kind": [ - { - "group": "provisioning.grafana.app", - "kind": "WebhookResponse", - "version": "v0alpha1" - } - ] + } }, "com.github.grafana.grafana.pkg.apis.provisioning.v0alpha1.WebhookStatus": { "type": "object", diff --git a/pkg/tests/apis/provisioning/helper_test.go b/pkg/tests/apis/provisioning/helper_test.go index 03ca9342f31..f1252af3662 100644 --- a/pkg/tests/apis/provisioning/helper_test.go +++ b/pkg/tests/apis/provisioning/helper_test.go @@ -27,7 +27,7 @@ import ( dashboardsV2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1" dashboardsV2beta1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1" folder "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" "github.com/grafana/grafana/pkg/registry/apis/provisioning/jobs" "github.com/grafana/grafana/pkg/services/featuremgmt" diff --git a/pkg/tests/apis/provisioning/provisioning_test.go b/pkg/tests/apis/provisioning/provisioning_test.go index f9a5c40a14e..a7b28d877ce 100644 --- a/pkg/tests/apis/provisioning/provisioning_test.go +++ b/pkg/tests/apis/provisioning/provisioning_test.go @@ -20,8 +20,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/apimachinery/utils" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/extensions" "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/tests/apis" diff --git a/pkg/tests/apis/provisioning/secrets_test.go b/pkg/tests/apis/provisioning/secrets_test.go index a85b8a56f62..331d4bc3067 100644 --- a/pkg/tests/apis/provisioning/secrets_test.go +++ b/pkg/tests/apis/provisioning/secrets_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - provisioning "github.com/grafana/grafana/pkg/apis/provisioning/v0alpha1" + provisioning "github.com/grafana/grafana/apps/provisioning/pkg/apis/provisioning/v0alpha1" "github.com/grafana/grafana/pkg/registry/apis/provisioning/secrets" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/stretchr/testify/require" From 8b5b9b68c2c5c33d12399b79a5f8beacedf9c0ce Mon Sep 17 00:00:00 2001 From: Alexander Akhmetov Date: Fri, 1 Aug 2025 22:39:54 +0200 Subject: [PATCH 39/89] Alerting: Document Accept header in Prometheus conversion API (#109080) --- docs/sources/alerting/alerting-rules/alerting-migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/alerting/alerting-rules/alerting-migration.md b/docs/sources/alerting/alerting-rules/alerting-migration.md index 08a301c24c3..2e63db00136 100644 --- a/docs/sources/alerting/alerting-rules/alerting-migration.md +++ b/docs/sources/alerting/alerting-rules/alerting-migration.md @@ -281,7 +281,7 @@ The `POST` endpoints can be used to import data source–managed alert rules. Th | POST | `/convert/prometheus/config/v1/rules` | [Create or update multiple rule groups](#create-or-update-multiple-rule-groups) across multiple namespaces. Requires [`X-Grafana-Alerting-Datasource-UID`](#x-grafana-alerting-datasource-uid). | None | | POST | `/convert/prometheus/config/v1/rules/:namespaceTitle` | Create or update a single rule group in a namespace. Requires [`X-Grafana-Alerting-Datasource-UID`](#x-grafana-alerting-datasource-uid). | [Set rule group](/docs/mimir/latest/references/http-api/#set-rule-group) | -The `GET` and `DELETE` endpoints work only with provisioned and imported alert rules. +The `GET` and `DELETE` endpoints work only with provisioned and imported alert rules. All `GET` endpoints support both JSON and YAML response formats based on the `Accept` header: use `application/json` for JSON responses, or `application/yaml` for YAML responses. YAML is the default format when no `Accept` header is specified. | Endpoint | Method | Summary | Mimir equivalent | | -------- | ------------------------------------------------------------ | --------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | From bd5c83bc11d880a77751c8b27730ec2fd041a0ec Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Fri, 1 Aug 2025 15:49:54 -0500 Subject: [PATCH 40/89] Revert "Chore: Use proper database type from env in testinfra integration tests" (#109081) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revert "Chore: Use proper database type from env in testinfra integration tes…" This reverts commit 772f647210cfe3c4ac95002e21888db9c0ed9f5d. --- apps/advisor/go.mod | 3 +- apps/advisor/go.sum | 10 ++++--- apps/investigations/go.mod | 2 +- apps/investigations/go.sum | 6 ++-- go.mod | 4 ++- go.sum | 6 ++-- pkg/services/sqlstore/sqlutil/sqlutil.go | 15 ---------- .../apis/provisioning/provisioning_test.go | 29 +++++++------------ pkg/tests/testinfra/testinfra.go | 15 ---------- 9 files changed, 30 insertions(+), 60 deletions(-) diff --git a/apps/advisor/go.mod b/apps/advisor/go.mod index 2a232b42873..5c3f927de43 100644 --- a/apps/advisor/go.mod +++ b/apps/advisor/go.mod @@ -10,7 +10,7 @@ require ( github.com/grafana/grafana-app-sdk v0.40.2 github.com/grafana/grafana-app-sdk/logging v0.40.1 github.com/grafana/grafana-plugin-sdk-go v0.278.0 - github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250725144121-b1592b5e36d2 + github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956 github.com/stretchr/testify v1.10.0 k8s.io/apimachinery v0.33.3 k8s.io/apiserver v0.33.3 @@ -132,6 +132,7 @@ require ( github.com/grafana/dskit v0.0.0-20250611075409-46f51e1ce914 // indirect github.com/grafana/grafana-aws-sdk v1.0.4 // indirect github.com/grafana/grafana-azure-sdk-go/v2 v2.2.0 // indirect + github.com/grafana/grafana/apps/provisioning v0.0.0-20250801193518-9f4773c9a5a3 // indirect github.com/grafana/grafana/pkg/apiserver v0.0.0-20250627191313-2f1a6ae1712b // indirect github.com/grafana/otel-profiling-go v0.5.1 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect diff --git a/apps/advisor/go.sum b/apps/advisor/go.sum index 653ca2c8c71..c6263714349 100644 --- a/apps/advisor/go.sum +++ b/apps/advisor/go.sum @@ -494,8 +494,8 @@ github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= -github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y= github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= @@ -677,12 +677,14 @@ github.com/grafana/grafana/apps/dashboard v0.0.0-20250730164619-34019e5ec017 h1: github.com/grafana/grafana/apps/dashboard v0.0.0-20250730164619-34019e5ec017/go.mod h1:/iuseD/cEpXDiy7MpL+4qBFZ3H6esnUJTYzpoJMw9dw= github.com/grafana/grafana/apps/folder v0.0.0-20250627191313-2f1a6ae1712b h1:31MwoIKKT9Ay0ZjbT4lkfcPijiWogUWzXs2EjrCgodI= github.com/grafana/grafana/apps/folder v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:dLtYBp1pza5HYalezNvzlP8JDeKrZ5BKTonDgEOE0NY= +github.com/grafana/grafana/apps/provisioning v0.0.0-20250801193518-9f4773c9a5a3 h1:MUyJnJE3GFj9QqA0sq7VOqWQkywYvH0/T4kwJfVQzJE= +github.com/grafana/grafana/apps/provisioning v0.0.0-20250801193518-9f4773c9a5a3/go.mod h1:qzFUVwLI1b5UIbVFxFydUYAsnOK27AgtA5so3EW8jM0= github.com/grafana/grafana/apps/secret v0.0.0-20250731151929-0aac22a9e2d3 h1:16eaVEucbwis3TxS4CYZxxg5wfPAP/6u7Ji2+wbiHyk= github.com/grafana/grafana/apps/secret v0.0.0-20250731151929-0aac22a9e2d3/go.mod h1:pS2M5ILsHx9VNTM96glLtCjCVXHWyfGcT34WHvbbMtM= github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b h1:ei01IFqmnXkOrrVvsT3CYe+i5xYra3SCX7Wsu3PMsDU= github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:+H4Va9jDJlGQJjAN+OFD/hLx2I/yEzDRMQLaKecvgAc= -github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250725144121-b1592b5e36d2 h1:lvmcK9XOJUJiYhl2kH4nwAKOUdq+ug+ueIGqfKlip3E= -github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250725144121-b1592b5e36d2/go.mod h1:3ZgUe0E3rIhI026xF4DKFptOst/jpDHJ/Sn+bRODzI4= +github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956 h1:FzReg7qT3G+11ZsFFbtguMdx+w1w76bJCOOH1fWfDKs= +github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956/go.mod h1:RRvSjHH12/PnQaXraMO65jUhVu8n59mzvhfIMBETnV4= github.com/grafana/grafana/pkg/apiserver v0.0.0-20250627191313-2f1a6ae1712b h1:QyJLJn3xwFTIXu9KPZujsrIUN0X8DdiR9b2h75L0AfI= github.com/grafana/grafana/pkg/apiserver v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:6OKkPWDB8PetDXqMVMOWL35iTCEUdpATwwpuew0k8+o= github.com/grafana/grafana/pkg/promlib v0.0.8 h1:VUWsqttdf0wMI4j9OX9oNrykguQpZcruudDAFpJJVw0= diff --git a/apps/investigations/go.mod b/apps/investigations/go.mod index fe28636873c..d31f7a36956 100644 --- a/apps/investigations/go.mod +++ b/apps/investigations/go.mod @@ -5,7 +5,7 @@ go 1.24.5 require ( github.com/grafana/grafana v0.0.0-00010101000000-000000000000 github.com/grafana/grafana-app-sdk v0.40.2 - github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250725152715-69d3b9023cec + github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956 github.com/stretchr/testify v1.10.0 k8s.io/apimachinery v0.33.3 k8s.io/apiserver v0.33.3 diff --git a/apps/investigations/go.sum b/apps/investigations/go.sum index 00347e0818c..3a9e0faf11a 100644 --- a/apps/investigations/go.sum +++ b/apps/investigations/go.sum @@ -355,8 +355,10 @@ github.com/grafana/grafana-plugin-sdk-go v0.278.0 h1:5/rIYparLi02pofdaag8wnjspMM github.com/grafana/grafana-plugin-sdk-go v0.278.0/go.mod h1:+8NXT/XUJ/89GV6FxGQ366NZ3nU+cAXDMd0OUESF9H4= github.com/grafana/grafana/apps/dashboard v0.0.0-20250730164619-34019e5ec017 h1:Niy+KRDWHsUVqfhZQg0oZbAQFO6QcO6a4l9V/ouDEEs= github.com/grafana/grafana/apps/dashboard v0.0.0-20250730164619-34019e5ec017/go.mod h1:/iuseD/cEpXDiy7MpL+4qBFZ3H6esnUJTYzpoJMw9dw= -github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250725152715-69d3b9023cec h1:cg1GbDVZ7goqDrqoMzqeN4AeAcD271MGYjOvdVTDwfw= -github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250725152715-69d3b9023cec/go.mod h1:3ZgUe0E3rIhI026xF4DKFptOst/jpDHJ/Sn+bRODzI4= +github.com/grafana/grafana/apps/provisioning v0.0.0-20250801193518-9f4773c9a5a3 h1:MUyJnJE3GFj9QqA0sq7VOqWQkywYvH0/T4kwJfVQzJE= +github.com/grafana/grafana/apps/provisioning v0.0.0-20250801193518-9f4773c9a5a3/go.mod h1:qzFUVwLI1b5UIbVFxFydUYAsnOK27AgtA5so3EW8jM0= +github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956 h1:FzReg7qT3G+11ZsFFbtguMdx+w1w76bJCOOH1fWfDKs= +github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956/go.mod h1:RRvSjHH12/PnQaXraMO65jUhVu8n59mzvhfIMBETnV4= github.com/grafana/grafana/pkg/apiserver v0.0.0-20250627191313-2f1a6ae1712b h1:QyJLJn3xwFTIXu9KPZujsrIUN0X8DdiR9b2h75L0AfI= github.com/grafana/grafana/pkg/apiserver v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:6OKkPWDB8PetDXqMVMOWL35iTCEUdpATwwpuew0k8+o= github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= diff --git a/go.mod b/go.mod index f8c2a0a7b16..3ec9e8a1029 100644 --- a/go.mod +++ b/go.mod @@ -238,7 +238,7 @@ require ( github.com/grafana/grafana/apps/playlist v0.0.0-20250627191313-2f1a6ae1712b // @grafana/grafana-app-platform-squad github.com/grafana/grafana/apps/secret v0.0.0-20250731151929-0aac22a9e2d3 // @grafana/grafana-operator-experience-squad github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b // @grafana/grafana-app-platform-squad - github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250711114246-c9b2126c4ad5 // @grafana/grafana-app-platform-squad + github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956 // @grafana/grafana-app-platform-squad github.com/grafana/grafana/pkg/apiserver v0.0.0-20250627191313-2f1a6ae1712b // @grafana/grafana-app-platform-squad // This needs to be here for other projects that import grafana/grafana @@ -249,6 +249,8 @@ require ( github.com/thomaspoignant/go-feature-flag v1.42.0 // @grafana/grafana-backend-group ) +require github.com/grafana/grafana/apps/provisioning v0.0.0-20250801193518-9f4773c9a5a3 // @grafana/grafana-app-platform-squad + require ( cel.dev/expr v0.24.0 // indirect cloud.google.com/go v0.121.1 // indirect diff --git a/go.sum b/go.sum index d3ce4af5ca7..e6e246c13a2 100644 --- a/go.sum +++ b/go.sum @@ -1630,12 +1630,14 @@ github.com/grafana/grafana/apps/investigations v0.0.0-20250627191313-2f1a6ae1712 github.com/grafana/grafana/apps/investigations v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:8RlQ4U9lccPEBD/QxV4zyIMh9+lzjS/7xGpiqn3cHLY= github.com/grafana/grafana/apps/playlist v0.0.0-20250627191313-2f1a6ae1712b h1:elfpvk06igCjE0yL+/urc69UDOt1B/sPfdNg9X9kUMc= github.com/grafana/grafana/apps/playlist v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:fPtx6dwGm0PweQRVbgtthMapJMvXobBcORbndb7Dgd4= +github.com/grafana/grafana/apps/provisioning v0.0.0-20250801193518-9f4773c9a5a3 h1:MUyJnJE3GFj9QqA0sq7VOqWQkywYvH0/T4kwJfVQzJE= +github.com/grafana/grafana/apps/provisioning v0.0.0-20250801193518-9f4773c9a5a3/go.mod h1:qzFUVwLI1b5UIbVFxFydUYAsnOK27AgtA5so3EW8jM0= github.com/grafana/grafana/apps/secret v0.0.0-20250731151929-0aac22a9e2d3 h1:16eaVEucbwis3TxS4CYZxxg5wfPAP/6u7Ji2+wbiHyk= github.com/grafana/grafana/apps/secret v0.0.0-20250731151929-0aac22a9e2d3/go.mod h1:pS2M5ILsHx9VNTM96glLtCjCVXHWyfGcT34WHvbbMtM= github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b h1:ei01IFqmnXkOrrVvsT3CYe+i5xYra3SCX7Wsu3PMsDU= github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:+H4Va9jDJlGQJjAN+OFD/hLx2I/yEzDRMQLaKecvgAc= -github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250711114246-c9b2126c4ad5 h1:f4fopIH6eQRoZ/E7bstn69UtDAHleIdQ6DrdzEs++Ug= -github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250711114246-c9b2126c4ad5/go.mod h1:eAlOam2uWhrsEZlOoAr7XZ9hbBP7SyYGYn31/aQAPs8= +github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956 h1:FzReg7qT3G+11ZsFFbtguMdx+w1w76bJCOOH1fWfDKs= +github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956/go.mod h1:RRvSjHH12/PnQaXraMO65jUhVu8n59mzvhfIMBETnV4= github.com/grafana/grafana/pkg/apiserver v0.0.0-20250627191313-2f1a6ae1712b h1:QyJLJn3xwFTIXu9KPZujsrIUN0X8DdiR9b2h75L0AfI= github.com/grafana/grafana/pkg/apiserver v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:6OKkPWDB8PetDXqMVMOWL35iTCEUdpATwwpuew0k8+o= github.com/grafana/grafana/pkg/promlib v0.0.8 h1:VUWsqttdf0wMI4j9OX9oNrykguQpZcruudDAFpJJVw0= diff --git a/pkg/services/sqlstore/sqlutil/sqlutil.go b/pkg/services/sqlstore/sqlutil/sqlutil.go index 7d3d09a5ff3..8506acdab79 100644 --- a/pkg/services/sqlstore/sqlutil/sqlutil.go +++ b/pkg/services/sqlstore/sqlutil/sqlutil.go @@ -22,11 +22,6 @@ type TestDB struct { DriverName string ConnStr string Path string - Host string - Port string - User string - Password string - Database string Cleanup func() } @@ -137,11 +132,6 @@ func mySQLTestDB() (*TestDB, error) { return &TestDB{ DriverName: "mysql", ConnStr: conn_str, - Host: host, - Port: port, - User: "grafana", - Password: "password", - Database: "grafana_tests", Cleanup: func() {}, }, nil } @@ -159,11 +149,6 @@ func postgresTestDB() (*TestDB, error) { return &TestDB{ DriverName: "postgres", ConnStr: connStr, - Host: host, - Port: port, - User: "grafanatest", - Password: "grafanatest", - Database: "grafanatest", Cleanup: func() {}, }, nil } diff --git a/pkg/tests/apis/provisioning/provisioning_test.go b/pkg/tests/apis/provisioning/provisioning_test.go index a7b28d877ce..6ed7dbb5702 100644 --- a/pkg/tests/apis/provisioning/provisioning_test.go +++ b/pkg/tests/apis/provisioning/provisioning_test.go @@ -161,21 +161,14 @@ func TestIntegrationProvisioning_CreatingAndGetting(t *testing.T) { // Viewer can see settings listing t.Run("viewer has access to list", func(t *testing.T) { settings := &provisioning.RepositoryViewList{} - // Wait for unified storage to make the data available - require.Eventually(t, func() bool { - rsp := helper.ViewerREST.Get(). - Namespace("default"). - Suffix("settings"). - Do(context.Background()) - if rsp.Error() != nil { - return false - } - err := rsp.Into(settings) - if err != nil { - return false - } - return len(settings.Items) == len(inputFiles) - }, time.Second*10, time.Millisecond*100, "Expected settings to have len(inputFiles) items") + rsp := helper.ViewerREST.Get(). + Namespace("default"). + Suffix("settings"). + Do(context.Background()) + require.NoError(t, rsp.Error()) + err := rsp.Into(settings) + require.NoError(t, err) + require.Len(t, settings.Items, len(inputFiles)) // FIXME: this should be an enterprise integration test if extensions.IsEnterprise { @@ -1832,10 +1825,8 @@ func TestIntegrationProvisioning_MoveResources(t *testing.T) { // Verify dashboard still exists in Grafana with same content but may have updated path references helper.SyncAndWait(t, repo, nil) - require.Eventually(t, func() bool { - _, err = helper.DashboardsV1.Resource.Get(ctx, allPanelsUID, metav1.GetOptions{}) - return err == nil - }, 10*time.Second, 100*time.Millisecond, "dashboard should still exist in Grafana after move") // Using Eventually to account for potential delays in dashboards APIs. + _, err = helper.DashboardsV1.Resource.Get(ctx, allPanelsUID, metav1.GetOptions{}) + require.NoError(t, err, "dashboard should still exist in Grafana after move") }) t.Run("move file to nested path without ref", func(t *testing.T) { diff --git a/pkg/tests/testinfra/testinfra.go b/pkg/tests/testinfra/testinfra.go index 56f9f3000e2..eb9b460c6b8 100644 --- a/pkg/tests/testinfra/testinfra.go +++ b/pkg/tests/testinfra/testinfra.go @@ -13,7 +13,6 @@ import ( "time" "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/services/sqlstore/sqlutil" "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -86,20 +85,6 @@ func StartGrafanaEnv(t *testing.T, grafDir, cfgPath string) (string, *server.Tes err = featuremgmt.InitOpenFeatureWithCfg(cfg) require.NoError(t, err) - - // Use proper database type based on the environment variable GRAFANA_TEST_DB in tests - testDB, err := sqlutil.GetTestDB(sqlutil.GetTestDBType()) - require.NoError(t, err) - t.Cleanup(testDB.Cleanup) - - dbCfg := cfg.Raw.Section("database") - dbCfg.Key("type").SetValue(testDB.DriverName) - dbCfg.Key("host").SetValue(testDB.Host) - dbCfg.Key("port").SetValue(testDB.Port) - dbCfg.Key("user").SetValue(testDB.User) - dbCfg.Key("password").SetValue(testDB.Password) - dbCfg.Key("name").SetValue(testDB.Database) - env, err := server.InitializeForTest(t, t, cfg, serverOpts, apiServerOpts) require.NoError(t, err) From cbf256120e955a17f517a183588b7536e54e3342 Mon Sep 17 00:00:00 2001 From: Yuri Tseretyan Date: Fri, 1 Aug 2025 17:34:31 -0400 Subject: [PATCH 41/89] Revert "Alerting: Remote Alertmanager to calculate hash of the request payload instead of just the configuration" (#109086) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revert "Alerting: Remote Alertmanager to calculate hash of the request payloa…" This reverts commit 32434810e16e9126d05ea9cd5f96493f3e8b2d0f. --- pkg/services/ngalert/remote/alertmanager.go | 151 ++++++++++-------- .../ngalert/remote/alertmanager_test.go | 60 ++++--- .../client/alertmanager_configuration.go | 16 +- pkg/services/ngalert/remote/client/mimir.go | 31 ++-- 4 files changed, 156 insertions(+), 102 deletions(-) diff --git a/pkg/services/ngalert/remote/alertmanager.go b/pkg/services/ngalert/remote/alertmanager.go index 8329c7bb8de..7c1e1dd4060 100644 --- a/pkg/services/ngalert/remote/alertmanager.go +++ b/pkg/services/ngalert/remote/alertmanager.go @@ -2,10 +2,10 @@ package remote import ( "context" + "crypto/md5" "encoding/base64" "encoding/json" "fmt" - "hash/fnv" "net/http" "net/url" "strings" @@ -16,12 +16,12 @@ import ( "github.com/grafana/alerting/definition" alertingModels "github.com/grafana/alerting/models" alertingNotify "github.com/grafana/alerting/notify" - "github.com/grafana/alerting/utils/hash" amalert "github.com/prometheus/alertmanager/api/v2/client/alert" amalertgroup "github.com/prometheus/alertmanager/api/v2/client/alertgroup" amgeneral "github.com/prometheus/alertmanager/api/v2/client/general" amsilence "github.com/prometheus/alertmanager/api/v2/client/silence" "github.com/prometheus/client_golang/prometheus" + "gopkg.in/yaml.v3" "github.com/grafana/grafana/pkg/infra/log" @@ -73,9 +73,6 @@ type Alertmanager struct { amClient *remoteClient.Alertmanager mimirClient remoteClient.MimirClient - - promoteConfig bool - externalURL string } type AlertmanagerConfig struct { @@ -130,10 +127,13 @@ func NewAlertmanager(ctx context.Context, cfg AlertmanagerConfig, store stateSto logger := log.New("ngalert.remote.alertmanager") mcCfg := &remoteClient.Config{ - Logger: logger, - Password: cfg.BasicAuthPassword, - TenantID: cfg.TenantID, - URL: u, + Logger: logger, + Password: cfg.BasicAuthPassword, + TenantID: cfg.TenantID, + URL: u, + PromoteConfig: cfg.PromoteConfig, + ExternalURL: cfg.ExternalURL, + Smtp: cfg.SmtpConfig, } mc, err := remoteClient.New(mcCfg, metrics, tracer) if err != nil { @@ -188,10 +188,7 @@ func NewAlertmanager(ctx context.Context, cfg AlertmanagerConfig, store stateSto syncInterval: cfg.SyncInterval, tenantID: cfg.TenantID, url: cfg.URL, - - externalURL: cfg.ExternalURL, - promoteConfig: cfg.PromoteConfig, - smtp: cfg.SmtpConfig, + smtp: cfg.SmtpConfig, } // Parse the default configuration once and remember its hash so we can compare it later. @@ -199,11 +196,15 @@ func NewAlertmanager(ctx context.Context, cfg AlertmanagerConfig, store stateSto // (grouping, group timing, time intervals etc) changes the autogenerated configuration. // The `default` flag is sent to the remote Alertmanager for informational purposes, so we can tolerate this. err = func() error { - defaultCfg, err := am.buildConfiguration(ctx, []byte(cfg.DefaultConfig), 0) + defaultCfg, err := am.buildConfiguration(ctx, []byte(cfg.DefaultConfig)) if err != nil { return fmt.Errorf("unable to build default configuration: %w", err) } - am.defaultConfigHash = defaultCfg.Hash + rawDefaultCfg, err := json.Marshal(defaultCfg) + if err != nil { + return fmt.Errorf("unable to marshal default configuration: %w", err) + } + am.defaultConfigHash = fmt.Sprintf("%x", md5.Sum(rawDefaultCfg)) return nil }() if err != nil { @@ -264,16 +265,22 @@ func (am *Alertmanager) checkReadiness(ctx context.Context) error { // CompareAndSendConfiguration checks whether a given configuration is being used by the remote Alertmanager. // If not, it sends the configuration to the remote Alertmanager. func (am *Alertmanager) CompareAndSendConfiguration(ctx context.Context, config *models.AlertConfiguration) error { - payload, err := am.buildConfiguration(ctx, []byte(config.AlertmanagerConfiguration), config.CreatedAt) + payload, err := am.buildConfiguration(ctx, []byte(config.AlertmanagerConfiguration)) if err != nil { return fmt.Errorf("unable to build configuration: %w", err) } + rawPayload, err := json.Marshal(payload) + if err != nil { + return fmt.Errorf("unable to marshal decrypted configuration: %w", err) + } + configHash := fmt.Sprintf("%x", md5.Sum(rawPayload)) + // Send the configuration only if we need to. - if !am.shouldSendConfig(ctx, payload.Hash) { + if !am.shouldSendConfig(ctx, configHash) { return nil } - return am.sendConfiguration(ctx, payload) + return am.sendConfiguration(ctx, payload, configHash, config.CreatedAt, am.isDefaultConfiguration(configHash)) } func (am *Alertmanager) isDefaultConfiguration(configHash string) bool { @@ -296,31 +303,31 @@ func decrypter(ctx context.Context, crypto Crypto) models.DecryptFn { // buildConfiguration takes a raw Alertmanager configuration and returns a config that the remote Alertmanager can use. // It parses the initial configuration, adds auto-generated routes, decrypts receivers, and merges the extra configs. -func (am *Alertmanager) buildConfiguration(ctx context.Context, raw []byte, createdAtEpoch int64) (remoteClient.UserGrafanaConfig, error) { +func (am *Alertmanager) buildConfiguration(ctx context.Context, raw []byte) (remoteClient.GrafanaAlertmanagerConfig, error) { c, err := notifier.Load(raw) if err != nil { - return remoteClient.UserGrafanaConfig{}, err + return remoteClient.GrafanaAlertmanagerConfig{}, err } // Add auto-generated routes and decrypt before comparing. if err := am.autogenFn(ctx, am.log, am.orgID, &c.AlertmanagerConfig, true); err != nil { - return remoteClient.UserGrafanaConfig{}, err + return remoteClient.GrafanaAlertmanagerConfig{}, err } // Decrypt the receivers in the configuration. decryptedReceivers, err := legacy_storage.DecryptedReceivers(c.AlertmanagerConfig.Receivers, decrypter(ctx, am.crypto)) if err != nil { - return remoteClient.UserGrafanaConfig{}, fmt.Errorf("unable to decrypt receivers: %w", err) + return remoteClient.GrafanaAlertmanagerConfig{}, fmt.Errorf("unable to decrypt receivers: %w", err) } c.AlertmanagerConfig.Receivers = decryptedReceivers if err := am.crypto.DecryptExtraConfigs(ctx, c); err != nil { - return remoteClient.UserGrafanaConfig{}, fmt.Errorf("unable to decrypt extra configs: %w", err) + return remoteClient.GrafanaAlertmanagerConfig{}, fmt.Errorf("unable to decrypt extra configs: %w", err) } mergeResult, err := c.GetMergedAlertmanagerConfig() if err != nil { - return remoteClient.UserGrafanaConfig{}, fmt.Errorf("unable to get merged Alertmanager configuration: %w", err) + return remoteClient.GrafanaAlertmanagerConfig{}, fmt.Errorf("unable to get merged Alertmanager configuration: %w", err) } var templates []definition.PostableApiTemplate @@ -328,31 +335,22 @@ func (am *Alertmanager) buildConfiguration(ctx context.Context, raw []byte, crea templates = definition.TemplatesMapToPostableAPITemplates(c.ExtraConfigs[0].TemplateFiles, definition.MimirTemplateKind) } - payload := remoteClient.UserGrafanaConfig{ - GrafanaAlertmanagerConfig: remoteClient.GrafanaAlertmanagerConfig{ - TemplateFiles: c.TemplateFiles, - AlertmanagerConfig: mergeResult.Config, - Templates: templates, - }, - CreatedAt: createdAtEpoch, - Promoted: am.promoteConfig, - ExternalURL: am.externalURL, - SmtpConfig: am.smtp, - } - - cfgHash, err := calculateUserGrafanaConfigHash(payload) - if err != nil { - am.log.Error("Unable to calculate hash of the configuration. Using the empty string", "error", err) - cfgHash = "" - } - payload.Hash = cfgHash - payload.Default = am.isDefaultConfiguration(cfgHash) - return payload, nil + return remoteClient.GrafanaAlertmanagerConfig{ + TemplateFiles: c.TemplateFiles, + AlertmanagerConfig: mergeResult.Config, + Templates: templates, + }, nil } -func (am *Alertmanager) sendConfiguration(ctx context.Context, cfg remoteClient.UserGrafanaConfig) error { +func (am *Alertmanager) sendConfiguration(ctx context.Context, cfg remoteClient.GrafanaAlertmanagerConfig, hash string, createdAt int64, isDefault bool) error { am.metrics.ConfigSyncsTotal.Inc() - if err := am.mimirClient.CreateGrafanaAlertmanagerConfig(ctx, &cfg); err != nil { + if err := am.mimirClient.CreateGrafanaAlertmanagerConfig( + ctx, + cfg, + hash, + createdAt, + isDefault, + ); err != nil { am.metrics.ConfigSyncErrorsTotal.Inc() return err } @@ -424,25 +422,40 @@ func (am *Alertmanager) SaveAndApplyConfig(ctx context.Context, cfg *apimodels.P return err } - payload, err := am.buildConfiguration(ctx, rawCopy, time.Now().Unix()) + payload, err := am.buildConfiguration(ctx, rawCopy) if err != nil { return fmt.Errorf("unable to build configuration: %w", err) } - return am.sendConfiguration(ctx, payload) + rawCfg, err := json.Marshal(payload) + if err != nil { + return err + } + hash := fmt.Sprintf("%x", md5.Sum(rawCfg)) + + return am.sendConfiguration(ctx, payload, hash, time.Now().Unix(), false) } // SaveAndApplyDefaultConfig sends the default Grafana Alertmanager configuration to the remote Alertmanager. func (am *Alertmanager) SaveAndApplyDefaultConfig(ctx context.Context) error { am.log.Debug("Sending default configuration to a remote Alertmanager", "url", am.url) - payload, err := am.buildConfiguration(ctx, []byte(am.defaultConfig), time.Now().Unix()) + payload, err := am.buildConfiguration(ctx, []byte(am.defaultConfig)) if err != nil { return fmt.Errorf("unable to build default configuration: %w", err) } - payload.Default = true // override default status + + rawCfg, err := json.Marshal(payload) + if err != nil { + return err + } + hash := fmt.Sprintf("%x", md5.Sum(rawCfg)) + return am.sendConfiguration( ctx, payload, + hash, + time.Now().Unix(), + true, ) } @@ -683,29 +696,37 @@ func (am *Alertmanager) getFullState(ctx context.Context) (string, error) { // shouldSendConfig compares the remote Alertmanager configuration with our local one. // It returns true if the configurations are different. func (am *Alertmanager) shouldSendConfig(ctx context.Context, hash string) bool { - if hash == "" { // empty hash means that something went wrong while calculating it. In this case, always send the config. - return true - } rc, err := am.mimirClient.GetGrafanaAlertmanagerConfig(ctx) if err != nil { // Log the error and return true so we try to upload our config anyway. am.log.Warn("Unable to get the remote Alertmanager configuration for comparison, sending the configuration without comparing", "err", err) return true } - if rc.Hash != hash { - am.log.Debug("Hash of the remote Alertmanager configuration is different, sending the configuration", "remote", rc.Hash, "local", hash) + + if rc.Promoted != am.mimirClient.ShouldPromoteConfig() { return true } - return false -} -func calculateUserGrafanaConfigHash(config remoteClient.UserGrafanaConfig) (string, error) { - // Ignore some fields when calculating the hash. Make sure the original struct is not modified after that. - config.Default = false - config.CreatedAt = 0 // ignore createdAt to support comparison with hash of default config - config.Hash = "" + // Compare SMTP configs. + if rc.SmtpConfig.EhloIdentity != am.smtp.EhloIdentity || + rc.SmtpConfig.Password != am.smtp.Password || + rc.SmtpConfig.FromAddress != am.smtp.FromAddress || + rc.SmtpConfig.FromName != am.smtp.FromName || + rc.SmtpConfig.Host != am.smtp.Host || + rc.SmtpConfig.SkipVerify != am.smtp.SkipVerify || + rc.SmtpConfig.StartTLSPolicy != am.smtp.StartTLSPolicy || + len(rc.SmtpConfig.StaticHeaders) != len(am.smtp.StaticHeaders) || + rc.SmtpConfig.User != am.smtp.User { + am.log.Debug("SMTP config is different, sending the configuration to the remote Alertmanager") + return true + } - hasher := fnv.New64a() - hash.DeepHashObject(hasher, &config) - return fmt.Sprintf("%x", hasher.Sum64()), nil + for k, v := range rc.SmtpConfig.StaticHeaders { + if value, ok := am.smtp.StaticHeaders[k]; !ok || v != value { + am.log.Debug("SMTP static headers are different, sending the configuration to the remote Alertmanager") + return true + } + } + + return rc.Hash != hash } diff --git a/pkg/services/ngalert/remote/alertmanager_test.go b/pkg/services/ngalert/remote/alertmanager_test.go index 10ea5e45eaf..6ce6abb8994 100644 --- a/pkg/services/ngalert/remote/alertmanager_test.go +++ b/pkg/services/ngalert/remote/alertmanager_test.go @@ -19,13 +19,10 @@ import ( "time" "github.com/go-openapi/strfmt" - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" amv2 "github.com/prometheus/alertmanager/api/v2/models" "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/pkg/labels" "github.com/prometheus/client_golang/prometheus" - common_config "github.com/prometheus/common/config" "github.com/stretchr/testify/require" alertingClusterPB "github.com/grafana/alerting/cluster/clusterpb" @@ -504,6 +501,15 @@ func TestCompareAndSendConfiguration(t *testing.T) { AlertmanagerConfig: testAutogenRoutes.AlertmanagerConfig, } + // Calculate hashes for expected configurations + cfgWithDecryptedSecretBytes, err := json.Marshal(cfgWithDecryptedSecret) + require.NoError(t, err) + cfgWithDecryptedSecretHash := fmt.Sprintf("%x", md5.Sum(cfgWithDecryptedSecretBytes)) + + cfgWithAutogenRoutesBytes, err := json.Marshal(cfgWithAutogenRoutes) + require.NoError(t, err) + cfgWithAutogenRoutesHash := fmt.Sprintf("%x", md5.Sum(cfgWithAutogenRoutesBytes)) + cfgWithExtraUnmergedBytes, err := testData.ReadFile(path.Join("test-data", "config-with-extra.json")) require.NoError(t, err) cfgWithExtraUnmerged, err := notifier.Load(cfgWithExtraUnmergedBytes) @@ -515,6 +521,9 @@ func TestCompareAndSendConfiguration(t *testing.T) { AlertmanagerConfig: r.Config, Templates: definition.TemplatesMapToPostableAPITemplates(cfgWithExtraUnmerged.ExtraConfigs[0].TemplateFiles, definition.MimirTemplateKind), } + cfgWithExtraMergedBytes, err := json.Marshal(cfgWithExtraMerged) + require.NoError(t, err) + cfgWithExtraMergedHash := fmt.Sprintf("%x", md5.Sum(cfgWithExtraMergedBytes)) tests := []struct { name string @@ -557,6 +566,7 @@ func TestCompareAndSendConfiguration(t *testing.T) { NoopAutogenFn, &client.UserGrafanaConfig{ GrafanaAlertmanagerConfig: cfgWithDecryptedSecret, + Hash: cfgWithDecryptedSecretHash, }, nil, }, @@ -566,6 +576,7 @@ func TestCompareAndSendConfiguration(t *testing.T) { testAutogenFn, &client.UserGrafanaConfig{ GrafanaAlertmanagerConfig: cfgWithAutogenRoutes, + Hash: cfgWithAutogenRoutesHash, }, nil, }, @@ -575,6 +586,7 @@ func TestCompareAndSendConfiguration(t *testing.T) { autogenFn: NoopAutogenFn, expCfg: &client.UserGrafanaConfig{ GrafanaAlertmanagerConfig: cfgWithExtraMerged, + Hash: cfgWithExtraMergedHash, }, }, } @@ -602,26 +614,9 @@ func TestCompareAndSendConfiguration(t *testing.T) { err = am.CompareAndSendConfiguration(ctx, &cfg) if len(test.expErrContains) == 0 { require.NoError(tt, err) - - var gotCfg client.UserGrafanaConfig - require.NoError(tt, json.Unmarshal([]byte(got), &gotCfg)) - - require.NotEmpty(tt, gotCfg.Hash) - require.Empty(tt, cmp.Diff(test.expCfg, &gotCfg, - cmpopts.IgnoreFields(client.UserGrafanaConfig{}, "Hash"), // do not compare hashes because the config is processed slightly different: empty maps are nils. - cmpopts.EquateEmpty(), - cmpopts.IgnoreUnexported( - time.Location{}, - labels.Matcher{}, - common_config.ProxyConfig{}))) - - got1 := got - got = "" - err = am.CompareAndSendConfiguration(ctx, &cfg) + rawCfg, err := json.Marshal(test.expCfg) require.NoError(tt, err) - - got2 := got - require.Equalf(tt, got1, got2, "Configuration is not idempotent") + require.JSONEq(tt, string(rawCfg), got) return } for _, expErr := range test.expErrContains { @@ -820,7 +815,12 @@ receivers: require.NotNil(t, extraReceiver) require.Len(t, extraReceiver.EmailConfigs, 1) require.Equal(t, "alerts@grafana.com", extraReceiver.EmailConfigs[0].To) - require.NotEmpty(t, configSent.Hash) + + // Verify the config hash + expectedConfigBytes, err := json.Marshal(configSent.GrafanaAlertmanagerConfig) + require.NoError(t, err) + expectedHash := fmt.Sprintf("%x", md5.Sum(expectedConfigBytes)) + require.Equal(t, expectedHash, configSent.Hash) } func TestCompareAndSendConfigurationWithExtraConfigs(t *testing.T) { @@ -934,7 +934,10 @@ receivers: require.True(t, found) // Verify the config hash - require.NotEmpty(t, configSent.Hash) + expectedConfigBytes, err := json.Marshal(configSent.GrafanaAlertmanagerConfig) + require.NoError(t, err) + expectedHash := fmt.Sprintf("%x", md5.Sum(expectedConfigBytes)) + require.Equal(t, expectedHash, configSent.Hash) } func TestIntegrationRemoteAlertmanagerConfiguration(t *testing.T) { @@ -958,10 +961,11 @@ func TestIntegrationRemoteAlertmanagerConfiguration(t *testing.T) { DefaultConfig: defaultGrafanaConfig, } + testConfigHash := fmt.Sprintf("%x", md5.Sum([]byte(testGrafanaConfig))) testConfigCreatedAt := time.Now().Unix() testConfig := &ngmodels.AlertConfiguration{ AlertmanagerConfiguration: testGrafanaConfig, - ConfigurationHash: "", + ConfigurationHash: testConfigHash, ConfigurationVersion: "v2", CreatedAt: testConfigCreatedAt, OrgID: 1, @@ -1008,6 +1012,7 @@ func TestIntegrationRemoteAlertmanagerConfiguration(t *testing.T) { rawCfg, err := json.Marshal(config.GrafanaAlertmanagerConfig) require.NoError(t, err) require.JSONEq(t, testGrafanaConfig, string(rawCfg)) + require.Equal(t, testConfigHash, config.Hash) require.Equal(t, testConfigCreatedAt, config.CreatedAt) require.Equal(t, testConfig.Default, config.Default) @@ -1033,6 +1038,7 @@ func TestIntegrationRemoteAlertmanagerConfiguration(t *testing.T) { rawCfg, err := json.Marshal(config.GrafanaAlertmanagerConfig) require.NoError(t, err) require.JSONEq(t, testGrafanaConfig, string(rawCfg)) + require.Equal(t, testConfigHash, config.Hash) require.Equal(t, testConfigCreatedAt, config.CreatedAt) require.False(t, config.Default) @@ -1079,6 +1085,9 @@ func TestIntegrationRemoteAlertmanagerConfiguration(t *testing.T) { require.JSONEq(t, testGrafanaConfigWithSecret, string(got)) + // Verify that the hash is calculated from the final configuration, including simplified routing + expectedHash := fmt.Sprintf("%x", md5.Sum(got)) + require.Equal(t, expectedHash, config.Hash, "Hash should be calculated from the final processed configuration") require.False(t, config.Default) // An error while adding auto-generated rutes should be returned. @@ -1105,6 +1114,7 @@ func TestIntegrationRemoteAlertmanagerConfiguration(t *testing.T) { require.NoError(t, err) require.JSONEq(t, string(want), string(got)) + require.Equal(t, fmt.Sprintf("%x", md5.Sum(want)), config.Hash) require.True(t, config.Default) // An error while adding auto-generated rutes should be returned. diff --git a/pkg/services/ngalert/remote/client/alertmanager_configuration.go b/pkg/services/ngalert/remote/client/alertmanager_configuration.go index a53132a8812..b812c146687 100644 --- a/pkg/services/ngalert/remote/client/alertmanager_configuration.go +++ b/pkg/services/ngalert/remote/client/alertmanager_configuration.go @@ -39,6 +39,10 @@ type UserGrafanaConfig struct { SmtpConfig SmtpConfig `json:"smtp_config"` } +func (mc *Mimir) ShouldPromoteConfig() bool { + return mc.promoteConfig +} + func (mc *Mimir) GetGrafanaAlertmanagerConfig(ctx context.Context) (*UserGrafanaConfig, error) { gc := &UserGrafanaConfig{} response := successResponse{ @@ -58,8 +62,16 @@ func (mc *Mimir) GetGrafanaAlertmanagerConfig(ctx context.Context) (*UserGrafana return gc, nil } -func (mc *Mimir) CreateGrafanaAlertmanagerConfig(ctx context.Context, cfg *UserGrafanaConfig) error { - payload, err := definition.MarshalJSONWithSecrets(cfg) +func (mc *Mimir) CreateGrafanaAlertmanagerConfig(ctx context.Context, cfg GrafanaAlertmanagerConfig, hash string, createdAt int64, isDefault bool) error { + payload, err := definition.MarshalJSONWithSecrets(&UserGrafanaConfig{ + GrafanaAlertmanagerConfig: cfg, + Hash: hash, + CreatedAt: createdAt, + Default: isDefault, + Promoted: mc.promoteConfig, + ExternalURL: mc.externalURL, + SmtpConfig: mc.smtpConfig, + }) if err != nil { return err } diff --git a/pkg/services/ngalert/remote/client/mimir.go b/pkg/services/ngalert/remote/client/mimir.go index d8f9a51f327..1533e24c208 100644 --- a/pkg/services/ngalert/remote/client/mimir.go +++ b/pkg/services/ngalert/remote/client/mimir.go @@ -30,21 +30,26 @@ type MimirClient interface { DeleteGrafanaAlertmanagerState(ctx context.Context) error GetGrafanaAlertmanagerConfig(ctx context.Context) (*UserGrafanaConfig, error) - CreateGrafanaAlertmanagerConfig(ctx context.Context, config *UserGrafanaConfig) error + CreateGrafanaAlertmanagerConfig(ctx context.Context, configuration GrafanaAlertmanagerConfig, hash string, createdAt int64, isDefault bool) error DeleteGrafanaAlertmanagerConfig(ctx context.Context) error TestTemplate(ctx context.Context, c alertingNotify.TestTemplatesConfigBodyParams) (*alertingNotify.TestTemplatesResults, error) TestReceivers(ctx context.Context, c alertingNotify.TestReceiversConfigBodyParams) (*alertingNotify.TestReceiversResult, int, error) + ShouldPromoteConfig() bool + // Mimir implements an extended version of the receivers API under a different path. GetReceivers(ctx context.Context) ([]apimodels.Receiver, error) } type Mimir struct { - client client.Requester - endpoint *url.URL - logger log.Logger - metrics *metrics.RemoteAlertmanager + client client.Requester + endpoint *url.URL + logger log.Logger + metrics *metrics.RemoteAlertmanager + promoteConfig bool + externalURL string + smtpConfig SmtpConfig } type SmtpConfig struct { @@ -64,7 +69,10 @@ type Config struct { TenantID string Password string - Logger log.Logger + Logger log.Logger + PromoteConfig bool + ExternalURL string + Smtp SmtpConfig } // successResponse represents a successful response from the Mimir API. @@ -102,10 +110,13 @@ func New(cfg *Config, metrics *metrics.RemoteAlertmanager, tracer tracing.Tracer trc := client.NewTracedClient(tc, tracer, "remote.alertmanager.client") return &Mimir{ - endpoint: cfg.URL, - client: trc, - logger: cfg.Logger, - metrics: metrics, + endpoint: cfg.URL, + client: trc, + logger: cfg.Logger, + metrics: metrics, + promoteConfig: cfg.PromoteConfig, + externalURL: cfg.ExternalURL, + smtpConfig: cfg.Smtp, }, nil } From a5ceac4474318c5bc9220313d7d55df7f586b714 Mon Sep 17 00:00:00 2001 From: Paul Marbach Date: Fri, 1 Aug 2025 19:56:12 -0400 Subject: [PATCH 42/89] TableNG: Markdown cell, plus auto row height (#107549) * TableNG: Markdown cell, plus custom row height * tab indentation in cue file * fix i18n * trying an auto height with the updated RDG * get auto cellHeight working * i18n updates * hoor disable_sanitize_html flag in MarkdownCell * update react-data-grid version to attempt to support page up and down * removing custom height * use the latest experimental RDG with paging up and down * TableNG: Wrap text for DataLinks and Pills; groundwork for max wrap length * disable editing max wrapped lines for now * disable wrap text line limit e2e * new i18n extract after commenting out input * wip * kill max wrapped lines for now * more cleanup * remove targeting classes added for max wrapped lines * fix Pill test * couple more style cleanups * fix e2es given these updates * add a couple tests * wip: tests * add tests * bump up capital letters in lorem ipsum * fix copy-pasta mistake * whoops, mis-merged the selector * use a local count instead of getCellLinks * use react-data-grid on react-18 branch * fix linting on test * gdev dashboard and smoketest for Markdown table * remove cellHeightCustom * reorganize in light of recent and upcoming changes * remove one more reference to cellHeightCustom * put getDefaultRowHeight back into a util * clean up test * swap cell height back to a radio * revert ImageCell change, we'll do it in the getStyles PR * don't memo defaultRowHeight * final couple of style cleanups * different approach to managing the auto height part of this * kill console.log * update i18n * reorganized once more * i18n * guard against rowHeight being auto for virtualization * may as well memoize the defaultRowHeight * get rid of the enableVirtualization initializer thing * fixes from CI * fix test * fix test * just omit third arg for that test * remove nonsensical test case * this file didn't get re-gen'd * fixes from review * row expander doesn't need height * remove console.log * fix e2e after we fixed pagination toggle bug --- .betterer.results | 3 + .../panel-table/table_markdown.json | 126 ++++++++++++++++++ devenv/jsonnet/dev-dashboards.libsonnet | 1 + .../panels-suite/table-kitchenSink.spec.ts | 4 +- .../panels-suite/table-markdown.spec.ts | 25 ++++ .../grafana-schema/src/common/common.gen.ts | 8 +- packages/grafana-schema/src/common/table.cue | 9 +- packages/grafana-ui/package.json | 2 +- .../Table/TableNG/Cells/MarkdownCell.tsx | 17 +++ .../Table/TableNG/Cells/RowExpander.tsx | 7 +- .../Table/TableNG/Cells/renderers.tsx | 15 ++- .../src/components/Table/TableNG/TableNG.tsx | 75 +++++++++-- .../src/components/Table/TableNG/hooks.ts | 18 ++- .../src/components/Table/TableNG/types.ts | 10 +- .../components/Table/TableNG/utils.test.ts | 49 +++++-- .../src/components/Table/TableNG/utils.ts | 14 +- .../table/table-new/PaginationEditor.tsx | 5 +- .../table/table-new/TableCellOptionEditor.tsx | 5 + .../panel/table/table-new/TablePanel.tsx | 4 + .../cells/MarkdownCellOptionsEditor.tsx | 39 ++++++ public/locales/en-US/grafana.json | 8 ++ yarn.lock | 8 +- 22 files changed, 394 insertions(+), 58 deletions(-) create mode 100644 devenv/dev-dashboards/panel-table/table_markdown.json create mode 100644 e2e-playwright/panels-suite/table-markdown.spec.ts create mode 100644 packages/grafana-ui/src/components/Table/TableNG/Cells/MarkdownCell.tsx create mode 100644 public/app/plugins/panel/table/table-new/cells/MarkdownCellOptionsEditor.tsx diff --git a/.betterer.results b/.betterer.results index 0493a87d6d3..b11063eae47 100644 --- a/.betterer.results +++ b/.betterer.results @@ -3932,6 +3932,9 @@ exports[`better eslint`] = { [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"], [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"] ], + "public/app/plugins/panel/table/table-new/cells/MarkdownCellOptionsEditor.tsx:5381": [ + [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"] + ], "public/app/plugins/panel/table/table-new/cells/SparklineCellOptionsEditor.tsx:5381": [ [0, 0, 0, "\'VerticalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"], [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"] diff --git a/devenv/dev-dashboards/panel-table/table_markdown.json b/devenv/dev-dashboards/panel-table/table_markdown.json new file mode 100644 index 00000000000..b6aa28ca3b0 --- /dev/null +++ b/devenv/dev-dashboards/panel-table/table_markdown.json @@ -0,0 +1,126 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1735, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false, + "wrapHeaderText": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "markdown" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "type": "markdown", + "dynamicHeight": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 18, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "cellHeight": "lg", + "footer": { + "enablePagination": true, + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "12.1.0-pre", + "targets": [ + { + "csvContent": "id,markdown\n1,\"
\n
Definition list
\n
Is something people use sometimes.
\n
Markdown in HTML
\n
Does *not* work **very** well. Use HTML tags.
\n
\"\n2,\"Three or more...\n\n---\n\nHyphens\n\n***\n\nAsterisks\n\n___\n\nUnderscores\"\n3,\"Here's a line for us to start with.\n\nThis line is separated from the one above by two newlines, so it will be a *separate paragraph*.\n\nThis line is also a separate paragraph, but...\nThis line is only separated by a single newline, so it's a separate line in the *same paragraph*.\"\n4,\"red, green, blue\"\n5,\"\"\n6,\"[Link](https://grafana.com), or HTML link\"\n7,\"1. foo\n1. bar\n - baz\n * bim\n3. bip\"\n8,\"# heading 1\n## heading 2\n### heading 3\n#### heading 4\n##### heading 5\n###### heading 6\"\n9,\"Emphasis, aka italics, with *asterisks* or _underscores_.\n\nStrong emphasis, aka bold, with **asterisks** or __underscores__.\n\nCombined emphasis with **asterisks and _underscores_**.\n\nStrikethrough uses two tildes. ~~Scratch this.~~\n\nunderline does require an HTML element tho.\"\n10,\"```javascript\nvar s = 'JavaScript syntax highlighting';\nalert(s);\n```\"\n11,\"\n| Month | Savings |\n| -------- | ------- |\n| I heard | $250 |\n| you like | $80 |\n| tables | $365 |\"\n", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Markdown Table", + "type": "table" + } + ], + "preload": false, + "schemaVersion": 41, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Panel Tests - Table - Markdown", + "uid": "2769f5d8-0094-4ac4-a4f0-f68f620339cc", + "version": 1 +} diff --git a/devenv/jsonnet/dev-dashboards.libsonnet b/devenv/jsonnet/dev-dashboards.libsonnet index d16f9b96c84..c050297d430 100644 --- a/devenv/jsonnet/dev-dashboards.libsonnet +++ b/devenv/jsonnet/dev-dashboards.libsonnet @@ -94,6 +94,7 @@ "shared_queries": (import '../dev-dashboards/panel-common/shared_queries.json'), "slow_queries_and_annotations": (import '../dev-dashboards/scenarios/slow_queries_and_annotations.json'), "table_kitchen_sink": (import '../dev-dashboards/panel-table/table_kitchen_sink.json'), + "table_markdown": (import '../dev-dashboards/panel-table/table_markdown.json'), "table_pagination": (import '../dev-dashboards/panel-table/table_pagination.json'), "table_sparkline_cell": (import '../dev-dashboards/panel-table/table_sparkline_cell.json'), "table_tests": (import '../dev-dashboards/panel-table/table_tests.json'), diff --git a/e2e-playwright/panels-suite/table-kitchenSink.spec.ts b/e2e-playwright/panels-suite/table-kitchenSink.spec.ts index c7947fcd281..8ac43ceebb1 100644 --- a/e2e-playwright/panels-suite/table-kitchenSink.spec.ts +++ b/e2e-playwright/panels-suite/table-kitchenSink.spec.ts @@ -225,7 +225,7 @@ test.describe('Panels test: Table - Kitchen Sink', { tag: ['@panels', '@table'] // in a second, though. const smallRowStatus = await getRowStatus(page); expect(smallRowStatus.end).toBeGreaterThan(1); - expect(page.getByRole('grid').getByRole('row')).toHaveCount(smallRowStatus.end + 1); + expect(page.getByRole('grid').getByRole('row')).toHaveCount(smallRowStatus.end + 2); // +2 for header and footer rows // change cell height to Large await dashboardPage @@ -235,7 +235,7 @@ test.describe('Panels test: Table - Kitchen Sink', { tag: ['@panels', '@table'] .click(); const largeRowStatus = await getRowStatus(page); expect(largeRowStatus.end).toBeLessThan(smallRowStatus.end); - expect(page.getByRole('grid').getByRole('row')).toHaveCount(largeRowStatus.end + 1); + expect(page.getByRole('grid').getByRole('row')).toHaveCount(largeRowStatus.end + 2); // +2 for header and footer rows // click a page over with the directional nav await page.getByLabel('next page').click(); diff --git a/e2e-playwright/panels-suite/table-markdown.spec.ts b/e2e-playwright/panels-suite/table-markdown.spec.ts new file mode 100644 index 00000000000..b2e127fc92c --- /dev/null +++ b/e2e-playwright/panels-suite/table-markdown.spec.ts @@ -0,0 +1,25 @@ +import { test, expect } from '@grafana/plugin-e2e'; + +test.use({ + viewport: { width: 1280, height: 1080 }, + featureToggles: { + tableNextGen: true, + }, +}); + +test.describe( + 'Panels test: Table - Markdown', + { + tag: ['@panels', '@table'], + }, + () => { + test('Tests Markdown tables are successfully rendered', async ({ gotoDashboardPage, page }) => { + await gotoDashboardPage({ + uid: '2769f5d8-0094-4ac4-a4f0-f68f620339cc', + queryParams: new URLSearchParams({ editPanel: '1' }), + }); + + await expect(page.getByRole('grid')).toBeVisible(); + }); + } +); diff --git a/packages/grafana-schema/src/common/common.gen.ts b/packages/grafana-schema/src/common/common.gen.ts index 9b229c4d1e9..c256e8ed6bd 100644 --- a/packages/grafana-schema/src/common/common.gen.ts +++ b/packages/grafana-schema/src/common/common.gen.ts @@ -708,6 +708,7 @@ export enum TableCellDisplayMode { Image = 'image', JSONView = 'json-view', LcdGauge = 'lcd-gauge', + Markdown = 'markdown', Pill = 'pill', Sparkline = 'sparkline', } @@ -836,6 +837,11 @@ export interface TablePillCellOptions extends TableWrapTextOptions { type: TableCellDisplayMode.Pill; } +export interface TableMarkdownCellOptions { + dynamicHeight?: boolean; + type: TableCellDisplayMode.Markdown; +} + /** * Height of a table cell */ @@ -850,7 +856,7 @@ export enum TableCellHeight { * Table cell options. Each cell has a display mode * and other potential options for that display. */ -export type TableCellOptions = (TableAutoCellOptions | TableSparklineCellOptions | TableBarGaugeCellOptions | TableColoredBackgroundCellOptions | TableColorTextCellOptions | TableImageCellOptions | TablePillCellOptions | TableDataLinksCellOptions | TableActionsCellOptions | TableJsonViewCellOptions); +export type TableCellOptions = (TableAutoCellOptions | TableSparklineCellOptions | TableBarGaugeCellOptions | TableColoredBackgroundCellOptions | TableColorTextCellOptions | TableImageCellOptions | TablePillCellOptions | TableDataLinksCellOptions | TableActionsCellOptions | TableJsonViewCellOptions | TableMarkdownCellOptions); /** * Use UTC/GMT timezone diff --git a/packages/grafana-schema/src/common/table.cue b/packages/grafana-schema/src/common/table.cue index 0a15fb926b5..57b7b56dc44 100644 --- a/packages/grafana-schema/src/common/table.cue +++ b/packages/grafana-schema/src/common/table.cue @@ -4,7 +4,7 @@ package common // in the table such as colored text, JSON, gauge, etc. // The color-background-solid, gradient-gauge, and lcd-gauge // modes are deprecated in favor of new cell subOptions -TableCellDisplayMode: "auto" | "color-text" | "color-background" | "color-background-solid" | "gradient-gauge" | "lcd-gauge" | "json-view" | "basic" | "image" | "gauge" | "sparkline" | "data-links" | "custom" | "actions" | "pill" @cuetsy(kind="enum",memberNames="Auto|ColorText|ColorBackground|ColorBackgroundSolid|GradientGauge|LcdGauge|JSONView|BasicGauge|Image|Gauge|Sparkline|DataLinks|Custom|Actions|Pill") +TableCellDisplayMode: "auto" | "color-text" | "color-background" | "color-background-solid" | "gradient-gauge" | "lcd-gauge" | "json-view" | "basic" | "image" | "gauge" | "sparkline" | "data-links" | "custom" | "actions" | "pill" | "markdown" @cuetsy(kind="enum",memberNames="Auto|ColorText|ColorBackground|ColorBackgroundSolid|GradientGauge|LcdGauge|JSONView|BasicGauge|Image|Gauge|Sparkline|DataLinks|Custom|Actions|Pill|Markdown") // Display mode to the "Colored Background" display // mode for table cells. Either displays a solid color (basic mode) @@ -91,12 +91,17 @@ TablePillCellOptions: { type: TableCellDisplayMode & "pill" } & TableWrapTextOptions @cuetsy(kind="interface") +TableMarkdownCellOptions: { + type: TableCellDisplayMode & "markdown" + dynamicHeight?: bool +} @cuetsy(kind="interface") + // Height of a table cell TableCellHeight: "sm" | "md" | "lg" | "auto" @cuetsy(kind="enum") // Table cell options. Each cell has a display mode // and other potential options for that display. -TableCellOptions: TableAutoCellOptions | TableSparklineCellOptions | TableBarGaugeCellOptions | TableColoredBackgroundCellOptions | TableColorTextCellOptions | TableImageCellOptions | TablePillCellOptions | TableDataLinksCellOptions | TableActionsCellOptions | TableJsonViewCellOptions @cuetsy(kind="type") +TableCellOptions: TableAutoCellOptions | TableSparklineCellOptions | TableBarGaugeCellOptions | TableColoredBackgroundCellOptions | TableColorTextCellOptions | TableImageCellOptions | TablePillCellOptions | TableDataLinksCellOptions | TableActionsCellOptions | TableJsonViewCellOptions | TableMarkdownCellOptions @cuetsy(kind="type") // Field options for each field within a table (e.g 10, "The String", 64.20, etc.) // Generally defines alignment, filtering capabilties, display options, etc. diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index dfb0c9754ea..f04ad6287e1 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -109,7 +109,7 @@ "react-calendar": "^6.0.0", "react-colorful": "5.6.1", "react-custom-scrollbars-2": "4.5.0", - "react-data-grid": "grafana/react-data-grid#de920f0105cb2b7d774444e7443a675f3b568ad6", + "react-data-grid": "grafana/react-data-grid#a922856b5ede21d55db3fdffb6d38dc76bdc7c58", "react-dropzone": "14.3.8", "react-highlight-words": "0.21.0", "react-hook-form": "^7.49.2", diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/MarkdownCell.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/MarkdownCell.tsx new file mode 100644 index 00000000000..7d4922c2434 --- /dev/null +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/MarkdownCell.tsx @@ -0,0 +1,17 @@ +import { renderMarkdown } from '@grafana/data'; + +import { MaybeWrapWithLink } from '../MaybeWrapWithLink'; +import { MarkdownCellProps } from '../types'; + +export function MarkdownCell({ field, rowIdx, disableSanitizeHtml }: MarkdownCellProps) { + return ( + +
+ + ); +} diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/RowExpander.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/RowExpander.tsx index 019afb7e243..d1f64824ef3 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/RowExpander.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/RowExpander.tsx @@ -7,8 +7,8 @@ import { useStyles2 } from '../../../../themes/ThemeContext'; import { Icon } from '../../../Icon/Icon'; import { RowExpanderNGProps } from '../types'; -export function RowExpander({ height, onCellExpand, isExpanded }: RowExpanderNGProps) { - const styles = useStyles2(getStyles, height); +export function RowExpander({ onCellExpand, isExpanded }: RowExpanderNGProps) { + const styles = useStyles2(getStyles); function handleKeyDown(e: React.KeyboardEvent) { if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); @@ -30,12 +30,11 @@ export function RowExpander({ height, onCellExpand, isExpanded }: RowExpanderNGP ); } -const getStyles = (theme: GrafanaTheme2, rowHeight: number) => ({ +const getStyles = (_theme: GrafanaTheme2) => ({ expanderCell: css({ display: 'flex', flexDirection: 'column', justifyContent: 'center', - height: `${rowHeight}px`, cursor: 'pointer', }), }); diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.tsx index 8d444eddf40..c406d7ffc3f 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/renderers.tsx @@ -11,6 +11,7 @@ import { BarGaugeCell } from './BarGaugeCell'; import { DataLinksCell } from './DataLinksCell'; import { GeoCell } from './GeoCell'; import { ImageCell } from './ImageCell'; +import { MarkdownCell } from './MarkdownCell'; import { PillCell } from './PillCell'; import { SparklineCell } from './SparklineCell'; @@ -78,6 +79,10 @@ const CUSTOM_RENDERER: TableCellRenderer = (props) => { return ; }; +const MARKDOWN_RENDERER: TableCellRenderer = (props) => ( + +); + const CELL_RENDERERS: Record = { [TableCellDisplayMode.Sparkline]: SPARKLINE_RENDERER, [TableCellDisplayMode.Gauge]: GAUGE_RENDERER, @@ -89,9 +94,16 @@ const CELL_RENDERERS: Record = { [TableCellDisplayMode.ColorText]: AUTO_RENDERER, [TableCellDisplayMode.ColorBackground]: AUTO_RENDERER, [TableCellDisplayMode.Auto]: AUTO_RENDERER, + [TableCellDisplayMode.Markdown]: MARKDOWN_RENDERER, [TableCellDisplayMode.Pill]: PILL_RENDERER, }; +// TODO: come up with a more elegant way to handle this. +const STRING_ONLY_RENDERERS = new Set([ + TableCellDisplayMode.Markdown, + TableCellDisplayMode.Pill, +]); + /** @internal */ export function getCellRenderer(field: Field, cellOptions: TableCellOptions): TableCellRenderer { const cellType = cellOptions?.type ?? TableCellDisplayMode.Auto; @@ -99,8 +111,7 @@ export function getCellRenderer(field: Field, cellOptions: TableCellOptions): Ta return getAutoRendererResult(field); } - // TODO: add support boolean, enum, (maybe int). but for now just string fields - if (cellType === TableCellDisplayMode.Pill && field.type !== FieldType.string) { + if (STRING_ONLY_RENDERERS.has(cellType) && field.type !== FieldType.string) { return AUTO_RENDERER; } diff --git a/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx b/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx index 8d6c9bb5ef8..82ca9192066 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx @@ -84,6 +84,7 @@ export function TableNG(props: TableNGProps) { const { cellHeight, data, + disableSanitizeHtml, enablePagination = false, enableSharedCrosshair = false, enableVirtualization, @@ -160,12 +161,15 @@ export function TableNG(props: TableNGProps) { setSortColumns, } = useSortedRows(filteredRows, data.fields, { hasNestedFrames, initialSortBy }); - const defaultRowHeight = getDefaultRowHeight(theme, cellHeight); const [isInspecting, setIsInspecting] = useState(false); const [expandedRows, setExpandedRows] = useState(() => new Set()); // vt scrollbar accounting for column auto-sizing const visibleFields = useMemo(() => getVisibleFields(data.fields), [data.fields]); + const defaultRowHeight = useMemo( + () => getDefaultRowHeight(theme, visibleFields, cellHeight), + [theme, visibleFields, cellHeight] + ); const gridRef = useRef(null); const scrollbarWidth = useScrollbarWidth(gridRef, height, sortedRows); const availableWidth = useMemo( @@ -212,7 +216,7 @@ export function TableNG(props: TableNGProps) { width: availableWidth, height, headerHeight, - footerHeight: hasFooter ? defaultRowHeight : 0, + footerHeight: hasFooter ? (typeof defaultRowHeight === 'number' ? defaultRowHeight : TABLE.MAX_CELL_HEIGHT) : 0, rowHeight, }); @@ -224,6 +228,17 @@ export function TableNG(props: TableNGProps) { }); const applyToRowBgFn = useMemo(() => getApplyToRowBgFn(data.fields, theme) ?? undefined, [data.fields, theme]); + // normalize the row height into a function which returns a number, so we avoid a bunch of conditionals during rendering. + const rowHeightFn = useMemo((): ((row: TableRow) => number) => { + if (typeof rowHeight === 'function') { + return rowHeight; + } + if (typeof rowHeight === 'string') { + return () => TABLE.MAX_CELL_HEIGHT; + } + return () => rowHeight; + }, [rowHeight]); + const renderRow = useMemo( () => renderRowFactory(data.fields, panelContext, expandedRows, enableSharedCrosshair), [data, enableSharedCrosshair, expandedRows, panelContext] @@ -232,7 +247,7 @@ export function TableNG(props: TableNGProps) { const commonDataGridProps = useMemo( () => ({ - enableVirtualization, + enableVirtualization: enableVirtualization !== false && rowHeight !== 'auto', defaultColumnOptions: { minWidth: 50, resizable: true, @@ -348,8 +363,8 @@ export function TableNG(props: TableNGProps) { ) : undefined; - const shouldOverflow = shouldTextOverflow(field); - const shouldWrap = shouldTextWrap(field); + const shouldOverflow = rowHeight !== 'auto' && shouldTextOverflow(field); + const shouldWrap = rowHeight === 'auto' || shouldTextWrap(field); const withTooltip = withDataLinksActionsTooltip(field, cellType); const canBeColorized = cellType === TableCellDisplayMode.ColorBackground || cellType === TableCellDisplayMode.ColorText; @@ -368,6 +383,7 @@ export function TableNG(props: TableNGProps) { case TableCellDisplayMode.DataLinks: case TableCellDisplayMode.JSONView: case TableCellDisplayMode.Pill: + case TableCellDisplayMode.Markdown: cellClass = getCellStyles( theme, cellType, @@ -428,7 +444,9 @@ export function TableNG(props: TableNGProps) { const value = props.row[props.column.key]; // TODO: it would be nice to get rid of passing height down as a prop. but this value // is cached so the cost of calling for every cell is low. - const height = typeof rowHeight === 'function' ? rowHeight(props.row) : rowHeight; + // NOTE: some cell types still require a height to be passed down, so that's why string-based + // cell types are going to just pass down the max cell height as a numeric height for those cells. + const height = rowHeightFn(props.row); const frame = data; return ( @@ -446,6 +464,7 @@ export function TableNG(props: TableNGProps) { cellInspect, showFilters, getActions: getCellActions, + disableSanitizeHtml, })} {showActions && ( { if (expandedRows.has(rowIdx)) { @@ -608,7 +626,7 @@ export function TableNG(props: TableNGProps) { crossFilterOrder, crossFilterRows, data, - defaultRowHeight, + disableSanitizeHtml, enableSharedCrosshair, expandedRows, filter, @@ -618,6 +636,7 @@ export function TableNG(props: TableNGProps) { onCellFilterAdded, panelContext, rowHeight, + rowHeightFn, rows, setFilter, showTypeIcons, @@ -947,16 +966,26 @@ const getCellStyles = ( shouldOverflow: boolean, isColorized: boolean, isMonospace: boolean -) => - css({ +) => { + const whiteSpace: CSSProperties['whiteSpace'] = (() => { + if (isMonospace) { + return 'pre'; + } + if (cellType === TableCellDisplayMode.Markdown) { + return 'normal'; + } + return 'pre-line'; + })(); + + return css({ display: 'flex', alignItems: 'center', textAlign, justifyContent: getJustifyContent(textAlign), - minHeight: '100%', - backgroundClip: 'padding-box !important', // helps when cells have a bg color - ...(shouldWrap && { whiteSpace: isMonospace ? 'pre' : 'pre-line' }), + ...(isColorized && { backgroundClip: 'padding-box !important' }), + ...(shouldOverflow && { minHeight: '100%' }), + ...(shouldWrap && { whiteSpace }), ...(isMonospace && { fontFamily: 'monospace' }), '&:hover, &[aria-selected=true]': { @@ -965,7 +994,7 @@ const getCellStyles = ( }, ...(shouldOverflow && { zIndex: theme.zIndex.tooltip - 2, - whiteSpace: isMonospace ? 'pre' : 'pre-line', + whiteSpace, height: 'fit-content', minWidth: 'fit-content', ...(cellType === TableCellDisplayMode.Pill && { @@ -1025,4 +1054,22 @@ const getCellStyles = ( whiteSpace: 'nowrap', }, }), + + ...(cellType === TableCellDisplayMode.Markdown && { + '& ol, & ul': { + paddingLeft: theme.spacing(1.5), + }, + '& p': { + whiteSpace: 'pre-line', + }, + '& a': { + color: theme.colors.primary.text, + }, + // for elements like `p`, `h*`, etc. which have an inherent margin, + // we want to remove the bottom margin for the last one in the container. + '& > .markdown-container > *:last-child': { + marginBottom: 0, + }, + }), }); +}; diff --git a/packages/grafana-ui/src/components/Table/TableNG/hooks.ts b/packages/grafana-ui/src/components/Table/TableNG/hooks.ts index 5c349bdd1ab..47efa394409 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/hooks.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/hooks.ts @@ -1,4 +1,4 @@ -import { useState, useMemo, useEffect, useCallback, useRef, useLayoutEffect, RefObject } from 'react'; +import { useState, useMemo, useCallback, useRef, useLayoutEffect, RefObject, CSSProperties } from 'react'; import { Column, DataGridHandle, DataGridProps, SortColumn } from 'react-data-grid'; import { Field, fieldReducers, FieldType, formattedValueToString, reduceField } from '@grafana/data'; @@ -135,7 +135,7 @@ export function useSortedRows( export interface PaginatedRowsOptions { height: number; width: number; - rowHeight: number | ((row: TableRow) => number); + rowHeight: NonNullable | ((row: TableRow) => number); headerHeight: number; footerHeight: number; paginationHeight?: number; @@ -174,6 +174,12 @@ export function usePaginatedRows( return rowHeight; } + // when using auto-sized rows, we're just going to have to pick a number. the alternative + // is to measure each row, which we could do but would be expensive. + if (typeof rowHeight === 'string') { + return TABLE.MAX_CELL_HEIGHT; + } + // we'll just measure 100 rows to estimate return rows.slice(0, 100).reduce((avg, row, _, { length }) => avg + rowHeight(row) / length, 0); }, [rows, rowHeight, enabled]); @@ -214,7 +220,7 @@ export function usePaginatedRows( }, [width, height, headerHeight, footerHeight, avgRowHeight, enabled, numRows, page]); // safeguard against page overflow on panel resize or other factors - useEffect(() => { + useLayoutEffect(() => { if (!enabled) { return; } @@ -381,7 +387,7 @@ interface UseRowHeightOptions { columnWidths: number[]; fields: Field[]; hasNestedFrames: boolean; - defaultHeight: number; + defaultHeight: NonNullable; expandedRows: Set; typographyCtx: TypographyCtx; } @@ -393,7 +399,7 @@ export function useRowHeight({ defaultHeight, expandedRows, typographyCtx, -}: UseRowHeightOptions): number | ((row: TableRow) => number) { +}: UseRowHeightOptions): NonNullable | ((row: TableRow) => number) { const lineCounters = useMemo(() => buildRowLineCounters(fields, typographyCtx), [fields, typographyCtx]); const hasWrappedCols = useMemo(() => lineCounters?.length ?? 0 > 0, [lineCounters]); @@ -404,7 +410,7 @@ export function useRowHeight({ const rowHeight = useMemo(() => { // row height is only complicated when there are nested frames or wrapped columns. - if (!hasNestedFrames && !hasWrappedCols) { + if ((!hasNestedFrames && !hasWrappedCols) || typeof defaultHeight === 'string') { return defaultHeight; } diff --git a/packages/grafana-ui/src/components/Table/TableNG/types.ts b/packages/grafana-ui/src/components/Table/TableNG/types.ts index d28bab7b668..eaca19734ea 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/types.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/types.ts @@ -141,6 +141,8 @@ export interface BaseTableProps { getActions?: GetActionsFunction; // Used solely for testing as RTL can't correctly render the table otherwise enableVirtualization?: boolean; + // for MarkdownCell, this flag disables sanitization of HTML content. Configured via config.ini. + disableSanitizeHtml?: boolean; } /* ---------------------------- Table cell props ---------------------------- */ @@ -161,6 +163,7 @@ export interface TableCellRendererProps { showFilters: boolean; justifyContent: Property.JustifyContent; getActions?: GetActionsFunctionLocal; + disableSanitizeHtml?: boolean; } export type ContextMenuProps = { @@ -186,7 +189,6 @@ export interface TableCellActionsProps { /* ------------------------- Specialized Cell Props ------------------------- */ export interface RowExpanderNGProps { - height: number; onCellExpand: (e: SyntheticEvent) => void; isExpanded?: boolean; } @@ -242,6 +244,12 @@ export interface AutoCellProps { rowIdx: number; } +export interface MarkdownCellProps { + field: Field; + rowIdx: number; + disableSanitizeHtml?: boolean; +} + export interface ActionCellProps { field: Field; rowIdx: number; diff --git a/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts b/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts index 4dd20cac215..e159c9933cb 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts @@ -27,7 +27,6 @@ import { getCellLinks, getCellOptions, getComparator, - getDefaultRowHeight, getIsNestedTable, getAlignment, getJustifyContent, @@ -44,6 +43,7 @@ import { wrapUwrapCount, getDataLinksCounter, getPillLineCounter, + getDefaultRowHeight, } from './utils'; describe('TableNG utils', () => { @@ -787,23 +787,46 @@ describe('TableNG utils', () => { describe('getDefaultRowHeight', () => { const theme = createTheme(); - it('returns correct height for TableCellHeight.Sm', () => { - const result = getDefaultRowHeight(theme, TableCellHeight.Sm); - expect(result).toBe(36); + it.each([ + { input: TableCellHeight.Sm, expected: 36 }, + { input: TableCellHeight.Md, expected: 42 }, + { input: TableCellHeight.Lg, expected: TABLE.MAX_CELL_HEIGHT }, + ])('returns "$expected" for "$input"', ({ input, expected }) => { + const result = getDefaultRowHeight(theme, [], input); + expect(result).toBe(expected); }); - it('returns correct height for TableCellHeight.Md', () => { - const result = getDefaultRowHeight(theme, TableCellHeight.Md); - expect(result).toBe(42); - }); - - it('returns correct height for TableCellHeight.Lg', () => { - const result = getDefaultRowHeight(theme, TableCellHeight.Lg); - expect(result).toBe(TABLE.MAX_CELL_HEIGHT); + it('returns "auto" if a field is present with the dynamicHeight cellOption is false', () => { + expect( + getDefaultRowHeight( + theme, + [ + { + name: 'test1', + type: FieldType.string, + config: {}, + values: ['value1'], + }, + { + name: 'test2', + type: FieldType.string, + config: { custom: { cellOptions: { type: TableCellDisplayMode.Markdown, dynamicHeight: true } } }, + values: ['value1'], + }, + { + name: 'test3', + type: FieldType.number, + config: { custom: { cellOptions: { type: TableCellDisplayMode.JSONView } } }, + values: [3], + }, + ], + TableCellHeight.Sm + ) + ).toBe('auto'); }); it('calculates height based on theme when cellHeight is undefined', () => { - const result = getDefaultRowHeight(theme, undefined as unknown as TableCellHeight); + const result = getDefaultRowHeight(theme, []); // Calculate the expected result based on the theme values const expected = TABLE.CELL_PADDING * 2 + theme.typography.fontSize * theme.typography.body.lineHeight; diff --git a/packages/grafana-ui/src/components/Table/TableNG/utils.ts b/packages/grafana-ui/src/components/Table/TableNG/utils.ts index 96e6c71c018..9ba4a5eddca 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/utils.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/utils.ts @@ -1,4 +1,5 @@ import { Property } from 'csstype'; +import { CSSProperties } from 'react'; import { SortColumn } from 'react-data-grid'; import tinycolor from 'tinycolor2'; import { Count, varPreLine } from 'uwrap'; @@ -45,9 +46,14 @@ export type CellNumLinesCalculator = (text: string, cellWidth: number) => number * @internal * Returns the default row height based on the theme and cell height setting. */ -export function getDefaultRowHeight(theme: GrafanaTheme2, cellHeight?: TableCellHeight): number { - const bodyFontSize = theme.typography.fontSize; - const lineHeight = theme.typography.body.lineHeight; +export function getDefaultRowHeight( + theme: GrafanaTheme2, + fields?: Field[], + cellHeight?: TableCellHeight +): NonNullable { + if (fields?.some((field) => field.config?.custom?.cellOptions?.dynamicHeight)) { + return 'auto'; + } switch (cellHeight) { case TableCellHeight.Sm: @@ -58,7 +64,7 @@ export function getDefaultRowHeight(theme: GrafanaTheme2, cellHeight?: TableCell return TABLE.MAX_CELL_HEIGHT; } - return TABLE.CELL_PADDING * 2 + bodyFontSize * lineHeight; + return TABLE.CELL_PADDING * 2 + theme.typography.fontSize * theme.typography.body.lineHeight; } /** diff --git a/public/app/plugins/panel/table/table-new/PaginationEditor.tsx b/public/app/plugins/panel/table/table-new/PaginationEditor.tsx index 6434c75e1b9..ccd9451ee3f 100644 --- a/public/app/plugins/panel/table/table-new/PaginationEditor.tsx +++ b/public/app/plugins/panel/table/table-new/PaginationEditor.tsx @@ -4,11 +4,8 @@ import { StandardEditorProps } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { Switch } from '@grafana/ui'; -export function PaginationEditor({ onChange, value, context }: StandardEditorProps) { +export function PaginationEditor({ onChange, value }: StandardEditorProps) { const changeValue = (event: React.FormEvent | undefined) => { - if (event?.currentTarget.checked) { - context.options.footer.show = false; - } onChange(event?.currentTarget.checked); }; diff --git a/public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx b/public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx index 92cbbf0f264..b70723695cb 100644 --- a/public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx +++ b/public/app/plugins/panel/table/table-new/TableCellOptionEditor.tsx @@ -10,6 +10,7 @@ import { Combobox, ComboboxOption, Field, TableCellDisplayMode, useStyles2 } fro import { BarGaugeCellOptionsEditor } from './cells/BarGaugeCellOptionsEditor'; import { ColorBackgroundCellOptionsEditor } from './cells/ColorBackgroundCellOptionsEditor'; import { ImageCellOptionsEditor } from './cells/ImageCellOptionsEditor'; +import { MarkdownCellOptionsEditor } from './cells/MarkdownCellOptionsEditor'; import { SparklineCellOptionsEditor } from './cells/SparklineCellOptionsEditor'; import { TextWrapOptionsEditor } from './cells/TextWrapOptionsEditor'; @@ -54,6 +55,7 @@ export const TableCellOptionEditor = ({ value, onChange }: Props) => { { value: TableCellDisplayMode.Sparkline, label: t('table.cell-types.sparkline', 'Sparkline') }, { value: TableCellDisplayMode.JSONView, label: t('table.cell-types.json', 'JSON View') }, { value: TableCellDisplayMode.Pill, label: t('table.cell-types.pill', 'Pill') }, + { value: TableCellDisplayMode.Markdown, label: t('table.cell-types.markdown', 'Markdown + HTML') }, { value: TableCellDisplayMode.Image, label: t('table.cell-types.image', 'Image') }, { value: TableCellDisplayMode.Actions, label: t('table.cell-types.actions', 'Actions') }, ]; @@ -105,6 +107,9 @@ export const TableCellOptionEditor = ({ value, onChange }: Props) => { {cellType === TableCellDisplayMode.Image && ( )} + {cellType === TableCellDisplayMode.Markdown && ( + + )}
); }; diff --git a/public/app/plugins/panel/table/table-new/TablePanel.tsx b/public/app/plugins/panel/table/table-new/TablePanel.tsx index 5af5472f19b..6859e6368fb 100644 --- a/public/app/plugins/panel/table/table-new/TablePanel.tsx +++ b/public/app/plugins/panel/table/table-new/TablePanel.tsx @@ -17,6 +17,7 @@ import { config, PanelDataErrorView } from '@grafana/runtime'; import { Select, usePanelContext, useTheme2 } from '@grafana/ui'; import { TableSortByFieldState } from '@grafana/ui/internal'; import { TableNG } from '@grafana/ui/unstable'; +import { getConfig } from 'app/core/config'; import { getActions } from '../../../../features/actions/utils'; @@ -61,6 +62,8 @@ export function TablePanel(props: Props) { const enableSharedCrosshair = panelContext.sync && panelContext.sync() !== DashboardCursorSync.Off; + const disableSanitizeHtml = getConfig().disableSanitizeHtml; + const tableElement = ( ); diff --git a/public/app/plugins/panel/table/table-new/cells/MarkdownCellOptionsEditor.tsx b/public/app/plugins/panel/table/table-new/cells/MarkdownCellOptionsEditor.tsx new file mode 100644 index 00000000000..00c086eb37e --- /dev/null +++ b/public/app/plugins/panel/table/table-new/cells/MarkdownCellOptionsEditor.tsx @@ -0,0 +1,39 @@ +import { FormEvent } from 'react'; + +import { t, Trans } from '@grafana/i18n'; +import { TableMarkdownCellOptions } from '@grafana/schema'; +import { Badge, Field, Label, Switch } from '@grafana/ui'; + +import { TableCellEditorProps } from '../TableCellOptionEditor'; + +export const MarkdownCellOptionsEditor = ({ + cellOptions, + onChange, +}: TableCellEditorProps) => { + const onDynamicHeightChange = (e: FormEvent) => { + cellOptions.dynamicHeight = e.currentTarget.checked; + onChange(cellOptions); + }; + + return ( + + Dynamic height{' '} + + + } + > + + + ); +}; diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 927b0c58839..fa1024f8d7a 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -12529,6 +12529,7 @@ "gauge": "Gauge", "image": "Image", "json": "JSON View", + "markdown": "Markdown + HTML", "pill": "Pill", "sparkline": "Sparkline" }, @@ -12566,6 +12567,13 @@ "label-alt-text": "Alt text", "label-title-text": "Title text" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "We recommend enabling pagination with this option to avoid performance issues.", + "label": { + "text-alpha": "Alpha" + }, + "label-dynamic-height": "Dynamic height" + }, "name-calculation": "Calculation", "name-cell-height": "Cell height", "name-cell-type": "Cell type", diff --git a/yarn.lock b/yarn.lock index dae3c03c7d0..69123b8140e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3829,7 +3829,7 @@ __metadata: react-calendar: "npm:^6.0.0" react-colorful: "npm:5.6.1" react-custom-scrollbars-2: "npm:4.5.0" - react-data-grid: "grafana/react-data-grid#de920f0105cb2b7d774444e7443a675f3b568ad6" + react-data-grid: "grafana/react-data-grid#a922856b5ede21d55db3fdffb6d38dc76bdc7c58" react-dom: "npm:18.3.1" react-dropzone: "npm:14.3.8" react-highlight-words: "npm:0.21.0" @@ -26823,15 +26823,15 @@ __metadata: languageName: node linkType: hard -"react-data-grid@grafana/react-data-grid#de920f0105cb2b7d774444e7443a675f3b568ad6": +"react-data-grid@grafana/react-data-grid#a922856b5ede21d55db3fdffb6d38dc76bdc7c58": version: 7.0.0-beta.56 - resolution: "react-data-grid@https://github.com/grafana/react-data-grid.git#commit=de920f0105cb2b7d774444e7443a675f3b568ad6" + resolution: "react-data-grid@https://github.com/grafana/react-data-grid.git#commit=a922856b5ede21d55db3fdffb6d38dc76bdc7c58" dependencies: clsx: "npm:^2.0.0" peerDependencies: react: ^18.0 || ^19.0 react-dom: ^18.0 || ^19.0 - checksum: 10/efc1dcb764fa5f3549d012737e79d423b34e6ad7b0a122849d757f59b45e648afe7c5cfeb1a61464245aa7b393f9251ff91fd49f8f857139d7df185c23d68b68 + checksum: 10/18d368ff52151c1e7900819b0d92bb554b3d26135a5d4401a6e3c044fd62ca72a4177b63ba705b93901fa489458a965ce1d1deb2e4f98aa5fb39c276d2b12d38 languageName: node linkType: hard From 9cc5171e50ddd077b0b12b20307e6d57c105d3f2 Mon Sep 17 00:00:00 2001 From: "grafana-pr-automation[bot]" <140550294+grafana-pr-automation[bot]@users.noreply.github.com> Date: Sat, 2 Aug 2025 00:41:54 +0000 Subject: [PATCH 43/89] I18n: Download translations from Crowdin (#109092) New Crowdin translations by GitHub Action Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- public/locales/cs-CZ/grafana.json | 22 +++++++++++++++++++++- public/locales/de-DE/grafana.json | 22 +++++++++++++++++++++- public/locales/es-ES/grafana.json | 22 +++++++++++++++++++++- public/locales/fr-FR/grafana.json | 22 +++++++++++++++++++++- public/locales/hu-HU/grafana.json | 22 +++++++++++++++++++++- public/locales/id-ID/grafana.json | 22 +++++++++++++++++++++- public/locales/it-IT/grafana.json | 22 +++++++++++++++++++++- public/locales/ja-JP/grafana.json | 22 +++++++++++++++++++++- public/locales/ko-KR/grafana.json | 22 +++++++++++++++++++++- public/locales/nl-NL/grafana.json | 22 +++++++++++++++++++++- public/locales/pl-PL/grafana.json | 22 +++++++++++++++++++++- public/locales/pt-BR/grafana.json | 22 +++++++++++++++++++++- public/locales/pt-PT/grafana.json | 22 +++++++++++++++++++++- public/locales/ru-RU/grafana.json | 22 +++++++++++++++++++++- public/locales/sv-SE/grafana.json | 22 +++++++++++++++++++++- public/locales/tr-TR/grafana.json | 22 +++++++++++++++++++++- public/locales/zh-Hans/grafana.json | 22 +++++++++++++++++++++- public/locales/zh-Hant/grafana.json | 22 +++++++++++++++++++++- 18 files changed, 378 insertions(+), 18 deletions(-) diff --git a/public/locales/cs-CZ/grafana.json b/public/locales/cs-CZ/grafana.json index 1643e92662c..b9b757edcaa 100644 --- a/public/locales/cs-CZ/grafana.json +++ b/public/locales/cs-CZ/grafana.json @@ -9422,6 +9422,15 @@ "show-more": "zobrazit více", "tooltip-error": "Chyba: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "Vymazat", "close": "Zavřít podrobnosti protokolu", @@ -12604,6 +12613,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12641,6 +12651,13 @@ "label-alt-text": "Alternativní text", "label-title-text": "Text názvu" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "Výpočet", "name-cell-height": "Výška buňky", "name-cell-type": "Typ buňky", @@ -12657,7 +12674,10 @@ "name-show-table-header": "Zobrazit záhlaví tabulky", "name-wrap-header-text": "Zalomit text záhlaví", "placeholder-column-width": "auto.", - "placeholder-fields": "Všechna číselná pole" + "placeholder-fields": "Všechna číselná pole", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "Možnosti buněk", diff --git a/public/locales/de-DE/grafana.json b/public/locales/de-DE/grafana.json index 80e030a1058..3f7bf773d34 100644 --- a/public/locales/de-DE/grafana.json +++ b/public/locales/de-DE/grafana.json @@ -9362,6 +9362,15 @@ "show-more": "mehr anzeigen", "tooltip-error": "Fehler: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "Löschen", "close": "Logdetails schließen", @@ -12520,6 +12529,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12557,6 +12567,13 @@ "label-alt-text": "Alt-Text", "label-title-text": "Titeltext" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "Berechnung", "name-cell-height": "Zellenhöhe", "name-cell-type": "Zellentyp", @@ -12573,7 +12590,10 @@ "name-show-table-header": "Tabellenüberschirft anzeigen", "name-wrap-header-text": "Kopfzeilentext umbrechen", "placeholder-column-width": "auto", - "placeholder-fields": "Alle numerischen Felder" + "placeholder-fields": "Alle numerischen Felder", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "Zellenoptionen", diff --git a/public/locales/es-ES/grafana.json b/public/locales/es-ES/grafana.json index fed89a55f7e..336040ef0d0 100644 --- a/public/locales/es-ES/grafana.json +++ b/public/locales/es-ES/grafana.json @@ -9362,6 +9362,15 @@ "show-more": "mostrar más", "tooltip-error": "Error: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "", "close": "", @@ -12520,6 +12529,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12557,6 +12567,13 @@ "label-alt-text": "Texto alternativo", "label-title-text": "Texto del título" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "", "name-cell-height": "", "name-cell-type": "", @@ -12573,7 +12590,10 @@ "name-show-table-header": "", "name-wrap-header-text": "", "placeholder-column-width": "", - "placeholder-fields": "" + "placeholder-fields": "", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "", diff --git a/public/locales/fr-FR/grafana.json b/public/locales/fr-FR/grafana.json index 4b9634936a7..2ae7265aba0 100644 --- a/public/locales/fr-FR/grafana.json +++ b/public/locales/fr-FR/grafana.json @@ -9362,6 +9362,15 @@ "show-more": "afficher plus", "tooltip-error": "Erreur : {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "Effacer", "close": "Fermer les détails du log", @@ -12520,6 +12529,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12557,6 +12567,13 @@ "label-alt-text": "Texte alternatif", "label-title-text": "Texte du titre" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "Calcul", "name-cell-height": "Hauteur de cellule", "name-cell-type": "Type de cellule", @@ -12573,7 +12590,10 @@ "name-show-table-header": "Afficher l’en-tête du tableau", "name-wrap-header-text": "Retour à la ligne dans l’en-tête", "placeholder-column-width": "auto", - "placeholder-fields": "Tous les champs numériques" + "placeholder-fields": "Tous les champs numériques", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "Options de cellule", diff --git a/public/locales/hu-HU/grafana.json b/public/locales/hu-HU/grafana.json index cc206d4e880..466dfd78dba 100644 --- a/public/locales/hu-HU/grafana.json +++ b/public/locales/hu-HU/grafana.json @@ -9362,6 +9362,15 @@ "show-more": "több megjelenítése", "tooltip-error": "Hiba: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "Törlés", "close": "Napló részleteinek bezárása", @@ -12520,6 +12529,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12557,6 +12567,13 @@ "label-alt-text": "Helyettesítő szöveg", "label-title-text": "Cím szövege" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "Számítás", "name-cell-height": "Cellamagasság", "name-cell-type": "Cellatípus", @@ -12573,7 +12590,10 @@ "name-show-table-header": "Táblázatfejléc megjelenítése", "name-wrap-header-text": "Fejléc szövegének tördelése", "placeholder-column-width": "automatikus", - "placeholder-fields": "Numerikus mezők" + "placeholder-fields": "Numerikus mezők", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "Cellabeállítások", diff --git a/public/locales/id-ID/grafana.json b/public/locales/id-ID/grafana.json index 6cc5262ca6c..0ac83101bf8 100644 --- a/public/locales/id-ID/grafana.json +++ b/public/locales/id-ID/grafana.json @@ -9332,6 +9332,15 @@ "show-more": "tampilkan lebih banyak", "tooltip-error": "Kesalahan: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "Hapus", "close": "Tutup detail log", @@ -12478,6 +12487,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12515,6 +12525,13 @@ "label-alt-text": "Teks alt", "label-title-text": "Teks judul" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "Perhitungan", "name-cell-height": "Tinggi sel", "name-cell-type": "Jenis sel", @@ -12531,7 +12548,10 @@ "name-show-table-header": "Tampilkan header tabel", "name-wrap-header-text": "Bungkus teks header", "placeholder-column-width": "otomatis", - "placeholder-fields": "Semua Bidang Numerik" + "placeholder-fields": "Semua Bidang Numerik", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "Opsi sel", diff --git a/public/locales/it-IT/grafana.json b/public/locales/it-IT/grafana.json index 76a93f29384..de5ef71b11f 100644 --- a/public/locales/it-IT/grafana.json +++ b/public/locales/it-IT/grafana.json @@ -9362,6 +9362,15 @@ "show-more": "mostra altro", "tooltip-error": "Errore: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "", "close": "", @@ -12520,6 +12529,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12557,6 +12567,13 @@ "label-alt-text": "", "label-title-text": "" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "", "name-cell-height": "", "name-cell-type": "", @@ -12573,7 +12590,10 @@ "name-show-table-header": "", "name-wrap-header-text": "", "placeholder-column-width": "", - "placeholder-fields": "" + "placeholder-fields": "", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "", diff --git a/public/locales/ja-JP/grafana.json b/public/locales/ja-JP/grafana.json index e3c05000367..bba4b28e474 100644 --- a/public/locales/ja-JP/grafana.json +++ b/public/locales/ja-JP/grafana.json @@ -9332,6 +9332,15 @@ "show-more": "さらに表示する", "tooltip-error": "エラー:{{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "クリア", "close": "ログの詳細を閉じる", @@ -12478,6 +12487,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12515,6 +12525,13 @@ "label-alt-text": "代替テキスト", "label-title-text": "タイトルテキスト" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "計算", "name-cell-height": "セルの高さ", "name-cell-type": "セルの種類", @@ -12531,7 +12548,10 @@ "name-show-table-header": "テーブルヘッダーを表示", "name-wrap-header-text": "ヘッダーテキストの折り返し", "placeholder-column-width": "自動", - "placeholder-fields": "すべての数値フィールド" + "placeholder-fields": "すべての数値フィールド", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "セルオプション", diff --git a/public/locales/ko-KR/grafana.json b/public/locales/ko-KR/grafana.json index 324297aeb54..7bf31c806de 100644 --- a/public/locales/ko-KR/grafana.json +++ b/public/locales/ko-KR/grafana.json @@ -9332,6 +9332,15 @@ "show-more": "더 보기", "tooltip-error": "오류: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "", "close": "", @@ -12478,6 +12487,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12515,6 +12525,13 @@ "label-alt-text": "대체 텍스트", "label-title-text": "제목 텍스트" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "", "name-cell-height": "", "name-cell-type": "", @@ -12531,7 +12548,10 @@ "name-show-table-header": "", "name-wrap-header-text": "", "placeholder-column-width": "", - "placeholder-fields": "" + "placeholder-fields": "", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "", diff --git a/public/locales/nl-NL/grafana.json b/public/locales/nl-NL/grafana.json index 17e611245de..bdb6da9d75d 100644 --- a/public/locales/nl-NL/grafana.json +++ b/public/locales/nl-NL/grafana.json @@ -9362,6 +9362,15 @@ "show-more": "meer", "tooltip-error": "Fout: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "Wissen", "close": "Logboekdetails sluiten", @@ -12520,6 +12529,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12557,6 +12567,13 @@ "label-alt-text": "Alt text", "label-title-text": "Titeltekst" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "Berekening", "name-cell-height": "Celhoogte", "name-cell-type": "Type cel", @@ -12573,7 +12590,10 @@ "name-show-table-header": "Header tabel tonen", "name-wrap-header-text": "Koptekst laten teruglopen", "placeholder-column-width": "automatisch", - "placeholder-fields": "Alle numerieke velden" + "placeholder-fields": "Alle numerieke velden", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "Celopties", diff --git a/public/locales/pl-PL/grafana.json b/public/locales/pl-PL/grafana.json index 1456a69bc9f..d0ee2281b71 100644 --- a/public/locales/pl-PL/grafana.json +++ b/public/locales/pl-PL/grafana.json @@ -9422,6 +9422,15 @@ "show-more": "pokaż więcej", "tooltip-error": "Błąd: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "", "close": "", @@ -12604,6 +12613,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12641,6 +12651,13 @@ "label-alt-text": "Tekst alternatywny", "label-title-text": "Tekst tytułu" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "", "name-cell-height": "", "name-cell-type": "", @@ -12657,7 +12674,10 @@ "name-show-table-header": "", "name-wrap-header-text": "", "placeholder-column-width": "", - "placeholder-fields": "" + "placeholder-fields": "", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "", diff --git a/public/locales/pt-BR/grafana.json b/public/locales/pt-BR/grafana.json index fc4479dde69..3f410b512e0 100644 --- a/public/locales/pt-BR/grafana.json +++ b/public/locales/pt-BR/grafana.json @@ -9362,6 +9362,15 @@ "show-more": "exibir mais", "tooltip-error": "Erro: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "", "close": "", @@ -12520,6 +12529,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12557,6 +12567,13 @@ "label-alt-text": "Texto alternativo", "label-title-text": "Texto do título" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "", "name-cell-height": "", "name-cell-type": "", @@ -12573,7 +12590,10 @@ "name-show-table-header": "", "name-wrap-header-text": "", "placeholder-column-width": "", - "placeholder-fields": "" + "placeholder-fields": "", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "", diff --git a/public/locales/pt-PT/grafana.json b/public/locales/pt-PT/grafana.json index 5ed4085e358..fe033510942 100644 --- a/public/locales/pt-PT/grafana.json +++ b/public/locales/pt-PT/grafana.json @@ -9362,6 +9362,15 @@ "show-more": "mostrar mais", "tooltip-error": "Erro: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "", "close": "", @@ -12520,6 +12529,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12557,6 +12567,13 @@ "label-alt-text": "Texto alternativo", "label-title-text": "Texto do título" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "", "name-cell-height": "", "name-cell-type": "", @@ -12573,7 +12590,10 @@ "name-show-table-header": "", "name-wrap-header-text": "", "placeholder-column-width": "", - "placeholder-fields": "" + "placeholder-fields": "", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "", diff --git a/public/locales/ru-RU/grafana.json b/public/locales/ru-RU/grafana.json index 64122595b67..e93e6cbae31 100644 --- a/public/locales/ru-RU/grafana.json +++ b/public/locales/ru-RU/grafana.json @@ -9422,6 +9422,15 @@ "show-more": "больше", "tooltip-error": "Ошибка: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "", "close": "", @@ -12604,6 +12613,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12641,6 +12651,13 @@ "label-alt-text": "Альтернативный текст", "label-title-text": "Текст заголовка" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "", "name-cell-height": "", "name-cell-type": "", @@ -12657,7 +12674,10 @@ "name-show-table-header": "", "name-wrap-header-text": "", "placeholder-column-width": "", - "placeholder-fields": "" + "placeholder-fields": "", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "", diff --git a/public/locales/sv-SE/grafana.json b/public/locales/sv-SE/grafana.json index b3ef95e164c..3e629468b46 100644 --- a/public/locales/sv-SE/grafana.json +++ b/public/locales/sv-SE/grafana.json @@ -9362,6 +9362,15 @@ "show-more": "visa mer", "tooltip-error": "Fel: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "", "close": "", @@ -12520,6 +12529,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12557,6 +12567,13 @@ "label-alt-text": "Alt text", "label-title-text": "Rubriktext" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "", "name-cell-height": "", "name-cell-type": "", @@ -12573,7 +12590,10 @@ "name-show-table-header": "", "name-wrap-header-text": "", "placeholder-column-width": "", - "placeholder-fields": "" + "placeholder-fields": "", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "", diff --git a/public/locales/tr-TR/grafana.json b/public/locales/tr-TR/grafana.json index c0dd88f9e9e..78522965546 100644 --- a/public/locales/tr-TR/grafana.json +++ b/public/locales/tr-TR/grafana.json @@ -9362,6 +9362,15 @@ "show-more": "daha fazla göster", "tooltip-error": "Hata: {{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "", "close": "", @@ -12520,6 +12529,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12557,6 +12567,13 @@ "label-alt-text": "Alternatif metin", "label-title-text": "Başlık metni" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "", "name-cell-height": "", "name-cell-type": "", @@ -12573,7 +12590,10 @@ "name-show-table-header": "", "name-wrap-header-text": "", "placeholder-column-width": "", - "placeholder-fields": "" + "placeholder-fields": "", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "", diff --git a/public/locales/zh-Hans/grafana.json b/public/locales/zh-Hans/grafana.json index 68923de4d6b..d1686c701fa 100644 --- a/public/locales/zh-Hans/grafana.json +++ b/public/locales/zh-Hans/grafana.json @@ -9332,6 +9332,15 @@ "show-more": "展开", "tooltip-error": "错误:{{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "清除", "close": "关闭日志详情", @@ -12478,6 +12487,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12515,6 +12525,13 @@ "label-alt-text": "替代文本", "label-title-text": "标题文本" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "计算", "name-cell-height": "单元格高度", "name-cell-type": "单元格类型", @@ -12531,7 +12548,10 @@ "name-show-table-header": "显示表格表头", "name-wrap-header-text": "表头文字换行", "placeholder-column-width": "自动", - "placeholder-fields": "所有数字字段" + "placeholder-fields": "所有数字字段", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "单元格选项", diff --git a/public/locales/zh-Hant/grafana.json b/public/locales/zh-Hant/grafana.json index 79e17eb09a4..9d5c448b15c 100644 --- a/public/locales/zh-Hant/grafana.json +++ b/public/locales/zh-Hant/grafana.json @@ -9332,6 +9332,15 @@ "show-more": "顯示更多", "tooltip-error": "錯誤:{{errorMessage}}" }, + "log-line-context": { + "center-matched-line": "", + "newer-logs": "", + "no-more-logs-available": "", + "older-logs": "", + "open-in-split-view": "", + "title-log-context": "", + "title-log-line": "" + }, "log-line-details": { "clear-search": "清除", "close": "關閉紀錄詳細資訊", @@ -12478,6 +12487,7 @@ "gauge": "", "image": "", "json": "", + "markdown": "", "pill": "", "sparkline": "" }, @@ -12515,6 +12525,13 @@ "label-alt-text": "替代文字", "label-title-text": "標題文字" }, + "markdown-cell-options-editor": { + "description-dynamic-height": "", + "label": { + "text-alpha": "" + }, + "label-dynamic-height": "" + }, "name-calculation": "計算", "name-cell-height": "儲存格高度", "name-cell-type": "儲存格類型", @@ -12531,7 +12548,10 @@ "name-show-table-header": "顯示表格頁首", "name-wrap-header-text": "換行標題文字", "placeholder-column-width": "自動", - "placeholder-fields": "所有數值欄位" + "placeholder-fields": "所有數值欄位", + "text-wrap-options": { + "label-wrap-text": "" + } }, "table-new": { "category-cell-options": "儲存格選項", From 8ac74e24df1ff9e5de0c1d0f78dcd8be12305b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Falksk=C3=A4r?= <457523+edvard-falkskar@users.noreply.github.com> Date: Sat, 2 Aug 2025 16:13:02 +0200 Subject: [PATCH 44/89] TraceView: Add span attributes to attributes extension point (#107756) --- .../src/types/pluginExtensions.ts | 1 + .../TraceTimelineViewer/SpanDetail/index.tsx | 22 ++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/packages/grafana-data/src/types/pluginExtensions.ts b/packages/grafana-data/src/types/pluginExtensions.ts index 32764409a8d..488eced154a 100644 --- a/packages/grafana-data/src/types/pluginExtensions.ts +++ b/packages/grafana-data/src/types/pluginExtensions.ts @@ -250,6 +250,7 @@ export type PluginExtensionCommandPaletteContext = {}; export type PluginExtensionResourceAttributesContext = { // Key-value pairs of resource attributes, attribute name is the key attributes: Record; + spanAttributes?: Record; datasource: { type: string; uid: string; diff --git a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/index.tsx b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/index.tsx index 627e8fc2ec4..99575f7badc 100644 --- a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/index.tsx +++ b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/index.tsx @@ -51,7 +51,12 @@ import { ShareSpanButton } from './ShareSpanButton'; import { getSpanDetailLinkButtons } from './SpanDetailLinkButtons'; import SpanFlameGraph from './SpanFlameGraph'; -const useResourceAttributesExtensionLinks = (process: TraceProcess, datasourceType: string, datasourceUid: string) => { +const useResourceAttributesExtensionLinks = ( + process: TraceProcess, + spanTags: TraceKeyValuePair[], + datasourceType: string, + datasourceUid: string +) => { // Stable context for useMemo inside usePluginLinks const context: PluginExtensionResourceAttributesContext = useMemo(() => { const attributes = (process.tags ?? []).reduce>((acc, tag) => { @@ -63,14 +68,24 @@ const useResourceAttributesExtensionLinks = (process: TraceProcess, datasourceTy return acc; }, {}); + const spanAttributes = (spanTags ?? []).reduce>((acc, tag) => { + if (acc[tag.key]) { + acc[tag.key].push(tag.value); + } else { + acc[tag.key] = [tag.value]; + } + return acc; + }, {}); + return { attributes, + spanAttributes, datasource: { type: datasourceType, uid: datasourceUid, }, }; - }, [process.tags, datasourceType, datasourceUid]); + }, [process.tags, spanTags, datasourceType, datasourceUid]); const { links } = usePluginLinks({ extensionPointId: PluginExtensionPoints.TraceViewResourceAttributes, @@ -328,7 +343,7 @@ export default function SpanDetail(props: SpanDetailProps) { }); const focusSpanLink = createFocusSpanLink(traceID, spanID); - const resourceLinksGetter = useResourceAttributesExtensionLinks(process, datasourceType, datasourceUid); + const resourceLinksGetter = useResourceAttributesExtensionLinks(process, tags, datasourceType, datasourceUid); return (
@@ -348,6 +363,7 @@ export default function SpanDetail(props: SpanDetailProps) { data={tags} label={t('explore.span-detail.label-span-attributes', 'Span attributes')} isOpen={isTagsOpen} + linksGetter={resourceLinksGetter} onToggle={() => tagsToggle(spanID)} /> {process.tags && ( From 343fe4dadf51bdf927b629ae1c3f68a5a44a946c Mon Sep 17 00:00:00 2001 From: Matheus Macabu Date: Mon, 4 Aug 2025 08:26:07 +0200 Subject: [PATCH 45/89] Secrets: Introduce inline secure value service proto (#109029) * Secrets: Introduce inline secure value service proto * Fix secure value description * Add orgid to obo auth context for testing --- apps/secret/inline/v1beta1/inline.pb.go | 515 ++++++++++++++++++ apps/secret/inline/v1beta1/inline.proto | 67 +++ apps/secret/inline/v1beta1/inline_grpc.pb.go | 190 +++++++ .../secret/service/inline_secure_value.go | 2 +- .../apis/secret/testutils/testutils.go | 1 + 5 files changed, 774 insertions(+), 1 deletion(-) create mode 100644 apps/secret/inline/v1beta1/inline.pb.go create mode 100644 apps/secret/inline/v1beta1/inline.proto create mode 100644 apps/secret/inline/v1beta1/inline_grpc.pb.go diff --git a/apps/secret/inline/v1beta1/inline.pb.go b/apps/secret/inline/v1beta1/inline.pb.go new file mode 100644 index 00000000000..d759693f4e0 --- /dev/null +++ b/apps/secret/inline/v1beta1/inline.pb.go @@ -0,0 +1,515 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.5 +// protoc (unknown) +// source: inline/v1beta1/inline.proto + +package inlinev1beta1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ObjectReference struct { + state protoimpl.MessageState `protogen:"open.v1"` + // APIGroup is the name of the API group that contains the referred object. + // The empty string represents the core API group. + ApiGroup string `protobuf:"bytes,1,opt,name=api_group,json=apiGroup,proto3" json:"api_group,omitempty"` + // APIVersion is the version of the API group that contains the referred object. + ApiVersion string `protobuf:"bytes,2,opt,name=api_version,json=apiVersion,proto3" json:"api_version,omitempty"` + // See https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#types-kinds + Kind string `protobuf:"bytes,3,opt,name=kind,proto3" json:"kind,omitempty"` + // Tenant isolation + Namespace string `protobuf:"bytes,4,opt,name=namespace,proto3" json:"namespace,omitempty"` + // Explicit resource identifier + Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ObjectReference) Reset() { + *x = ObjectReference{} + mi := &file_inline_v1beta1_inline_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ObjectReference) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ObjectReference) ProtoMessage() {} + +func (x *ObjectReference) ProtoReflect() protoreflect.Message { + mi := &file_inline_v1beta1_inline_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ObjectReference.ProtoReflect.Descriptor instead. +func (*ObjectReference) Descriptor() ([]byte, []int) { + return file_inline_v1beta1_inline_proto_rawDescGZIP(), []int{0} +} + +func (x *ObjectReference) GetApiGroup() string { + if x != nil { + return x.ApiGroup + } + return "" +} + +func (x *ObjectReference) GetApiVersion() string { + if x != nil { + return x.ApiVersion + } + return "" +} + +func (x *ObjectReference) GetKind() string { + if x != nil { + return x.Kind + } + return "" +} + +func (x *ObjectReference) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *ObjectReference) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type CanReferenceRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Owner reference. + Owner *ObjectReference `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` + // Secure value names to check. + Names []string `protobuf:"bytes,2,rep,name=names,proto3" json:"names,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CanReferenceRequest) Reset() { + *x = CanReferenceRequest{} + mi := &file_inline_v1beta1_inline_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CanReferenceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CanReferenceRequest) ProtoMessage() {} + +func (x *CanReferenceRequest) ProtoReflect() protoreflect.Message { + mi := &file_inline_v1beta1_inline_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CanReferenceRequest.ProtoReflect.Descriptor instead. +func (*CanReferenceRequest) Descriptor() ([]byte, []int) { + return file_inline_v1beta1_inline_proto_rawDescGZIP(), []int{1} +} + +func (x *CanReferenceRequest) GetOwner() *ObjectReference { + if x != nil { + return x.Owner + } + return nil +} + +func (x *CanReferenceRequest) GetNames() []string { + if x != nil { + return x.Names + } + return nil +} + +type CanReferenceResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CanReferenceResponse) Reset() { + *x = CanReferenceResponse{} + mi := &file_inline_v1beta1_inline_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CanReferenceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CanReferenceResponse) ProtoMessage() {} + +func (x *CanReferenceResponse) ProtoReflect() protoreflect.Message { + mi := &file_inline_v1beta1_inline_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CanReferenceResponse.ProtoReflect.Descriptor instead. +func (*CanReferenceResponse) Descriptor() ([]byte, []int) { + return file_inline_v1beta1_inline_proto_rawDescGZIP(), []int{2} +} + +type CreateInlineRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Owner reference. + Owner *ObjectReference `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` + // Raw secret value. + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateInlineRequest) Reset() { + *x = CreateInlineRequest{} + mi := &file_inline_v1beta1_inline_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateInlineRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateInlineRequest) ProtoMessage() {} + +func (x *CreateInlineRequest) ProtoReflect() protoreflect.Message { + mi := &file_inline_v1beta1_inline_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateInlineRequest.ProtoReflect.Descriptor instead. +func (*CreateInlineRequest) Descriptor() ([]byte, []int) { + return file_inline_v1beta1_inline_proto_rawDescGZIP(), []int{3} +} + +func (x *CreateInlineRequest) GetOwner() *ObjectReference { + if x != nil { + return x.Owner + } + return nil +} + +func (x *CreateInlineRequest) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +type CreateInlineResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The name of the created secure value. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateInlineResponse) Reset() { + *x = CreateInlineResponse{} + mi := &file_inline_v1beta1_inline_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateInlineResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateInlineResponse) ProtoMessage() {} + +func (x *CreateInlineResponse) ProtoReflect() protoreflect.Message { + mi := &file_inline_v1beta1_inline_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateInlineResponse.ProtoReflect.Descriptor instead. +func (*CreateInlineResponse) Descriptor() ([]byte, []int) { + return file_inline_v1beta1_inline_proto_rawDescGZIP(), []int{4} +} + +func (x *CreateInlineResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type DeleteWhenOwnedByResourceRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Owner reference. + Owner *ObjectReference `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` + // Name of the secure value to delete. + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteWhenOwnedByResourceRequest) Reset() { + *x = DeleteWhenOwnedByResourceRequest{} + mi := &file_inline_v1beta1_inline_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteWhenOwnedByResourceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteWhenOwnedByResourceRequest) ProtoMessage() {} + +func (x *DeleteWhenOwnedByResourceRequest) ProtoReflect() protoreflect.Message { + mi := &file_inline_v1beta1_inline_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteWhenOwnedByResourceRequest.ProtoReflect.Descriptor instead. +func (*DeleteWhenOwnedByResourceRequest) Descriptor() ([]byte, []int) { + return file_inline_v1beta1_inline_proto_rawDescGZIP(), []int{5} +} + +func (x *DeleteWhenOwnedByResourceRequest) GetOwner() *ObjectReference { + if x != nil { + return x.Owner + } + return nil +} + +func (x *DeleteWhenOwnedByResourceRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type DeleteWhenOwnedByResourceResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteWhenOwnedByResourceResponse) Reset() { + *x = DeleteWhenOwnedByResourceResponse{} + mi := &file_inline_v1beta1_inline_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteWhenOwnedByResourceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteWhenOwnedByResourceResponse) ProtoMessage() {} + +func (x *DeleteWhenOwnedByResourceResponse) ProtoReflect() protoreflect.Message { + mi := &file_inline_v1beta1_inline_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteWhenOwnedByResourceResponse.ProtoReflect.Descriptor instead. +func (*DeleteWhenOwnedByResourceResponse) Descriptor() ([]byte, []int) { + return file_inline_v1beta1_inline_proto_rawDescGZIP(), []int{6} +} + +var File_inline_v1beta1_inline_proto protoreflect.FileDescriptor + +var file_inline_v1beta1_inline_proto_rawDesc = string([]byte{ + 0x0a, 0x1b, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2f, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x22, 0x95, 0x01, 0x0a, + 0x0f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x69, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x70, 0x69, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1f, 0x0a, + 0x0b, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, + 0x6e, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x61, 0x0a, 0x13, 0x43, 0x61, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x05, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x16, 0x0a, 0x14, 0x43, 0x61, 0x6e, 0x52, 0x65, + 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x61, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x2a, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x6c, + 0x0a, 0x20, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x68, 0x65, 0x6e, 0x4f, 0x77, 0x6e, 0x65, + 0x64, 0x42, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x34, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, + 0x31, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, + 0x65, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x23, 0x0a, 0x21, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x68, 0x65, 0x6e, 0x4f, 0x77, 0x6e, 0x65, 0x64, 0x42, + 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x32, 0xcc, 0x02, 0x0a, 0x18, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x57, + 0x0a, 0x0c, 0x43, 0x61, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x22, + 0x2e, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, + 0x61, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x22, 0x2e, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x69, 0x6e, + 0x6c, 0x69, 0x6e, 0x65, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x7e, 0x0a, 0x19, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x68, 0x65, 0x6e, 0x4f, 0x77, + 0x6e, 0x65, 0x64, 0x42, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2f, 0x2e, + 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x57, 0x68, 0x65, 0x6e, 0x4f, 0x77, 0x6e, 0x65, 0x64, 0x42, 0x79, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, + 0x2e, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x68, 0x65, 0x6e, 0x4f, 0x77, 0x6e, 0x65, 0x64, 0x42, 0x79, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x45, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, + 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x61, + 0x70, 0x70, 0x73, 0x2f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x2f, 0x69, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +}) + +var ( + file_inline_v1beta1_inline_proto_rawDescOnce sync.Once + file_inline_v1beta1_inline_proto_rawDescData []byte +) + +func file_inline_v1beta1_inline_proto_rawDescGZIP() []byte { + file_inline_v1beta1_inline_proto_rawDescOnce.Do(func() { + file_inline_v1beta1_inline_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_inline_v1beta1_inline_proto_rawDesc), len(file_inline_v1beta1_inline_proto_rawDesc))) + }) + return file_inline_v1beta1_inline_proto_rawDescData +} + +var file_inline_v1beta1_inline_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_inline_v1beta1_inline_proto_goTypes = []any{ + (*ObjectReference)(nil), // 0: inlinev1beta1.ObjectReference + (*CanReferenceRequest)(nil), // 1: inlinev1beta1.CanReferenceRequest + (*CanReferenceResponse)(nil), // 2: inlinev1beta1.CanReferenceResponse + (*CreateInlineRequest)(nil), // 3: inlinev1beta1.CreateInlineRequest + (*CreateInlineResponse)(nil), // 4: inlinev1beta1.CreateInlineResponse + (*DeleteWhenOwnedByResourceRequest)(nil), // 5: inlinev1beta1.DeleteWhenOwnedByResourceRequest + (*DeleteWhenOwnedByResourceResponse)(nil), // 6: inlinev1beta1.DeleteWhenOwnedByResourceResponse +} +var file_inline_v1beta1_inline_proto_depIdxs = []int32{ + 0, // 0: inlinev1beta1.CanReferenceRequest.owner:type_name -> inlinev1beta1.ObjectReference + 0, // 1: inlinev1beta1.CreateInlineRequest.owner:type_name -> inlinev1beta1.ObjectReference + 0, // 2: inlinev1beta1.DeleteWhenOwnedByResourceRequest.owner:type_name -> inlinev1beta1.ObjectReference + 1, // 3: inlinev1beta1.InlineSecureValueService.CanReference:input_type -> inlinev1beta1.CanReferenceRequest + 3, // 4: inlinev1beta1.InlineSecureValueService.CreateInline:input_type -> inlinev1beta1.CreateInlineRequest + 5, // 5: inlinev1beta1.InlineSecureValueService.DeleteWhenOwnedByResource:input_type -> inlinev1beta1.DeleteWhenOwnedByResourceRequest + 2, // 6: inlinev1beta1.InlineSecureValueService.CanReference:output_type -> inlinev1beta1.CanReferenceResponse + 4, // 7: inlinev1beta1.InlineSecureValueService.CreateInline:output_type -> inlinev1beta1.CreateInlineResponse + 6, // 8: inlinev1beta1.InlineSecureValueService.DeleteWhenOwnedByResource:output_type -> inlinev1beta1.DeleteWhenOwnedByResourceResponse + 6, // [6:9] is the sub-list for method output_type + 3, // [3:6] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_inline_v1beta1_inline_proto_init() } +func file_inline_v1beta1_inline_proto_init() { + if File_inline_v1beta1_inline_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_inline_v1beta1_inline_proto_rawDesc), len(file_inline_v1beta1_inline_proto_rawDesc)), + NumEnums: 0, + NumMessages: 7, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_inline_v1beta1_inline_proto_goTypes, + DependencyIndexes: file_inline_v1beta1_inline_proto_depIdxs, + MessageInfos: file_inline_v1beta1_inline_proto_msgTypes, + }.Build() + File_inline_v1beta1_inline_proto = out.File + file_inline_v1beta1_inline_proto_goTypes = nil + file_inline_v1beta1_inline_proto_depIdxs = nil +} diff --git a/apps/secret/inline/v1beta1/inline.proto b/apps/secret/inline/v1beta1/inline.proto new file mode 100644 index 00000000000..493b855c517 --- /dev/null +++ b/apps/secret/inline/v1beta1/inline.proto @@ -0,0 +1,67 @@ +syntax = "proto3"; + +package inlinev1beta1; + +option go_package = "github.com/grafana/grafana/apps/secret/inline/v1beta1;inlinev1beta1"; + +message ObjectReference { + // APIGroup is the name of the API group that contains the referred object. + // The empty string represents the core API group. + string api_group = 1; + + // APIVersion is the version of the API group that contains the referred object. + string api_version = 2; + + // See https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#types-kinds + string kind = 3; + + // Tenant isolation + string namespace = 4; + + // Explicit resource identifier + string name = 5; +} + +message CanReferenceRequest { + // Owner reference. + ObjectReference owner = 1; + + // Secure value names to check. + repeated string names = 2; +} + +message CanReferenceResponse {} + +message CreateInlineRequest { + // Owner reference. + ObjectReference owner = 1; + + // Raw secret value. + string value = 2; +} + +message CreateInlineResponse { + // The name of the created secure value. + string name = 1; +} + +message DeleteWhenOwnedByResourceRequest { + // Owner reference. + ObjectReference owner = 1; + + // Name of the secure value to delete. + string name = 2; +} + +message DeleteWhenOwnedByResourceResponse {} + +service InlineSecureValueService { + // Check that the request user can reference a secret in the context of a given resource (owner) + rpc CanReference(CanReferenceRequest) returns (CanReferenceResponse); + + // CreateInline creates a secret that is owned by the referenced object. Returns the name of the created secret or an error + rpc CreateInline(CreateInlineRequest) returns (CreateInlineResponse); + + // DeleteWhenOwnedByResource removes secrets if and only if they are owned by a referenced object + rpc DeleteWhenOwnedByResource(DeleteWhenOwnedByResourceRequest) returns (DeleteWhenOwnedByResourceResponse); +} diff --git a/apps/secret/inline/v1beta1/inline_grpc.pb.go b/apps/secret/inline/v1beta1/inline_grpc.pb.go new file mode 100644 index 00000000000..2ce117adb7d --- /dev/null +++ b/apps/secret/inline/v1beta1/inline_grpc.pb.go @@ -0,0 +1,190 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.4.0 +// - protoc (unknown) +// source: inline/v1beta1/inline.proto + +package inlinev1beta1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.62.0 or later. +const _ = grpc.SupportPackageIsVersion8 + +const ( + InlineSecureValueService_CanReference_FullMethodName = "/inlinev1beta1.InlineSecureValueService/CanReference" + InlineSecureValueService_CreateInline_FullMethodName = "/inlinev1beta1.InlineSecureValueService/CreateInline" + InlineSecureValueService_DeleteWhenOwnedByResource_FullMethodName = "/inlinev1beta1.InlineSecureValueService/DeleteWhenOwnedByResource" +) + +// InlineSecureValueServiceClient is the client API for InlineSecureValueService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type InlineSecureValueServiceClient interface { + // Check that the request user can reference a secret in the context of a given resource (owner) + CanReference(ctx context.Context, in *CanReferenceRequest, opts ...grpc.CallOption) (*CanReferenceResponse, error) + // CreateInline creates a secret that is owned by the referenced object. Returns the name of the created secret or an error + CreateInline(ctx context.Context, in *CreateInlineRequest, opts ...grpc.CallOption) (*CreateInlineResponse, error) + // DeleteWhenOwnedByResource removes secrets if and only if they are owned by a referenced object + DeleteWhenOwnedByResource(ctx context.Context, in *DeleteWhenOwnedByResourceRequest, opts ...grpc.CallOption) (*DeleteWhenOwnedByResourceResponse, error) +} + +type inlineSecureValueServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewInlineSecureValueServiceClient(cc grpc.ClientConnInterface) InlineSecureValueServiceClient { + return &inlineSecureValueServiceClient{cc} +} + +func (c *inlineSecureValueServiceClient) CanReference(ctx context.Context, in *CanReferenceRequest, opts ...grpc.CallOption) (*CanReferenceResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CanReferenceResponse) + err := c.cc.Invoke(ctx, InlineSecureValueService_CanReference_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *inlineSecureValueServiceClient) CreateInline(ctx context.Context, in *CreateInlineRequest, opts ...grpc.CallOption) (*CreateInlineResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CreateInlineResponse) + err := c.cc.Invoke(ctx, InlineSecureValueService_CreateInline_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *inlineSecureValueServiceClient) DeleteWhenOwnedByResource(ctx context.Context, in *DeleteWhenOwnedByResourceRequest, opts ...grpc.CallOption) (*DeleteWhenOwnedByResourceResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DeleteWhenOwnedByResourceResponse) + err := c.cc.Invoke(ctx, InlineSecureValueService_DeleteWhenOwnedByResource_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// InlineSecureValueServiceServer is the server API for InlineSecureValueService service. +// All implementations should embed UnimplementedInlineSecureValueServiceServer +// for forward compatibility +type InlineSecureValueServiceServer interface { + // Check that the request user can reference a secret in the context of a given resource (owner) + CanReference(context.Context, *CanReferenceRequest) (*CanReferenceResponse, error) + // CreateInline creates a secret that is owned by the referenced object. Returns the name of the created secret or an error + CreateInline(context.Context, *CreateInlineRequest) (*CreateInlineResponse, error) + // DeleteWhenOwnedByResource removes secrets if and only if they are owned by a referenced object + DeleteWhenOwnedByResource(context.Context, *DeleteWhenOwnedByResourceRequest) (*DeleteWhenOwnedByResourceResponse, error) +} + +// UnimplementedInlineSecureValueServiceServer should be embedded to have forward compatible implementations. +type UnimplementedInlineSecureValueServiceServer struct { +} + +func (UnimplementedInlineSecureValueServiceServer) CanReference(context.Context, *CanReferenceRequest) (*CanReferenceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CanReference not implemented") +} +func (UnimplementedInlineSecureValueServiceServer) CreateInline(context.Context, *CreateInlineRequest) (*CreateInlineResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateInline not implemented") +} +func (UnimplementedInlineSecureValueServiceServer) DeleteWhenOwnedByResource(context.Context, *DeleteWhenOwnedByResourceRequest) (*DeleteWhenOwnedByResourceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteWhenOwnedByResource not implemented") +} + +// UnsafeInlineSecureValueServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to InlineSecureValueServiceServer will +// result in compilation errors. +type UnsafeInlineSecureValueServiceServer interface { + mustEmbedUnimplementedInlineSecureValueServiceServer() +} + +func RegisterInlineSecureValueServiceServer(s grpc.ServiceRegistrar, srv InlineSecureValueServiceServer) { + s.RegisterService(&InlineSecureValueService_ServiceDesc, srv) +} + +func _InlineSecureValueService_CanReference_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CanReferenceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InlineSecureValueServiceServer).CanReference(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InlineSecureValueService_CanReference_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InlineSecureValueServiceServer).CanReference(ctx, req.(*CanReferenceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _InlineSecureValueService_CreateInline_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateInlineRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InlineSecureValueServiceServer).CreateInline(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InlineSecureValueService_CreateInline_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InlineSecureValueServiceServer).CreateInline(ctx, req.(*CreateInlineRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _InlineSecureValueService_DeleteWhenOwnedByResource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteWhenOwnedByResourceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InlineSecureValueServiceServer).DeleteWhenOwnedByResource(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InlineSecureValueService_DeleteWhenOwnedByResource_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InlineSecureValueServiceServer).DeleteWhenOwnedByResource(ctx, req.(*DeleteWhenOwnedByResourceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// InlineSecureValueService_ServiceDesc is the grpc.ServiceDesc for InlineSecureValueService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var InlineSecureValueService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "inlinev1beta1.InlineSecureValueService", + HandlerType: (*InlineSecureValueServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CanReference", + Handler: _InlineSecureValueService_CanReference_Handler, + }, + { + MethodName: "CreateInline", + Handler: _InlineSecureValueService_CreateInline_Handler, + }, + { + MethodName: "DeleteWhenOwnedByResource", + Handler: _InlineSecureValueService_DeleteWhenOwnedByResource_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "inline/v1beta1/inline.proto", +} diff --git a/pkg/registry/apis/secret/service/inline_secure_value.go b/pkg/registry/apis/secret/service/inline_secure_value.go index 665bc622f54..365ff00cd6e 100644 --- a/pkg/registry/apis/secret/service/inline_secure_value.go +++ b/pkg/registry/apis/secret/service/inline_secure_value.go @@ -200,7 +200,7 @@ func (s *inlineSecureValueService) CreateInline(ctx context.Context, owner commo OwnerReferences: []metav1.OwnerReference{owner.ToOwnerReference()}, }, Spec: secretv1beta1.SecureValueSpec{ - Description: fmt.Sprintf("Inline secure value for %s/%s in %s/%s", owner.Kind, owner.Name, owner.APIVersion, owner.APIVersion), + Description: fmt.Sprintf("Inline secure value for %s/%s in %s/%s", owner.Kind, owner.Name, owner.APIGroup, owner.APIVersion), Value: &secret, Decrypters: []string{ serviceIdentity, diff --git a/pkg/registry/apis/secret/testutils/testutils.go b/pkg/registry/apis/secret/testutils/testutils.go index 3e742439bb0..4c000e76908 100644 --- a/pkg/registry/apis/secret/testutils/testutils.go +++ b/pkg/registry/apis/secret/testutils/testutils.go @@ -269,6 +269,7 @@ func CreateOBOAuthContext( requester := &identity.StaticRequester{ Namespace: namespace, Type: types.TypeUser, + OrgID: 1, UserID: 1, Permissions: map[int64]map[string][]string{ 1: userPermissions, From 81f544e186aa7df967964782905e2cd3033f8590 Mon Sep 17 00:00:00 2001 From: Matheus Macabu Date: Mon, 4 Aug 2025 08:51:15 +0200 Subject: [PATCH 46/89] Secrets: Add service name as explicit parameter for Decrypt (#109054) * Secrets: Add service name as explicit parameter for Decrypt * Apply suggestions from code review Co-authored-by: Stephanie Hingtgen --------- Co-authored-by: Stephanie Hingtgen --- .../secrets/mocks/decrypt_service_mock.go | 45 +++++++------------ .../apis/provisioning/secrets/secret.go | 16 +------ .../apis/provisioning/secrets/secret_test.go | 15 ++++--- pkg/registry/apis/secret/contracts/decrypt.go | 2 +- .../apis/secret/decrypt/grpc_client.go | 26 +++-------- .../apis/secret/decrypt/local_client.go | 11 ++++- .../apis/secret/decrypt/service_test.go | 10 ++--- .../service/inline_secure_value_test.go | 4 +- .../secret/metadata/secure_value_test.go | 6 +-- 9 files changed, 51 insertions(+), 84 deletions(-) diff --git a/pkg/registry/apis/provisioning/secrets/mocks/decrypt_service_mock.go b/pkg/registry/apis/provisioning/secrets/mocks/decrypt_service_mock.go index b5cca7ebe62..967e77bf216 100644 --- a/pkg/registry/apis/provisioning/secrets/mocks/decrypt_service_mock.go +++ b/pkg/registry/apis/provisioning/secrets/mocks/decrypt_service_mock.go @@ -67,16 +67,9 @@ func (_c *MockDecryptService_Close_Call) RunAndReturn(run func() error) *MockDec return _c } -// Decrypt provides a mock function with given fields: ctx, namespace, names -func (_m *MockDecryptService) Decrypt(ctx context.Context, namespace string, names ...string) (map[string]contracts.DecryptResult, error) { - _va := make([]interface{}, len(names)) - for _i := range names { - _va[_i] = names[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, namespace) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// Decrypt provides a mock function with given fields: ctx, serviceName, namespace, names +func (_m *MockDecryptService) Decrypt(ctx context.Context, serviceName string, namespace string, names []string) (map[string]contracts.DecryptResult, error) { + ret := _m.Called(ctx, serviceName, namespace, names) if len(ret) == 0 { panic("no return value specified for Decrypt") @@ -84,19 +77,19 @@ func (_m *MockDecryptService) Decrypt(ctx context.Context, namespace string, nam var r0 map[string]contracts.DecryptResult var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, ...string) (map[string]contracts.DecryptResult, error)); ok { - return rf(ctx, namespace, names...) + if rf, ok := ret.Get(0).(func(context.Context, string, string, []string) (map[string]contracts.DecryptResult, error)); ok { + return rf(ctx, serviceName, namespace, names) } - if rf, ok := ret.Get(0).(func(context.Context, string, ...string) map[string]contracts.DecryptResult); ok { - r0 = rf(ctx, namespace, names...) + if rf, ok := ret.Get(0).(func(context.Context, string, string, []string) map[string]contracts.DecryptResult); ok { + r0 = rf(ctx, serviceName, namespace, names) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(map[string]contracts.DecryptResult) } } - if rf, ok := ret.Get(1).(func(context.Context, string, ...string) error); ok { - r1 = rf(ctx, namespace, names...) + if rf, ok := ret.Get(1).(func(context.Context, string, string, []string) error); ok { + r1 = rf(ctx, serviceName, namespace, names) } else { r1 = ret.Error(1) } @@ -111,22 +104,16 @@ type MockDecryptService_Decrypt_Call struct { // Decrypt is a helper method to define mock.On call // - ctx context.Context +// - serviceName string // - namespace string -// - names ...string -func (_e *MockDecryptService_Expecter) Decrypt(ctx interface{}, namespace interface{}, names ...interface{}) *MockDecryptService_Decrypt_Call { - return &MockDecryptService_Decrypt_Call{Call: _e.mock.On("Decrypt", - append([]interface{}{ctx, namespace}, names...)...)} +// - names []string +func (_e *MockDecryptService_Expecter) Decrypt(ctx interface{}, serviceName interface{}, namespace interface{}, names interface{}) *MockDecryptService_Decrypt_Call { + return &MockDecryptService_Decrypt_Call{Call: _e.mock.On("Decrypt", ctx, serviceName, namespace, names)} } -func (_c *MockDecryptService_Decrypt_Call) Run(run func(ctx context.Context, namespace string, names ...string)) *MockDecryptService_Decrypt_Call { +func (_c *MockDecryptService_Decrypt_Call) Run(run func(ctx context.Context, serviceName string, namespace string, names []string)) *MockDecryptService_Decrypt_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]string, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(string) - } - } - run(args[0].(context.Context), args[1].(string), variadicArgs...) + run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].([]string)) }) return _c } @@ -136,7 +123,7 @@ func (_c *MockDecryptService_Decrypt_Call) Return(_a0 map[string]contracts.Decry return _c } -func (_c *MockDecryptService_Decrypt_Call) RunAndReturn(run func(context.Context, string, ...string) (map[string]contracts.DecryptResult, error)) *MockDecryptService_Decrypt_Call { +func (_c *MockDecryptService_Decrypt_Call) RunAndReturn(run func(context.Context, string, string, []string) (map[string]contracts.DecryptResult, error)) *MockDecryptService_Decrypt_Call { _c.Call.Return(run) return _c } diff --git a/pkg/registry/apis/provisioning/secrets/secret.go b/pkg/registry/apis/provisioning/secrets/secret.go index 9127e7b7868..f0c69e88153 100644 --- a/pkg/registry/apis/provisioning/secrets/secret.go +++ b/pkg/registry/apis/provisioning/secrets/secret.go @@ -4,8 +4,6 @@ import ( "context" "errors" - "github.com/grafana/authlib/types" - "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/registry/apis/secret" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/setting" @@ -109,13 +107,7 @@ func (s *secretsService) Encrypt(ctx context.Context, namespace, name string, da } func (s *secretsService) Decrypt(ctx context.Context, namespace string, name string) ([]byte, error) { - ns, err := types.ParseNamespace(namespace) - if err != nil { - return nil, err - } - ctx = identity.WithServiceIdentityContext(ctx, ns.OrgID, identity.WithServiceIdentityName(svcName)) - - results, err := s.decryptSvc.Decrypt(ctx, namespace, name) + results, err := s.decryptSvc.Decrypt(ctx, svcName, namespace, []string{name}) if err != nil { return nil, err } @@ -132,12 +124,6 @@ func (s *secretsService) Decrypt(ctx context.Context, namespace string, name str } func (s *secretsService) Delete(ctx context.Context, namespace string, name string) error { - ns, err := types.ParseNamespace(namespace) - if err != nil { - return err - } - - ctx = identity.WithServiceIdentityContext(ctx, ns.OrgID, identity.WithServiceIdentityName(svcName)) client, err := s.secureValues.Client(ctx, namespace) if err != nil { return err diff --git a/pkg/registry/apis/provisioning/secrets/secret_test.go b/pkg/registry/apis/provisioning/secrets/secret_test.go index e393ac7d8dd..d7097975f43 100644 --- a/pkg/registry/apis/provisioning/secrets/secret_test.go +++ b/pkg/registry/apis/provisioning/secrets/secret_test.go @@ -266,8 +266,9 @@ func TestSecretsService_Decrypt(t *testing.T) { // Verify that the context is not nil (the service creates a new StaticRequester) return ctx != nil }), + svcName, "test-namespace", - "test-secret", + []string{"test-secret"}, ).Return(map[string]secret.DecryptResult{ "test-secret": mockResult, }, nil) @@ -283,8 +284,9 @@ func TestSecretsService_Decrypt(t *testing.T) { mock.MatchedBy(func(ctx context.Context) bool { return ctx != nil }), + svcName, "test-namespace", - "test-secret", + []string{"test-secret"}, ).Return(nil, errors.New("decrypt service error")) }, expectedError: "decrypt service error", @@ -298,8 +300,9 @@ func TestSecretsService_Decrypt(t *testing.T) { mock.MatchedBy(func(ctx context.Context) bool { return ctx != nil }), + svcName, "test-namespace", - "test-secret", + []string{"test-secret"}, ).Return(map[string]secret.DecryptResult{}, nil) }, expectedError: secret.ErrDecryptNotFound.Error(), @@ -315,8 +318,9 @@ func TestSecretsService_Decrypt(t *testing.T) { mock.MatchedBy(func(ctx context.Context) bool { return ctx != nil }), + svcName, "test-namespace", - "test-secret", + []string{"test-secret"}, ).Return(map[string]secret.DecryptResult{ "test-secret": mockResult, }, nil) @@ -363,8 +367,9 @@ func TestSecretsService_Decrypt_ServiceIdentityContext(t *testing.T) { // At minimum, verify the context is not nil and is different from the original return ctx != nil }), + svcName, "test-namespace", - "test-secret", + []string{"test-secret"}, ).Return(map[string]secret.DecryptResult{ "test-secret": mockResult, }, nil) diff --git a/pkg/registry/apis/secret/contracts/decrypt.go b/pkg/registry/apis/secret/contracts/decrypt.go index 2c5403c790d..d0bf52ae65a 100644 --- a/pkg/registry/apis/secret/contracts/decrypt.go +++ b/pkg/registry/apis/secret/contracts/decrypt.go @@ -29,7 +29,7 @@ type DecryptAuthorizer interface { // DecryptService is the interface for the decrypt service. type DecryptService interface { - Decrypt(ctx context.Context, namespace string, names ...string) (map[string]DecryptResult, error) + Decrypt(ctx context.Context, serviceName string, namespace string, names []string) (map[string]DecryptResult, error) Close() error } diff --git a/pkg/registry/apis/secret/decrypt/grpc_client.go b/pkg/registry/apis/secret/decrypt/grpc_client.go index 9851eec4526..f0af3967734 100644 --- a/pkg/registry/apis/secret/decrypt/grpc_client.go +++ b/pkg/registry/apis/secret/decrypt/grpc_client.go @@ -10,7 +10,7 @@ import ( "github.com/fullstorydev/grpchan" authnlib "github.com/grafana/authlib/authn" - claims "github.com/grafana/authlib/types" + "github.com/grafana/authlib/types" "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -127,25 +127,11 @@ func (g *GRPCDecryptClient) Close() error { return nil } -func (g *GRPCDecryptClient) Decrypt(ctx context.Context, namespace string, names ...string) (map[string]contracts.DecryptResult, error) { - authInfo, ok := claims.AuthInfoFrom(ctx) - if !ok { - return nil, errors.New("missing auth info in context") +func (g *GRPCDecryptClient) Decrypt(ctx context.Context, serviceName string, namespace string, names []string) (map[string]contracts.DecryptResult, error) { + _, err := types.ParseNamespace(namespace) + if err != nil { + return nil, err } - - // Up until here the identity is the one set by the internal service, but when the request goes out to the gRPC server, - // the aggregator will use the access token which contains a different service identity for grafana as a whole. - // This is used for logging purposes only. - serviceIdentityList, ok := authInfo.GetExtra()[authnlib.ServiceIdentityKey] - if !ok || len(serviceIdentityList) != 1 { - return nil, errors.New("invalid service identity in auth info") - } - - serviceIdentity := serviceIdentityList[0] - if len(serviceIdentity) == 0 { - return nil, errors.New("empty service identity in auth info") - } - req := &decryptv1beta1.SecureValueDecryptRequest{ Namespace: namespace, Names: names, @@ -154,7 +140,7 @@ func (g *GRPCDecryptClient) Decrypt(ctx context.Context, namespace string, names // Decryption will still use the service identity from the auth token, // but we also pass the service identity from the request metadata for auditing purposes. md := metadata.New(map[string]string{ - contracts.HeaderGrafanaServiceIdentityName: serviceIdentity, + contracts.HeaderGrafanaServiceIdentityName: serviceName, }) ctx = metadata.NewOutgoingContext(ctx, md) diff --git a/pkg/registry/apis/secret/decrypt/local_client.go b/pkg/registry/apis/secret/decrypt/local_client.go index 6aa3f89ebe6..5b232c0413c 100644 --- a/pkg/registry/apis/secret/decrypt/local_client.go +++ b/pkg/registry/apis/secret/decrypt/local_client.go @@ -3,6 +3,8 @@ package decrypt import ( "context" + "github.com/grafana/authlib/types" + "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" ) @@ -19,7 +21,14 @@ func NewLocalDecryptClient(decryptStorage contracts.DecryptStorage) (*LocalDecry }, nil } -func (c *LocalDecryptClient) Decrypt(ctx context.Context, namespace string, names ...string) (map[string]contracts.DecryptResult, error) { +func (c *LocalDecryptClient) Decrypt(ctx context.Context, serviceName, namespace string, names []string) (map[string]contracts.DecryptResult, error) { + ns, err := types.ParseNamespace(namespace) + if err != nil { + return nil, err + } + + ctx = identity.WithServiceIdentityContext(ctx, ns.OrgID, identity.WithServiceIdentityName(serviceName)) + results := make(map[string]contracts.DecryptResult, len(names)) for _, name := range names { diff --git a/pkg/registry/apis/secret/decrypt/service_test.go b/pkg/registry/apis/secret/decrypt/service_test.go index 53091f27bc4..d108d0d15ff 100644 --- a/pkg/registry/apis/secret/decrypt/service_test.go +++ b/pkg/registry/apis/secret/decrypt/service_test.go @@ -20,7 +20,6 @@ import ( "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" - "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/registry/apis/secret/xkube" "github.com/grafana/grafana/pkg/services/authn/clients" @@ -49,7 +48,7 @@ func TestDecryptService(t *testing.T) { decryptService, err := ProvideDecryptService(cfg, tracer, mockStorage) require.NoError(t, err) - resp, err := decryptService.Decrypt(ctx, "default", "secure-value-1") + resp, err := decryptService.Decrypt(ctx, "svc-name", "default", []string{"secure-value-1"}) require.NotNil(t, resp) require.NoError(t, err) require.EqualValues(t, decryptedValuesResp, resp) @@ -78,7 +77,7 @@ func TestDecryptService(t *testing.T) { decryptService, err := ProvideDecryptService(cfg, tracer, mockStorage) require.NoError(t, err) - resp, err := decryptService.Decrypt(ctx, "default", "secure-value-1", "secure-value-2") + resp, err := decryptService.Decrypt(ctx, "svc-name", "default", []string{"secure-value-1", "secure-value-2"}) require.NotNil(t, resp) require.NoError(t, err) require.EqualValues(t, decryptedValuesResp, resp) @@ -106,7 +105,7 @@ func TestDecryptService(t *testing.T) { decryptService, err := ProvideDecryptService(cfg, tracer, mockStorage) require.NoError(t, err) - resp, err := decryptService.Decrypt(ctx, "default", "secure-value-1", "secure-value-2") + resp, err := decryptService.Decrypt(ctx, "svc-name", "default", []string{"secure-value-1", "secure-value-2"}) require.NotNil(t, resp) require.NoError(t, err) require.EqualValues(t, decryptedValuesResp, resp) @@ -236,9 +235,8 @@ func TestDecryptService(t *testing.T) { t.Cleanup(func() { require.NoError(t, decryptService.Close()) }) svcIdentity := "provsysoning-test" - authCtx := identity.WithServiceIdentityContext(ctx, 1, identity.WithServiceIdentityName(svcIdentity)) - result, err := decryptService.Decrypt(authCtx, namespace, "secure-value-1") + result, err := decryptService.Decrypt(t.Context(), svcIdentity, namespace, []string{"secure-value-1"}) require.NoError(t, err) require.NotNil(t, result) require.Len(t, result, 1) diff --git a/pkg/registry/apis/secret/service/inline_secure_value_test.go b/pkg/registry/apis/secret/service/inline_secure_value_test.go index 3c8742bffb3..e20885b0cc3 100644 --- a/pkg/registry/apis/secret/service/inline_secure_value_test.go +++ b/pkg/registry/apis/secret/service/inline_secure_value_test.go @@ -254,9 +254,7 @@ func TestIntegration_InlineSecureValue_CreateInline(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, createdName) - decryptAuthCtx := testutils.CreateServiceAuthContext(t.Context(), serviceIdentity, owner.Namespace, []string{"secret.grafana.app/securevalues:decrypt"}) - - decryptedValues, err := tu.DecryptService.Decrypt(decryptAuthCtx, owner.Namespace, createdName) + decryptedValues, err := tu.DecryptService.Decrypt(t.Context(), serviceIdentity, owner.Namespace, []string{createdName}) require.NoError(t, err) decryptedResult, ok := decryptedValues[createdName] diff --git a/pkg/storage/secret/metadata/secure_value_test.go b/pkg/storage/secret/metadata/secure_value_test.go index ce1513d95cf..7f387847848 100644 --- a/pkg/storage/secret/metadata/secure_value_test.go +++ b/pkg/storage/secret/metadata/secure_value_test.go @@ -403,9 +403,8 @@ func TestStateMachine(t *testing.T) { }, "decrypt": func(t *rapid.T) { input := decryptGen.Draw(t, "decryptInput") - authCtx := testutils.CreateServiceAuthContext(t.Context(), input.decrypter, input.namespace, []string{fmt.Sprintf("secret.grafana.app/securevalues/%+v:decrypt", input.name)}) modelResult, modelErr := model.decrypt(input.decrypter, input.namespace, input.name) - result, err := sut.DecryptService.Decrypt(authCtx, input.namespace, input.name) + result, err := sut.DecryptService.Decrypt(t.Context(), input.decrypter, input.namespace, []string{input.name}) if err != nil || modelErr != nil { require.ErrorIs(t, err, modelErr) return @@ -440,8 +439,7 @@ func TestSecureValueServiceExampleBased(t *testing.T) { require.NoError(t, err) require.Equal(t, sv.Status.Version, deletedSv.Status.Version) - authCtx := testutils.CreateServiceAuthContext(t.Context(), sv.Spec.Decrypters[0], sv.Namespace, []string{fmt.Sprintf("secret.grafana.app/securevalues/%+v:decrypt", sv.Name)}) - result, err := sut.DecryptService.Decrypt(authCtx, sv.Namespace, sv.Name) + result, err := sut.DecryptService.Decrypt(t.Context(), sv.Spec.Decrypters[0], sv.Namespace, []string{sv.Name}) require.NoError(t, err) require.Equal(t, 1, len(result)) require.ErrorIs(t, result[sv.Name].Error(), contracts.ErrDecryptNotFound) From 6dc0dedc97213fa9a3cf9e7102bfda237c262b9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Farkas?= Date: Mon, 4 Aug 2025 09:57:41 +0200 Subject: [PATCH 47/89] datasources: querier: refactor (#108776) datasources: querier: refactor types --- pkg/registry/apis/query/client/supplier.go | 35 +++++++++++++++---- .../apis/query/clientapi/clientapi.go | 16 +++++---- pkg/registry/apis/query/query.go | 9 ++--- pkg/registry/apis/query/query_test.go | 17 +++++++-- pkg/registry/apis/query/register.go | 4 +-- .../mt_datasource_client_builder.go | 24 ++++++------- 6 files changed, 68 insertions(+), 37 deletions(-) diff --git a/pkg/registry/apis/query/client/supplier.go b/pkg/registry/apis/query/client/supplier.go index 08c462d466c..a870f74fed8 100644 --- a/pkg/registry/apis/query/client/supplier.go +++ b/pkg/registry/apis/query/client/supplier.go @@ -4,6 +4,7 @@ import ( "context" data "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1" + "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/registry/apis/query/clientapi" "github.com/grafana/grafana/pkg/services/accesscontrol" @@ -18,7 +19,17 @@ type singleTenantClientSupplier struct { cfg *setting.Cfg } -func NewSingleTenantClientSupplier(cfg *setting.Cfg, features featuremgmt.FeatureToggles, p plugins.Client, ctxProv *plugincontext.Provider, accessControl accesscontrol.AccessControl) clientapi.DataSourceClientSupplier { +type singleTenantInstance struct { + client clientapi.QueryDataClient + features featuremgmt.FeatureToggles + cfg *setting.Cfg +} + +func (t *singleTenantInstance) GetDataSourceClient(_ context.Context, _ data.DataSourceRef, _ map[string]string) (clientapi.QueryDataClient, error) { + return t.client, nil +} + +func NewSingleTenantClientSupplier(cfg *setting.Cfg, features featuremgmt.FeatureToggles, p plugins.Client, ctxProv *plugincontext.Provider, accessControl accesscontrol.AccessControl) clientapi.InstanceProvider { return &singleTenantClientSupplier{ cfg: cfg, features: features, @@ -26,19 +37,29 @@ func NewSingleTenantClientSupplier(cfg *setting.Cfg, features featuremgmt.Featur } } -func (s *singleTenantClientSupplier) GetDataSourceClient(_ context.Context, _ data.DataSourceRef, _ map[string]string, _ clientapi.InstanceConfigurationSettings) (clientapi.QueryDataClient, error) { +func (s *singleTenantClientSupplier) GetDataSourceClient(_ context.Context, _ data.DataSourceRef, _ map[string]string) (clientapi.QueryDataClient, error) { return s.client, nil } -func (s *singleTenantClientSupplier) GetInstanceConfigurationSettings(ctx context.Context) (clientapi.InstanceConfigurationSettings, error) { +func (s *singleTenantClientSupplier) GetInstance(_ context.Context) (clientapi.Instance, error) { + return &singleTenantInstance{ + client: s.client, + features: s.features, + cfg: s.cfg, + }, nil +} + +func (s *singleTenantInstance) GetSettings() clientapi.InstanceConfigurationSettings { return clientapi.InstanceConfigurationSettings{ - StackID: 0, FeatureToggles: s.features, - FullConfig: nil, - Options: nil, SQLExpressionCellLimit: s.cfg.SQLExpressionCellLimit, SQLExpressionOutputCellLimit: s.cfg.SQLExpressionOutputCellLimit, SQLExpressionTimeout: s.cfg.SQLExpressionTimeout, ExpressionsEnabled: s.cfg.ExpressionsEnabled, - }, nil + } +} + +func (s *singleTenantInstance) GetLogger(parent log.Logger) log.Logger { + // currently we do not add any extra info + return parent.New() } diff --git a/pkg/registry/apis/query/clientapi/clientapi.go b/pkg/registry/apis/query/clientapi/clientapi.go index 7e83565dbea..46f9167199b 100644 --- a/pkg/registry/apis/query/clientapi/clientapi.go +++ b/pkg/registry/apis/query/clientapi/clientapi.go @@ -7,6 +7,7 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" data "github.com/grafana/grafana-plugin-sdk-go/experimental/apis/data/v0alpha1" + "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/featuremgmt" ) @@ -20,19 +21,20 @@ type QueryDataClient interface { } type InstanceConfigurationSettings struct { - StackID uint32 FeatureToggles featuremgmt.FeatureToggles - FullConfig map[string]map[string]string // configuration file settings - Options map[string]string // additional settings related to an instance as set by grafana SQLExpressionCellLimit int64 SQLExpressionOutputCellLimit int64 SQLExpressionTimeout time.Duration ExpressionsEnabled bool } -type DataSourceClientSupplier interface { - // Get a client for a given datasource - GetDataSourceClient(ctx context.Context, ref data.DataSourceRef, headers map[string]string, instanceConfig InstanceConfigurationSettings) (QueryDataClient, error) +type Instance interface { + GetDataSourceClient(ctx context.Context, ref data.DataSourceRef, headers map[string]string) (QueryDataClient, error) // fetch information on the grafana instance (e.g. feature toggles) - GetInstanceConfigurationSettings(ctx context.Context) (InstanceConfigurationSettings, error) + GetSettings() InstanceConfigurationSettings + GetLogger(parent log.Logger) log.Logger +} + +type InstanceProvider interface { + GetInstance(ctx context.Context) (Instance, error) } diff --git a/pkg/registry/apis/query/query.go b/pkg/registry/apis/query/query.go index a70aa657765..89c94e2c3a9 100644 --- a/pkg/registry/apis/query/query.go +++ b/pkg/registry/apis/query/query.go @@ -246,20 +246,21 @@ func handleQuery(ctx context.Context, raw query.QueryDataRequest, b QueryAPIBuil headers := ExtractKnownHeaders(httpreq.Header) - instanceConfig, err := b.clientSupplier.GetInstanceConfigurationSettings(ctx) + instance, err := b.clientSupplier.GetInstance(ctx) if err != nil { connectLogger.Error("failed to get instance configuration settings", "err", err) responder.Error(err) return nil, err } - dsQuerierLoggerWithSlug := connectLogger.New("slug", instanceConfig.Options["slug"], "ruleuid", headers["X-Rule-Uid"]) + instanceConfig := instance.GetSettings() + + dsQuerierLoggerWithSlug := instance.GetLogger(connectLogger).New("ruleuid", headers["X-Rule-Uid"]) mtDsClientBuilder := mtdsclient.NewMtDatasourceClientBuilderWithClientSupplier( - b.clientSupplier, + instance, ctx, headers, - instanceConfig, dsQuerierLoggerWithSlug, ) diff --git a/pkg/registry/apis/query/query_test.go b/pkg/registry/apis/query/query_test.go index 530e3a5d6b6..3c4cefa3ec5 100644 --- a/pkg/registry/apis/query/query_test.go +++ b/pkg/registry/apis/query/query_test.go @@ -250,7 +250,18 @@ type mockClient struct { stubbedFrame *data.Frame } -func (m mockClient) GetDataSourceClient(ctx context.Context, ref dataapi.DataSourceRef, headers map[string]string, instanceConfig clientapi.InstanceConfigurationSettings) (clientapi.QueryDataClient, error) { +func (m mockClient) GetInstance(ctx context.Context) (clientapi.Instance, error) { + mclient := mockClient{ + stubbedFrame: m.stubbedFrame, + } + return mclient, nil +} + +func (m mockClient) GetLogger(parent log.Logger) log.Logger { + return parent.New() +} + +func (m mockClient) GetDataSourceClient(ctx context.Context, ref dataapi.DataSourceRef, headers map[string]string) (clientapi.QueryDataClient, error) { mclient := mockClient{ stubbedFrame: m.stubbedFrame, } @@ -281,11 +292,11 @@ func (m mockClient) CheckHealth(ctx context.Context, req *backend.CheckHealthReq return nil, nil } -func (m mockClient) GetInstanceConfigurationSettings(ctx context.Context) (clientapi.InstanceConfigurationSettings, error) { +func (m mockClient) GetSettings() clientapi.InstanceConfigurationSettings { return clientapi.InstanceConfigurationSettings{ ExpressionsEnabled: true, FeatureToggles: featuremgmt.WithFeatures(featuremgmt.FlagSqlExpressions), - }, nil + } } type mockLegacyDataSourceLookup struct{} diff --git a/pkg/registry/apis/query/register.go b/pkg/registry/apis/query/register.go index 1efd3efdb2a..ffae6d6fdbf 100644 --- a/pkg/registry/apis/query/register.go +++ b/pkg/registry/apis/query/register.go @@ -45,7 +45,7 @@ type QueryAPIBuilder struct { tracer tracing.Tracer metrics *metrics.ExprMetrics - clientSupplier clientapi.DataSourceClientSupplier + clientSupplier clientapi.InstanceProvider registry query.DataSourceApiServerRegistry converter *expr.ResultConverter queryTypes *query.QueryTypeDefinitionList @@ -54,7 +54,7 @@ type QueryAPIBuilder struct { func NewQueryAPIBuilder( features featuremgmt.FeatureToggles, - clientSupplier clientapi.DataSourceClientSupplier, + clientSupplier clientapi.InstanceProvider, ar authorizer.Authorizer, registry query.DataSourceApiServerRegistry, registerer prometheus.Registerer, diff --git a/pkg/services/mtdsclient/mt_datasource_client_builder.go b/pkg/services/mtdsclient/mt_datasource_client_builder.go index d5108aef4e2..5b7ea5c1823 100644 --- a/pkg/services/mtdsclient/mt_datasource_client_builder.go +++ b/pkg/services/mtdsclient/mt_datasource_client_builder.go @@ -24,22 +24,20 @@ func NewNullMTDatasourceClientBuilder() MTDatasourceClientBuilder { } type MtDatasourceClientBuilderWithClientSupplier struct { - clientSupplier clientapi.DataSourceClientSupplier - ctx context.Context - headers map[string]string - instanceConfig clientapi.InstanceConfigurationSettings - logger log.Logger + instance clientapi.Instance + ctx context.Context + headers map[string]string + logger log.Logger } func (b *MtDatasourceClientBuilderWithClientSupplier) BuildClient(pluginId string, uid string) (clientapi.QueryDataClient, bool) { - dsClient, err := b.clientSupplier.GetDataSourceClient( + dsClient, err := b.instance.GetDataSourceClient( b.ctx, v0alpha1.DataSourceRef{ Type: pluginId, UID: uid, }, b.headers, - b.instanceConfig, ) if err != nil { b.logger.Debug("failed to get mt ds client", "error", err) @@ -50,18 +48,16 @@ func (b *MtDatasourceClientBuilderWithClientSupplier) BuildClient(pluginId strin // TODO: I think we might be able to refactor this to just use the client supplier directly func NewMtDatasourceClientBuilderWithClientSupplier( - clientSupplier clientapi.DataSourceClientSupplier, + instance clientapi.Instance, ctx context.Context, headers map[string]string, - instanceConfig clientapi.InstanceConfigurationSettings, logger log.Logger, ) MTDatasourceClientBuilder { return &MtDatasourceClientBuilderWithClientSupplier{ - clientSupplier: clientSupplier, - ctx: ctx, - headers: headers, - instanceConfig: instanceConfig, - logger: logger, + instance: instance, + ctx: ctx, + headers: headers, + logger: logger, } } From 3e66819baccbcbd4fcfb7d825f106d837c84c188 Mon Sep 17 00:00:00 2001 From: Matheus Macabu Date: Mon, 4 Aug 2025 09:58:54 +0200 Subject: [PATCH 48/89] Air: Keep binary after exiting (#109103) --- .air.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.air.toml b/.air.toml index 87083f809aa..dd0faa01f23 100644 --- a/.air.toml +++ b/.air.toml @@ -7,7 +7,7 @@ exclude_unchanged = true follow_symlink = true include_dir = ["apps", "conf", "devenv/dev-dashboards", "pkg", "public/views"] include_ext = ["go", "ini", "toml", "html", "json"] -stop_on_error = true +stop_on_error = false send_interrupt = true kill_delay = 500 From b839bb7a8167fd5d300f27221cc68aa537c5c548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Farkas?= Date: Mon, 4 Aug 2025 11:00:59 +0200 Subject: [PATCH 49/89] datasources: querier: removed unused method (#109109) --- pkg/registry/apis/query/client/supplier.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/registry/apis/query/client/supplier.go b/pkg/registry/apis/query/client/supplier.go index a870f74fed8..646068a8d9d 100644 --- a/pkg/registry/apis/query/client/supplier.go +++ b/pkg/registry/apis/query/client/supplier.go @@ -37,10 +37,6 @@ func NewSingleTenantClientSupplier(cfg *setting.Cfg, features featuremgmt.Featur } } -func (s *singleTenantClientSupplier) GetDataSourceClient(_ context.Context, _ data.DataSourceRef, _ map[string]string) (clientapi.QueryDataClient, error) { - return s.client, nil -} - func (s *singleTenantClientSupplier) GetInstance(_ context.Context) (clientapi.Instance, error) { return &singleTenantInstance{ client: s.client, From f5e1e8e8e2a85a206c2435ec93915c93ecdb4693 Mon Sep 17 00:00:00 2001 From: Matheus Macabu Date: Mon, 4 Aug 2025 11:20:48 +0200 Subject: [PATCH 50/89] Secrets: Bump dependency with inline proto (#109106) --- apps/advisor/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/advisor/go.sum b/apps/advisor/go.sum index c6263714349..77f75837733 100644 --- a/apps/advisor/go.sum +++ b/apps/advisor/go.sum @@ -679,8 +679,8 @@ github.com/grafana/grafana/apps/folder v0.0.0-20250627191313-2f1a6ae1712b h1:31M github.com/grafana/grafana/apps/folder v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:dLtYBp1pza5HYalezNvzlP8JDeKrZ5BKTonDgEOE0NY= github.com/grafana/grafana/apps/provisioning v0.0.0-20250801193518-9f4773c9a5a3 h1:MUyJnJE3GFj9QqA0sq7VOqWQkywYvH0/T4kwJfVQzJE= github.com/grafana/grafana/apps/provisioning v0.0.0-20250801193518-9f4773c9a5a3/go.mod h1:qzFUVwLI1b5UIbVFxFydUYAsnOK27AgtA5so3EW8jM0= -github.com/grafana/grafana/apps/secret v0.0.0-20250731151929-0aac22a9e2d3 h1:16eaVEucbwis3TxS4CYZxxg5wfPAP/6u7Ji2+wbiHyk= -github.com/grafana/grafana/apps/secret v0.0.0-20250731151929-0aac22a9e2d3/go.mod h1:pS2M5ILsHx9VNTM96glLtCjCVXHWyfGcT34WHvbbMtM= +github.com/grafana/grafana/apps/secret v0.0.0-20250804062607-343fe4dadf51 h1:7Ye9dLxWESPVk4NmIbBvUF9IwFbPH1R+PvpuvpaIBu0= +github.com/grafana/grafana/apps/secret v0.0.0-20250804062607-343fe4dadf51/go.mod h1:pS2M5ILsHx9VNTM96glLtCjCVXHWyfGcT34WHvbbMtM= github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b h1:ei01IFqmnXkOrrVvsT3CYe+i5xYra3SCX7Wsu3PMsDU= github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:+H4Va9jDJlGQJjAN+OFD/hLx2I/yEzDRMQLaKecvgAc= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956 h1:FzReg7qT3G+11ZsFFbtguMdx+w1w76bJCOOH1fWfDKs= diff --git a/go.mod b/go.mod index 3ec9e8a1029..2fe993877e6 100644 --- a/go.mod +++ b/go.mod @@ -236,7 +236,7 @@ require ( github.com/grafana/grafana/apps/iam v0.0.0-20250627191313-2f1a6ae1712b // @grafana/identity-access-team github.com/grafana/grafana/apps/investigations v0.0.0-20250627191313-2f1a6ae1712b // @fcjack @matryer github.com/grafana/grafana/apps/playlist v0.0.0-20250627191313-2f1a6ae1712b // @grafana/grafana-app-platform-squad - github.com/grafana/grafana/apps/secret v0.0.0-20250731151929-0aac22a9e2d3 // @grafana/grafana-operator-experience-squad + github.com/grafana/grafana/apps/secret v0.0.0-20250804062607-343fe4dadf51 // @grafana/grafana-operator-experience-squad github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b // @grafana/grafana-app-platform-squad github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956 // @grafana/grafana-app-platform-squad github.com/grafana/grafana/pkg/apiserver v0.0.0-20250627191313-2f1a6ae1712b // @grafana/grafana-app-platform-squad diff --git a/go.sum b/go.sum index e6e246c13a2..067008b4b7d 100644 --- a/go.sum +++ b/go.sum @@ -1632,8 +1632,8 @@ github.com/grafana/grafana/apps/playlist v0.0.0-20250627191313-2f1a6ae1712b h1:e github.com/grafana/grafana/apps/playlist v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:fPtx6dwGm0PweQRVbgtthMapJMvXobBcORbndb7Dgd4= github.com/grafana/grafana/apps/provisioning v0.0.0-20250801193518-9f4773c9a5a3 h1:MUyJnJE3GFj9QqA0sq7VOqWQkywYvH0/T4kwJfVQzJE= github.com/grafana/grafana/apps/provisioning v0.0.0-20250801193518-9f4773c9a5a3/go.mod h1:qzFUVwLI1b5UIbVFxFydUYAsnOK27AgtA5so3EW8jM0= -github.com/grafana/grafana/apps/secret v0.0.0-20250731151929-0aac22a9e2d3 h1:16eaVEucbwis3TxS4CYZxxg5wfPAP/6u7Ji2+wbiHyk= -github.com/grafana/grafana/apps/secret v0.0.0-20250731151929-0aac22a9e2d3/go.mod h1:pS2M5ILsHx9VNTM96glLtCjCVXHWyfGcT34WHvbbMtM= +github.com/grafana/grafana/apps/secret v0.0.0-20250804062607-343fe4dadf51 h1:7Ye9dLxWESPVk4NmIbBvUF9IwFbPH1R+PvpuvpaIBu0= +github.com/grafana/grafana/apps/secret v0.0.0-20250804062607-343fe4dadf51/go.mod h1:pS2M5ILsHx9VNTM96glLtCjCVXHWyfGcT34WHvbbMtM= github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b h1:ei01IFqmnXkOrrVvsT3CYe+i5xYra3SCX7Wsu3PMsDU= github.com/grafana/grafana/pkg/aggregator v0.0.0-20250627191313-2f1a6ae1712b/go.mod h1:+H4Va9jDJlGQJjAN+OFD/hLx2I/yEzDRMQLaKecvgAc= github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250801162753-7e4796893956 h1:FzReg7qT3G+11ZsFFbtguMdx+w1w76bJCOOH1fWfDKs= From 0a108e9c68597f47f22b3fa8e61373c2ab3d7c3d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:05:14 +0100 Subject: [PATCH 51/89] Update dependency eslint-config-prettier to v10 (#109064) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 7626f9f04b1..e039d16d6a9 100644 --- a/package.json +++ b/package.json @@ -186,7 +186,7 @@ "esbuild-loader": "4.3.0", "esbuild-plugin-browserslist": "^1.0.0", "eslint": "9.32.0", - "eslint-config-prettier": "9.1.0", + "eslint-config-prettier": "10.1.8", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "28.11.0", "eslint-plugin-jest-dom": "^5.4.0", diff --git a/yarn.lock b/yarn.lock index 69123b8140e..023528f1dd0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16084,14 +16084,14 @@ __metadata: languageName: node linkType: hard -"eslint-config-prettier@npm:9.1.0": - version: 9.1.0 - resolution: "eslint-config-prettier@npm:9.1.0" +"eslint-config-prettier@npm:10.1.8": + version: 10.1.8 + resolution: "eslint-config-prettier@npm:10.1.8" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: bin/cli.js - checksum: 10/411e3b3b1c7aa04e3e0f20d561271b3b909014956c4dba51c878bf1a23dbb8c800a3be235c46c4732c70827276e540b6eed4636d9b09b444fd0a8e07f0fcd830 + checksum: 10/03f8e6ea1a6a9b8f9eeaf7c8c52a96499ec4b275b9ded33331a6cc738ed1d56de734097dbd0091f136f0e84bc197388bd8ec22a52a4658105883f8c8b7d8921a languageName: node linkType: hard @@ -18355,7 +18355,7 @@ __metadata: esbuild-loader: "npm:4.3.0" esbuild-plugin-browserslist: "npm:^1.0.0" eslint: "npm:9.32.0" - eslint-config-prettier: "npm:9.1.0" + eslint-config-prettier: "npm:10.1.8" eslint-plugin-import: "npm:^2.31.0" eslint-plugin-jest: "npm:28.11.0" eslint-plugin-jest-dom: "npm:^5.4.0" From 3a1c1b623269aa8e3c4d34e050532129ae6f8d49 Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Mon, 4 Aug 2025 11:20:12 +0100 Subject: [PATCH 52/89] Devenv: Replace testdata UIDs with gdev-testdata (#108997) * Prettier format the devenv folder * Consistently use type-only dsref for testdata in devenv dashboards --- .prettierignore | 5 +- devenv/README.md | 19 +- devenv/datasources.yaml | 92 +- .../panel_tests_graph_time_regions.json | 20 +- .../panel_tests_polystat.json | 132 +- devenv/dev-dashboards/all-panels.json | 1880 +++--- .../annotations/annotation-filtering.json | 38 +- .../elasticsearch_complex.json | 40 +- .../elasticsearch_migration.json | 58 +- .../elasticsearch_simple.json | 26 +- .../datasource-loki/loki_fakedata.json | 14 +- .../datasource-loki/loki_query_splitting.json | 34 +- .../datasource-testdata/demo1.json | 126 +- .../new_features_in_v74.json | 138 +- .../new_features_in_v8.json | 133 +- .../e2e-repeats/Repeating-Kitchen-Sink.json | 32 +- .../Repeating-a-panel-horizontally.json | 18 +- .../Repeating-a-panel-vertically.json | 18 +- ...row-with-a-repeating-horizontal-panel.json | 26 +- ...a-row-with-a-repeating-vertical-panel.json | 26 +- .../e2e-repeats/Repeating-an-empty-row.json | 24 +- .../extensions/link-onclick-extensions.json | 26 +- .../extensions/link-path-extensions.json | 456 +- .../feature-templating/datadata-macros.json | 1684 +++-- .../templating-repeating-panels.json | 36 +- .../templating-repeating-rows.json | 34 +- .../testdata-nested-variables-drilldown.json | 16 +- .../testdata-nested-variables.json | 20 +- ...-variables-that-update-on-time-change.json | 8 +- devenv/dev-dashboards/home.json | 73 +- .../live/live-flakey-refresh.json | 695 +- devenv/dev-dashboards/live/live-flakey.json | 695 +- devenv/dev-dashboards/live/live-publish.json | 869 ++- devenv/dev-dashboards/live/live-streams.json | 1513 +++-- .../dev-dashboards/migrations/migrations.json | 159 +- .../panel-barchart/barchart-autosizing.json | 43 +- .../barchart-label-rotation-skipping.json | 592 +- .../barchart-series-toggle.json | 33 +- .../barchart-thresholds-mappings.json | 96 +- .../barchart-tooltips-legends.json | 63 +- .../panel-bargauge/bar_gauge_demo.json | 24 +- .../panel-bargauge/panel_tests_bar_gauge.json | 296 +- .../panel-candlestick/candlestick.json | 24 +- .../canvas-connection-examples.json | 28 +- .../panel-canvas/canvas-datalinks.json | 5693 +++++++---------- .../panel-canvas/canvas-examples.json | 50 +- .../panel-common/color_modes.json | 8 +- .../panel-common/lazy_loading.json | 96 +- .../panel-common/linked-viz.json | 72 +- .../panel-common/shared_queries.json | 47 +- .../panel-dashlist/dashlist.json | 3 +- .../datagrid_metric_values.json | 12 +- .../panel_tests_flame_graph.json | 12 +- .../panel-gauge/gauge-multi-series.json | 12 +- .../panel-gauge/gauge_tests.json | 60 +- .../panel-geomap/geomap-color-field.json | 25 +- .../panel-geomap/geomap-photo-layer.json | 7 +- .../panel-geomap/geomap-route-layer.json | 8 +- ...geomap-spatial-operations-transformer.json | 13 +- .../panel-geomap/geomap-v91.json | 27 +- .../panel-geomap/geomap_multi-layers.json | 10 +- .../panel-geomap/panel-geomap.json | 26 +- .../panel-graph/graph-shared-tooltips.json | 6 +- .../panel-graph/graph-time-regions.json | 20 +- .../panel-graph/graph_tests.json | 60 +- .../panel-heatmap/heatmap-calculate-log.json | 13 +- .../panel-heatmap/heatmap-legacy.json | 41 +- .../panel-heatmap/heatmap-x.json | 627 +- .../panel-histogram/histogram_tests.json | 126 +- .../panel-piechart/panel_test_piechart.json | 72 +- .../panel-polystat/polystat_test.json | 146 +- .../panel-stat/panel-stat-tests.json | 314 +- .../panel-table/table_kitchen_sink.json | 26 +- .../panel-table/table_markdown.json | 4 +- .../panel-table/table_pagination.json | 5324 ++++++++------- .../panel-table/table_sparkline_cell.json | 67 +- .../panel-table/table_tests.json | 26 +- .../panel-table/table_tests_new.json | 106 +- .../panel-text/text-options.json | 75 +- .../timeline-align-endtime.json | 35 +- .../timeline-align-nulls-retain.json | 15 +- .../panel-timeline/timeline-demo.json | 15 +- .../panel-timeline/timeline-modes.json | 89 +- .../timeline-thresholds-mappings.json | 67 +- .../timeseries-bars-high-density.json | 1178 ++-- .../timeseries-by-value-color-schemes.json | 45 +- .../panel-timeseries/timeseries-formats.json | 289 +- .../panel-timeseries/timeseries-nulls.json | 123 +- .../timeseries-out-of-rage.json | 998 ++- ...series-shared-tooltip-cursor-position.json | 6 +- .../panel-timeseries/timeseries-stacking.json | 6 +- .../timeseries-stacking2.json | 287 +- .../timeseries-thresholds.json | 6 +- .../timeseries-y-ticks-zero-decimals.json | 1661 +++-- .../timeseries-yaxis-ticks.json | 122 +- .../panel-timeseries/timeseries.json | 20 +- .../panel-trend/trend_example.json | 16 +- .../panel-xychart/xychart-demo.json | 106 +- .../panel-xychart/xychart-migrations.json | 491 +- .../xychart-tooltip-color-test.json | 27 +- .../scenarios/relative_time_zone_support.json | 20 +- .../slow_queries_and_annotations.json | 52 +- .../scenarios/time_zone_support.json | 24 +- .../transforms/config-from-query.json | 70 +- .../transforms/extract-json-paths.json | 39 +- devenv/dev-dashboards/transforms/filter.json | 316 +- .../transforms/join-by-field.json | 46 +- .../transforms/join-by-labels.json | 41 +- .../transforms/regression-analysis.json | 56 +- devenv/dev-dashboards/transforms/reuse.json | 1051 ++- .../transforms/rows-to-fields.json | 1197 ++-- devenv/docker/blocks/auth/authentik/README.md | 5 +- devenv/docker/blocks/auth/jwt_proxy/jwks.json | 18 +- devenv/docker/blocks/auth/jwt_proxy/readme.md | 24 +- devenv/docker/blocks/auth/oauth/jwks.json | 18 +- devenv/docker/blocks/auth/oauth/readme.md | 14 +- .../blocks/auth/openldap-multiple/README.md | 3 +- devenv/docker/blocks/auth/openldap/README.md | 6 +- .../prometheus_oauth2_proxy_azure/README.md | 7 +- devenv/docker/blocks/caddy_tls/README.md | 8 +- devenv/docker/blocks/collectd/README.md | 6 +- devenv/docker/blocks/loki-promtail/README.md | 3 +- devenv/docker/blocks/maildev/README.md | 2 +- devenv/docker/blocks/mqtt/README.md | 8 +- devenv/docker/blocks/mssql_arm64/README.md | 9 +- .../blocks/self-instrumentation/readme.md | 2 +- devenv/docker/blocks/sensugo/notes.md | 2 - devenv/docker/blocks/tempo/README.md | 2 + .../docker/ha-test-unified-alerting/README.md | 7 +- .../dashboards/alerts/overview.json | 15 +- .../dashboards/mysql/overview.json | 1416 +--- devenv/docker/ha_test/README.md | 1 + .../dashboards/alerts/overview.json | 15 +- .../dashboards/mysql/overview.json | 1416 +--- devenv/docker/loadtest/README.md | 1 - devenv/frontend-service/README.md | 16 +- 136 files changed, 15292 insertions(+), 19862 deletions(-) diff --git a/.prettierignore b/.prettierignore index 8fd0b837b78..e5b7bd9ca75 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,7 +5,6 @@ build compiled data deployment_tools_config.json -devenv dist e2e/tmp node_modules @@ -40,3 +39,7 @@ public/mockServiceWorker.js /.nx/cache /.nx/workspace-data + +# Playwright results +test-results +playwright-report \ No newline at end of file diff --git a/devenv/README.md b/devenv/README.md index cc37e031d0a..72c218037b9 100644 --- a/devenv/README.md +++ b/devenv/README.md @@ -14,53 +14,57 @@ Grafana uses [Docker](https://docker.com) to make the task of setting up databas ## Developer dashboards and data sources To setup developer dashboards and data sources + ```bash ./setup.sh ``` To remove the setup developer dashboards and data sources + ```bash ./setup.sh undev ``` After restarting the Grafana server, there should be a number of data sources named `gdev-` provisioned as well as -a dashboard folder named `gdev dashboards`. This folder contains dashboard and panel features tests dashboards. +a dashboard folder named `gdev dashboards`. This folder contains dashboard and panel features tests dashboards. Please update these dashboards or make new ones as new panels and dashboards features are developed or new bugs are -found. The dashboards are located in the `devenv/dev-dashboards` folder. +found. The dashboards are located in the `devenv/dev-dashboards` folder. ## docker-compose with databases This command creates a docker-compose file with specified databases configured and ready to run. Each database has a prepared image with some fake data ready to use. For available databases, see `docker/blocks` directory. Notice that -for some databases there are multiple images with different versions. Some blocks such as `slow_proxy_mac` or `apache_proxy_mac` are specifically for Macs. +for some databases there are multiple images with different versions. Some blocks such as `slow_proxy_mac` or `apache_proxy_mac` are specifically for Macs. ```bash make devenv sources=influxdb,prometheus,elastic5 ``` -Some of the blocks support dynamic change of the image version used in the Docker file. The signature looks like this: +Some of the blocks support dynamic change of the image version used in the Docker file. The signature looks like this: ```bash make devenv sources=postgres,auth/openldap,grafana postgres_version=9.2 grafana_version=6.7.0-beta1 ``` - ### Notes per block #### Grafana + The grafana block is pre-configured with the dev-datasources and dashboards. #### Tempo + The tempo block runs loki and prometheus as well and should not be ran with prometheus as a separate source. You need to install a docker plugin for the self logging to work, without it the container won't start. See https://grafana.com/docs/loki/latest/clients/docker-driver/#installing for installation instructions. #### Jaeger + Jaeger block runs both Jaeger and Loki container. Loki container sends traces to Jaeger and also logs its own logs into itself so it is possible to setup derived field for traceID from Loki to Jaeger. You need to install a docker plugin for the self logging to work, without it the container won't start. See https://grafana.com/docs/loki/latest/clients/docker-driver/#installing for installation instructions. #### Graphite | version | source name | graphite-web port | plaintext port | pickle port | -|---------|-------------|-------------------|----------------|-------------| +| ------- | ----------- | ----------------- | -------------- | ----------- | | 1.1 | graphite | 8180 | 2103 | 2103 | | 1.0 | graphite1 | 8280 | 2203 | 2203 | | 0.9 | graphite09 | 8380 | 2303 | 2303 | @@ -81,7 +85,8 @@ host = "localhost:1025" You can access the web UI at http://localhost:12080/#/ ## Debugging setup in VS Code -An example of launch.json is provided in `.vscode/launch.json`. It basically does what Makefile and .bra.toml do. The 'program' field is set to the folder name so VS Code loads all *.go files in it instead of just main.go. + +An example of launch.json is provided in `.vscode/launch.json`. It basically does what Makefile and .bra.toml do. The 'program' field is set to the folder name so VS Code loads all \*.go files in it instead of just main.go. ## Troubleshooting diff --git a/devenv/datasources.yaml b/devenv/datasources.yaml index 8eaad77a2fb..346cd22e02d 100644 --- a/devenv/datasources.yaml +++ b/devenv/datasources.yaml @@ -27,21 +27,21 @@ datasources: access: proxy url: http://localhost:8180 jsonData: - graphiteVersion: "1.1" + graphiteVersion: '1.1' - name: gdev-graphite-1.0 type: graphite access: proxy url: http://localhost:8280 jsonData: - graphiteVersion: "1.0" + graphiteVersion: '1.0' - name: gdev-graphite-0.9 type: graphite access: proxy url: http://localhost:8380 jsonData: - graphiteVersion: "0.9" + graphiteVersion: '0.9' - name: gdev-alertmanager type: alertmanager @@ -64,8 +64,8 @@ datasources: prometheusType: Prometheus #Cortex | Mimir | Prometheus | Thanos prometheusVersion: 2.40.0 exemplarTraceIdDestinations: - - name: traceID - datasourceUid: gdev-tempo + - name: traceID + datasourceUid: gdev-tempo secureJsonData: basicAuthPassword: admin #https://grafana.com/docs/grafana/latest/administration/provisioning/#using-environment-variables @@ -84,6 +84,7 @@ datasources: basicAuthPassword: admin #https://grafana.com/docs/grafana/latest/administration/provisioning/#using-environment-variables - name: gdev-testdata + uid: PD8C576611E62080A isDefault: true type: testdata @@ -116,9 +117,9 @@ datasources: url: http://localhost:8086 jsonData: dbName: mybucket - httpHeaderName1: "Authorization" + httpHeaderName1: 'Authorization' secureJsonData: - httpHeaderValue1: "Token mytoken" + httpHeaderValue1: 'Token mytoken' - name: gdev-opentsdb type: opentsdb @@ -150,9 +151,9 @@ datasources: access: proxy url: http://localhost:9200 jsonData: - index: "[logs-]YYYY.MM.DD" + index: '[logs-]YYYY.MM.DD' interval: Daily - timeField: "@timestamp" + timeField: '@timestamp' logLevelField: level logMessageField: line @@ -161,10 +162,10 @@ datasources: access: proxy url: http://localhost:9200 jsonData: - index: "[filebeat-]YYYY.MM.DD" + index: '[filebeat-]YYYY.MM.DD' interval: Daily - timeField: "@timestamp" - timeInterval: "10s" + timeField: '@timestamp' + timeInterval: '10s' logMessageField: message logLevelField: fields.level @@ -173,10 +174,10 @@ datasources: access: proxy url: http://localhost:9200 jsonData: - index: "[metricbeat-]YYYY.MM.DD" + index: '[metricbeat-]YYYY.MM.DD' interval: Daily - timeField: "@timestamp" - timeInterval: "10s" + timeField: '@timestamp' + timeInterval: '10s' - name: gdev-mysql type: mysql @@ -211,7 +212,7 @@ datasources: user: grafana jsonData: database: grafana - encrypt: "true" + encrypt: 'true' tlsSkipVerify: true secureJsonData: password: Password! @@ -232,7 +233,7 @@ datasources: secureJsonData: password: password jsonData: - sslmode: "disable" + sslmode: 'disable' database: grafana - name: gdev-postgres-ds-tests @@ -242,7 +243,7 @@ datasources: secureJsonData: password: grafanatest jsonData: - sslmode: "disable" + sslmode: 'disable' database: grafanadstest - name: gdev-cloudwatch @@ -252,7 +253,7 @@ datasources: jsonData: authType: credentials defaultRegion: eu-west-2 - customMetricsNamespaces: "CWAgent" + customMetricsNamespaces: 'CWAgent' - name: gdev-loki uid: gdev-loki @@ -262,36 +263,36 @@ datasources: editable: false correlations: - targetUID: gdev-jaeger - label: "Jaeger traces" - description: "Related traces stored in Jaeger" + label: 'Jaeger traces' + description: 'Related traces stored in Jaeger' - targetUID: gdev-zipkin - label: "Zipkin traces" - description: "Related traces stored in Zipkin" + label: 'Zipkin traces' + description: 'Related traces stored in Zipkin' - targetUID: gdev-tempo - label: "Tempo traces" - description: "Related traces stored in Tempo" + label: 'Tempo traces' + description: 'Related traces stored in Tempo' - targetUID: gdev-prometheus - label: "Logs to metrics" - description: "Related metrics stored in Prometheus" + label: 'Logs to metrics' + description: 'Related metrics stored in Prometheus' config: type: query target: - expr: "{ job=\"test\" }" - field: "traceID" + expr: '{ job="test" }' + field: 'traceID' jsonData: manageAlerts: false derivedFields: - - name: "traceID" + - name: 'traceID' matcherRegex: "traceID=(\\w+)" - url: "$${__value.raw}" + url: '$${__value.raw}' datasourceUid: gdev-jaeger - - name: "traceID" + - name: 'traceID' matcherRegex: "traceID=(\\w+)" - url: "$${__value.raw}" + url: '$${__value.raw}' datasourceUid: gdev-zipkin - - name: "traceID" + - name: 'traceID' matcherRegex: "traceID=(\\w+)" - url: "$${__value.raw}" + url: '$${__value.raw}' datasourceUid: gdev-tempo - name: gdev-jaeger @@ -316,23 +317,23 @@ datasources: editable: false correlations: - targetUID: gdev-loki - label: "Logs (correlation)" - description: "Correlation to logs stored in Loki" + label: 'Logs (correlation)' + description: 'Correlation to logs stored in Loki' config: type: query target: - expr: "{ job=\"job\" }" - field: "traceID" + expr: '{ job="job" }' + field: 'traceID' jsonData: tracesToLogsV2: - datasourceUid: gdev-loki - spanStartTimeShift: '5m' - spanEndTimeShift: '-5m' - customQuery: true - query: '{filename="/var/log/grafana/grafana.log"} |="$${__span.traceId}"' + datasourceUid: gdev-loki + spanStartTimeShift: '5m' + spanEndTimeShift: '-5m' + customQuery: true + query: '{filename="/var/log/grafana/grafana.log"} |="$${__span.traceId}"' tracesToProfiles: datasourceUid: gdev-pyroscope - profileTypeId: "process_cpu:cpu:nanoseconds:cpu:nanoseconds" + profileTypeId: 'process_cpu:cpu:nanoseconds:cpu:nanoseconds' tracesToMetrics: datasourceUid: gdev-prometheus spanStartTimeShift: '1h' @@ -352,7 +353,6 @@ datasources: url: http://localhost:4040 editable: false - - name: gdev-e2etestdatasource type: grafana-e2etest-datasource uid: gdev-e2etest-datasource diff --git a/devenv/dev-dashboards-without-uid/panel_tests_graph_time_regions.json b/devenv/dev-dashboards-without-uid/panel_tests_graph_time_regions.json index 98d49958aaf..9f2fce99582 100644 --- a/devenv/dev-dashboards-without-uid/panel_tests_graph_time_regions.json +++ b/devenv/dev-dashboards-without-uid/panel_tests_graph_time_regions.json @@ -467,10 +467,7 @@ ], "refresh": false, "schemaVersion": 16, - "tags": [ - "gdev", - "panel-tests" - ], + "tags": ["gdev", "panel-tests"], "templating": { "list": [] }, @@ -479,20 +476,9 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "browser", "title": "Panel Tests - Graph (Time Regions)", "version": 1 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards-without-uid/panel_tests_polystat.json b/devenv/dev-dashboards-without-uid/panel_tests_polystat.json index 25b1f7154e5..d70f9ee68cc 100644 --- a/devenv/dev-dashboards-without-uid/panel_tests_polystat.json +++ b/devenv/dev-dashboards-without-uid/panel_tests_polystat.json @@ -43,48 +43,8 @@ } ], "fontSizes": [ - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 22, - 24, - 26, - 28, - 30, - 32, - 34, - 36, - 38, - 40, - 42, - 44, - 46, - 48, - 50, - 52, - 54, - 56, - 58, - 60, - 62, - 64, - 66, - 68, - 70 + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, + 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70 ], "fontTypes": [ "Open Sans", @@ -1201,48 +1161,8 @@ } ], "fontSizes": [ - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 22, - 24, - 26, - 28, - 30, - 32, - 34, - 36, - 38, - 40, - 42, - 44, - 46, - 48, - 50, - 52, - 54, - 56, - 58, - 60, - 62, - 64, - 66, - 68, - 70 + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, + 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70 ], "fontTypes": [ "Open Sans", @@ -2324,48 +2244,8 @@ } ], "fontSizes": [ - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 22, - 24, - 26, - 28, - 30, - 32, - 34, - 36, - 38, - 40, - 42, - 44, - 46, - 48, - 50, - 52, - 54, - 56, - 58, - 60, - 62, - 64, - 66, - 68, - 70 + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, + 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70 ], "fontTypes": [ "Open Sans", diff --git a/devenv/dev-dashboards/all-panels.json b/devenv/dev-dashboards/all-panels.json index c6d93b191fc..873691e4c8d 100644 --- a/devenv/dev-dashboards/all-panels.json +++ b/devenv/dev-dashboards/all-panels.json @@ -1,981 +1,967 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, + "annotations": { + "list": [ + { + "builtIn": 1, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], "type": "dashboard" - } - ] - }, - "editable": true, - "graphTooltip": 0, - "iteration": 1629464729438, - "links": [ - { - "asDropdown": true, - "icon": "external link", - "includeVars": false, - "keepTime": false, - "tags": [ - "gdev", - "panel-tests" - ], - "targetBlank": false, - "title": "Dropdown link", - "tooltip": "", - "type": "dashboards", - "url": "" - }, - { - "asDropdown": false, - "icon": "external link", - "includeVars": false, - "keepTime": false, - "tags": [], - "targetBlank": false, - "title": "External link", - "tooltip": "localhost", - "type": "link", - "url": "localhost:3000" + }, + "type": "dashboard" } - ], - "panels": [ - { - "gridPos": { - "h": 3, - "w": 12, - "x": 0, - "y": 0 - }, - "id": 34, - "options": { - "content": "# All panels\n\nThis dashboard was created to quickly check accessiblity issues on a lot of panels at the same time ", - "mode": "markdown" - }, - "pluginVersion": "8.1.0-pre", - "transparent": true, - "type": "text" + ] + }, + "editable": true, + "graphTooltip": 0, + "iteration": 1629464729438, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": false, + "keepTime": false, + "tags": ["gdev", "panel-tests"], + "targetBlank": false, + "title": "Dropdown link", + "tooltip": "", + "type": "dashboards", + "url": "" + }, + { + "asDropdown": false, + "icon": "external link", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "External link", + "tooltip": "localhost", + "type": "link", + "url": "localhost:3000" + } + ], + "panels": [ + { + "gridPos": { + "h": 3, + "w": 12, + "x": 0, + "y": 0 }, - { - "gridPos": { - "h": 3, - "w": 12, - "x": 12, - "y": 0 - }, - "id": 35, - "options": { - "content": "# Another text panel\n\nBecause why not", - "mode": "markdown" - }, - "pluginVersion": "8.1.0-pre", - "transparent": true, - "type": "text" + "id": 34, + "options": { + "content": "# All panels\n\nThis dashboard was created to quickly check accessiblity issues on a lot of panels at the same time ", + "mode": "markdown" }, - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 3 - }, - "id": 32, - "panels": [], - "title": "Row title", - "type": "row" + "pluginVersion": "8.1.0-pre", + "transparent": true, + "type": "text" + }, + { + "gridPos": { + "h": 3, + "w": 12, + "x": 12, + "y": 0 }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "fillOpacity": 70, - "lineWidth": 1 - }, - "mappings": [ - { - "options": { - "CRITICAL": { - "color": "red", - "index": 3 - }, - "HIGH": { - "color": "orange", - "index": 2 - }, - "LOW": { - "color": "blue", - "index": 0 - }, - "NORMAL": { - "color": "green", - "index": 1 - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 4 - }, - "id": 41, - "options": { - "alignValue": "left", - "legend": { - "displayMode": "list", - "placement": "bottom" - }, - "mergeValues": true, - "rowHeight": 0.99, - "showValue": "auto", - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "LOW,HIGH,NORMAL,NORMAL,NORMAL,LOW,LOW,NORMAL,HIGH,CRITICAL" - }, - { - "refId": "B", - "scenarioId": "csv_metric_values", - "stringInput": "NORMAL,LOW,LOW,CRITICAL,CRITICAL,LOW,LOW,NORMAL,HIGH,CRITICAL" - }, - { - "refId": "C", - "scenarioId": "csv_metric_values", - "stringInput": "NORMAL,NORMAL,NORMAL,NORMAL,CRITICAL,LOW,NORMAL,NORMAL,NORMAL,LOW" - } - ], - "title": "State timeline", - "type": "state-timeline" + "id": 35, + "options": { + "content": "# Another text panel\n\nBecause why not", + "mode": "markdown" }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "continuous-GrYlRd" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } + "pluginVersion": "8.1.0-pre", + "transparent": true, + "type": "text" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": 32, + "panels": [], + "title": "Row title", + "type": "row" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" }, - "overrides": [] - }, - "gridPos": { - "h": 11, - "w": 9, - "x": 0, - "y": 0 - }, - "id": 62, - "options": { - "basemap": { - "config": {}, - "type": "default" + "custom": { + "fillOpacity": 70, + "lineWidth": 1 }, - "controls": { - "mouseWheelZoom": true, - "showAttribution": true, - "showDebug": false, - "showScale": false, - "showZoom": true - }, - "layers": [ + "mappings": [ { - "config": { - "color": { - "field": "Price", - "fixed": "dark-green" + "options": { + "CRITICAL": { + "color": "red", + "index": 3 }, - "fillOpacity": 0.4, - "shape": "circle", - "showLegend": true, - "size": { - "field": "Count", - "fixed": 5, - "max": 15, - "min": 2 + "HIGH": { + "color": "orange", + "index": 2 + }, + "LOW": { + "color": "blue", + "index": 0 + }, + "NORMAL": { + "color": "green", + "index": 1 } }, - "location": { - "gazetteer": "public/gazetteer/usa-states.json", - "lookup": "State", - "mode": "auto" - }, - "type": "markers" + "type": "value" } ], - "view": { - "id": "coords", - "lat": 38.297683, - "lon": -99.228359, - "shared": true, - "zoom": 3.98 - } - }, - "targets": [ - { - "csvFileName": "flight_info_by_state.csv", - "refId": "A", - "scenarioId": "csv_file" - } - ], - "title": "Size, color mapped to different fields + share view", - "type": "geomap" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "fillOpacity": 80, - "gradientMode": "hue", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineWidth": 1 - }, - "links": [ + "thresholds": { + "mode": "absolute", + "steps": [ { - "title": "Data link", - "url": "/" + "color": "green" + }, + { + "color": "red", + "value": 80 } - ], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 13 - }, - "id": 4, - "options": { - "bucketOffset": 0, - "combine": false, - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" + ] } }, - "title": "Histogram", - "type": "histogram" + "overrides": [] }, - { - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 21 - }, - "id": 28, - "options": { - "dedupStrategy": "none", - "enableLogDetails": true, - "prettifyLogMessage": false, - "showCommonLabels": false, - "showLabels": false, - "showTime": false, - "sortOrder": "Descending", - "wrapLogMessage": false - }, - "targets": [ - { - "refId": "A", - "scenarioId": "logs" - } - ], - "title": "Logs", - "type": "logs" + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 4 }, - { - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 21 - }, - "id": 8, - "options": { - "maxItems": 10, - "query": "", - "showHeadings": true, - "showRecentlyViewed": true, - "showSearch": true, - "showStarred": true, - "tags": [] - }, - "pluginVersion": "8.1.0-pre", - "title": "Dashboard list", - "type": "dashlist" - }, - { - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 29 - }, - "id": 6, - "options": { - "alertName": "", - "dashboardAlerts": false, - "maxItems": 20, - "showInstances": false, - "sortOrder": 1, - "stateFilter": { - "firing": true, - "inactive": false, - "pending": true - } - }, - "title": "Alert list", - "type": "alertlist" - }, - { - "cards": { - }, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateOranges", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "timeseries", - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 37 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 26, + "id": 41, + "options": { + "alignValue": "left", "legend": { - "show": false + "displayMode": "list", + "placement": "bottom" }, - "reverseYBuckets": false, - "targets": [ - { - "refId": "A", - "scenarioId": "exponential_heatmap_bucket_data" - } - ], - "title": "Heatmap", + "mergeValues": true, + "rowHeight": 0.99, + "showValue": "auto", "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" + "mode": "single", + "sort": "none" + } }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 37 - }, - "id": 20, - "options": { - "displayMode": "gradient", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showUnfilled": true, - "text": {} - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "refId": "A", - "scenarioId": "random_walk", - "seriesCount": 10 - } - ], - "title": "Bar gauge", - "type": "bargauge" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - } - }, - "mappings": [] - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 45 - }, - "id": 24, - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" - }, - "pieType": "pie", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "refId": "A", - "scenarioId": "random_walk", - "seriesCount": 6 - } - ], - "title": "Pie chart", - "type": "piechart" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 45 - }, - "id": 18, - "options": { - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "orientation": "auto", - "showValue": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true, - "text": {} - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "refId": "A", - "scenarioId": "random_walk", - "seriesCount": 3 - } - ], - "title": "Gauge", - "type": "gauge" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 53 - }, - "id": 22, - "options": { - "showHeader": true - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "refId": "A", - "scenarioId": "table_static" - } - ], - "title": "Tabel", - "type": "table" - }, - { - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 53 - }, - "id": 10, - "options": { - "limit": 10, - "navigateAfter": "10m", - "navigateBefore": "10m", - "onlyFromThisDashboard": false, - "onlyInTimeRange": false, - "showTags": true, - "showTime": true, - "showUser": true - }, - "title": "Annotation list", - "type": "annolist" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 61 - }, - "id": 16, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": {}, - "textMode": "auto" - }, - "pluginVersion": "8.1.0-pre", - "title": "Stat", - "type": "stat" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 61 - }, - "id": 2, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "refId": "A", - "scenarioId": "random_walk", - "seriesCount": 4, - "spread": 120 - } - ], - "title": "Graph NG", - "type": "timeseries" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "fillOpacity": 80, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineWidth": 1 - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 69 - }, - "id": 14, - "options": { - "barWidth": 0.97, - "groupWidth": 0.7, - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" - }, - "orientation": "auto", - "showValue": "auto", - "stacking": "none", - "text": {}, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "csvContent": "Series, Value\nBar 2, 20\nBar 3, 25\nBar 3, 55.4", - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "Bar chart", - "type": "barchart" - }, - { - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 77 - }, - "id": 12, - "options": { - "showImage": true - }, - "title": "News panel", - "type": "news" - } - ], - "refresh": "", - "schemaVersion": 36, - "tags": [ - "gdev", - "panel-tests", - "all-panels" - ], - "templating": { - "list": [ + "targets": [ { - "current": {}, - "datasource": "gdev-testdata", - "definition": "*", - "hide": 0, - "includeAll": true, - "multi": true, - "name": "query0", - "options": [], - "query": { - "query": "*", - "refId": "StandardVariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "LOW,HIGH,NORMAL,NORMAL,NORMAL,LOW,LOW,NORMAL,HIGH,CRITICAL" }, { - "current": { + "refId": "B", + "scenarioId": "csv_metric_values", + "stringInput": "NORMAL,LOW,LOW,CRITICAL,CRITICAL,LOW,LOW,NORMAL,HIGH,CRITICAL" + }, + { + "refId": "C", + "scenarioId": "csv_metric_values", + "stringInput": "NORMAL,NORMAL,NORMAL,NORMAL,CRITICAL,LOW,NORMAL,NORMAL,NORMAL,LOW" + } + ], + "title": "State timeline", + "type": "state-timeline" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 9, + "x": 0, + "y": 0 + }, + "id": 62, + "options": { + "basemap": { + "config": {}, + "type": "default" + }, + "controls": { + "mouseWheelZoom": true, + "showAttribution": true, + "showDebug": false, + "showScale": false, + "showZoom": true + }, + "layers": [ + { + "config": { + "color": { + "field": "Price", + "fixed": "dark-green" + }, + "fillOpacity": 0.4, + "shape": "circle", + "showLegend": true, + "size": { + "field": "Count", + "fixed": 5, + "max": 15, + "min": 2 + } + }, + "location": { + "gazetteer": "public/gazetteer/usa-states.json", + "lookup": "State", + "mode": "auto" + }, + "type": "markers" + } + ], + "view": { + "id": "coords", + "lat": 38.297683, + "lon": -99.228359, + "shared": true, + "zoom": 3.98 + } + }, + "targets": [ + { + "csvFileName": "flight_info_by_state.csv", + "refId": "A", + "scenarioId": "csv_file" + } + ], + "title": "Size, color mapped to different fields + share view", + "type": "geomap" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "fillOpacity": 80, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1 + }, + "links": [ + { + "title": "Data link", + "url": "/" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 13 + }, + "id": 4, + "options": { + "bucketOffset": 0, + "combine": false, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + } + }, + "title": "Histogram", + "type": "histogram" + }, + { + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 28, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "targets": [ + { + "refId": "A", + "scenarioId": "logs" + } + ], + "title": "Logs", + "type": "logs" + }, + { + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 21 + }, + "id": 8, + "options": { + "maxItems": 10, + "query": "", + "showHeadings": true, + "showRecentlyViewed": true, + "showSearch": true, + "showStarred": true, + "tags": [] + }, + "pluginVersion": "8.1.0-pre", + "title": "Dashboard list", + "type": "dashlist" + }, + { + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 29 + }, + "id": 6, + "options": { + "alertName": "", + "dashboardAlerts": false, + "maxItems": 20, + "showInstances": false, + "sortOrder": 1, + "stateFilter": { + "firing": true, + "inactive": false, + "pending": true + } + }, + "title": "Alert list", + "type": "alertlist" + }, + { + "cards": {}, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateOranges", + "exponent": 0.5, + "mode": "spectrum" + }, + "dataFormat": "timeseries", + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 37 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 26, + "legend": { + "show": false + }, + "reverseYBuckets": false, + "targets": [ + { + "refId": "A", + "scenarioId": "exponential_heatmap_bucket_data" + } + ], + "title": "Heatmap", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "yAxis": { + "format": "short", + "logBase": 1, + "show": true + }, + "yBucketBound": "auto" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 37 + }, + "id": 20, + "options": { + "displayMode": "gradient", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "text": {} + }, + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 10 + } + ], + "title": "Bar gauge", + "type": "bargauge" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [] + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 45 + }, + "id": 24, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "pieType": "pie", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 6 + } + ], + "title": "Pie chart", + "type": "piechart" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 45 + }, + "id": 18, + "options": { + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "orientation": "auto", + "showValue": "auto", + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 3 + } + ], + "title": "Gauge", + "type": "gauge" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 53 + }, + "id": 22, + "options": { + "showHeader": true + }, + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "table_static" + } + ], + "title": "Tabel", + "type": "table" + }, + { + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 53 + }, + "id": 10, + "options": { + "limit": 10, + "navigateAfter": "10m", + "navigateBefore": "10m", + "onlyFromThisDashboard": false, + "onlyInTimeRange": false, + "showTags": true, + "showTime": true, + "showUser": true + }, + "title": "Annotation list", + "type": "annolist" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 61 + }, + "id": 16, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.1.0-pre", + "title": "Stat", + "type": "stat" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 61 + }, + "id": 2, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 4, + "spread": 120 + } + ], + "title": "Graph NG", + "type": "timeseries" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMin": 0, + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1 + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 69 + }, + "id": 14, + "options": { + "barWidth": 0.97, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "text": {}, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "csvContent": "Series, Value\nBar 2, 20\nBar 3, 25\nBar 3, 55.4", + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Bar chart", + "type": "barchart" + }, + { + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 77 + }, + "id": 12, + "options": { + "showImage": true + }, + "title": "News panel", + "type": "news" + } + ], + "refresh": "", + "schemaVersion": 36, + "tags": ["gdev", "panel-tests", "all-panels"], + "templating": { + "list": [ + { + "current": {}, + "datasource": { + "type": "grafana-testdata-datasource" + }, + "definition": "*", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "query0", + "options": [], + "query": { + "query": "*", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": true, + "text": "7", + "value": "7" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "query1", + "options": [ + { + "selected": false, + "text": "1", + "value": "1" + }, + { + "selected": false, + "text": "5", + "value": "5" + }, + { + "selected": false, + "text": "6", + "value": "6" + }, + { "selected": true, "text": "7", "value": "7" - }, - "hide": 0, - "includeAll": false, - "multi": false, - "name": "query1", - "options": [ - { - "selected": false, - "text": "1", - "value": "1" - }, - { - "selected": false, - "text": "5", - "value": "5" - }, - { - "selected": false, - "text": "6", - "value": "6" - }, - { - "selected": true, - "text": "7", - "value": "7" - } - ], - "query": "1,5,6,7", - "queryValue": "", - "skipUrlSync": false, - "type": "custom" + } + ], + "query": "1,5,6,7", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "selected": false, + "text": "", + "value": "" }, - { - "current": { - "selected": false, + "description": "This is some descriptive text", + "hide": 0, + "label": "Plain text", + "name": "text", + "options": [ + { + "selected": true, "text": "", "value": "" - }, - "description": "This is some descriptive text", - "hide": 0, - "label": "Plain text", - "name": "text", - "options": [ - { - "selected": true, - "text": "", - "value": "" - } - ], - "query": "", - "skipUrlSync": false, - "type": "textbox" - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Panel tests - All panels", - "uid": "n1jR8vnnz", - "version": 24 - } + } + ], + "query": "", + "skipUrlSync": false, + "type": "textbox" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Panel tests - All panels", + "uid": "n1jR8vnnz", + "version": 24 +} diff --git a/devenv/dev-dashboards/annotations/annotation-filtering.json b/devenv/dev-dashboards/annotations/annotation-filtering.json index a827d960d76..0a07c80ff0a 100644 --- a/devenv/dev-dashboards/annotations/annotation-filtering.json +++ b/devenv/dev-dashboards/annotations/annotation-filtering.json @@ -32,15 +32,12 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "enable": true, "filter": { "exclude": false, - "ids": [ - 1 - ] + "ids": [1] }, "iconColor": "red", "name": "Red, only panel 1", @@ -52,15 +49,12 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "enable": true, "filter": { "exclude": true, - "ids": [ - 1 - ] + "ids": [1] }, "iconColor": "yellow", "name": "Yellow - all except 1", @@ -72,16 +66,12 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "enable": true, "filter": { "exclude": false, - "ids": [ - 3, - 4 - ] + "ids": [3, 4] }, "iconColor": "dark-purple", "name": "Purple only panel 3+4", @@ -101,7 +91,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -176,7 +168,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -251,7 +245,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -326,7 +322,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { diff --git a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_complex.json b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_complex.json index 523a5b9db03..56187286696 100644 --- a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_complex.json +++ b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_complex.json @@ -596,13 +596,7 @@ "field": "value", "id": "1", "settings": { - "percents": [ - "25", - "50", - "75", - "95", - "99" - ] + "percents": ["25", "50", "75", "95", "99"] }, "type": "percentiles" } @@ -4565,13 +4559,7 @@ "field": "float", "id": "1", "settings": { - "percents": [ - "25", - "50", - "75", - "95", - "99" - ], + "percents": ["25", "50", "75", "95", "99"], "script": "_value * 2" }, "type": "percentiles" @@ -4695,9 +4683,7 @@ "field": "value", "id": "1", "settings": { - "percents": [ - "99" - ] + "percents": ["99"] }, "type": "percentiles" } @@ -4927,9 +4913,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -5015,9 +4999,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -5255,9 +5237,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -5291,7 +5271,7 @@ ], "title": "Logs", "type": "row" - }, + }, { "collapsed": true, "gridPos": { @@ -5739,11 +5719,7 @@ ], "refresh": "", "schemaVersion": 38, - "tags": [ - "gdev", - "elasticsearch", - "datasource-test" - ], + "tags": ["gdev", "elasticsearch", "datasource-test"], "templating": { "list": [ { diff --git a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_migration.json b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_migration.json index 47a36a310a9..1acd8d1246f 100644 --- a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_migration.json +++ b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_migration.json @@ -1051,13 +1051,7 @@ "field": "value", "id": "1", "settings": { - "percents": [ - "25", - "50", - "75", - "95", - "99" - ] + "percents": ["25", "50", "75", "95", "99"] }, "type": "percentiles" } @@ -1167,13 +1161,7 @@ "field": "value", "id": "1", "settings": { - "percents": [ - "25", - "50", - "75", - "95", - "99" - ] + "percents": ["25", "50", "75", "95", "99"] }, "type": "percentiles" } @@ -9165,13 +9153,7 @@ "field": "float", "id": "1", "settings": { - "percents": [ - "25", - "50", - "75", - "95", - "99" - ], + "percents": ["25", "50", "75", "95", "99"], "script": "_value * 2" }, "type": "percentiles" @@ -9295,13 +9277,7 @@ "field": "float", "id": "1", "settings": { - "percents": [ - "25", - "50", - "75", - "95", - "99" - ], + "percents": ["25", "50", "75", "95", "99"], "script": "_value * 2" }, "type": "percentiles" @@ -9436,9 +9412,7 @@ "field": "value", "id": "1", "settings": { - "percents": [ - "99" - ] + "percents": ["99"] }, "type": "percentiles" } @@ -9561,9 +9535,7 @@ "field": "value", "id": "1", "settings": { - "percents": [ - "99" - ] + "percents": ["99"] }, "type": "percentiles" } @@ -9959,9 +9931,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -10048,9 +10018,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -10290,9 +10258,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -10330,11 +10296,7 @@ ], "refresh": "", "schemaVersion": 38, - "tags": [ - "gdev", - "elasticsearch", - "datasource-test" - ], + "tags": ["gdev", "elasticsearch", "datasource-test"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_simple.json b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_simple.json index b86f99334a8..bfa84378ba5 100644 --- a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_simple.json +++ b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_simple.json @@ -406,13 +406,7 @@ "id": "1", "meta": {}, "settings": { - "percents": [ - 25, - 50, - 75, - 95, - 99 - ] + "percents": [25, 50, 75, 95, 99] }, "type": "percentiles" } @@ -589,9 +583,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -979,9 +971,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -1059,9 +1049,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -1106,11 +1094,7 @@ ], "refresh": "", "schemaVersion": 38, - "tags": [ - "gdev", - "elasticsearch", - "datasource-test" - ], + "tags": ["gdev", "elasticsearch", "datasource-test"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/datasource-loki/loki_fakedata.json b/devenv/dev-dashboards/datasource-loki/loki_fakedata.json index 947c191ba61..57242a86953 100644 --- a/devenv/dev-dashboards/datasource-loki/loki_fakedata.json +++ b/devenv/dev-dashboards/datasource-loki/loki_fakedata.json @@ -276,9 +276,7 @@ "justifyMode": "auto", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -338,9 +336,7 @@ "justifyMode": "auto", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -366,11 +362,7 @@ ], "refresh": "", "schemaVersion": 37, - "tags": [ - "gdev", - "loki", - "datasource-test" - ], + "tags": ["gdev", "loki", "datasource-test"], "templating": { "list": [ { diff --git a/devenv/dev-dashboards/datasource-loki/loki_query_splitting.json b/devenv/dev-dashboards/datasource-loki/loki_query_splitting.json index 804b354ea9d..0cc5135a0f4 100644 --- a/devenv/dev-dashboards/datasource-loki/loki_query_splitting.json +++ b/devenv/dev-dashboards/datasource-loki/loki_query_splitting.json @@ -65,9 +65,7 @@ "alias": "id_count", "mode": "reduceRow", "reduce": { - "include": [ - "id" - ], + "include": ["id"], "reducer": "count" }, "replaceFields": false @@ -138,9 +136,7 @@ "alias": "id_count", "mode": "reduceRow", "reduce": { - "include": [ - "id" - ], + "include": ["id"], "reducer": "count" }, "replaceFields": false @@ -514,9 +510,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -607,9 +601,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -700,9 +692,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -816,9 +806,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -932,9 +920,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -1049,9 +1035,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -1136,4 +1120,4 @@ "uid": "dc4ec947-7e6b-4c3b-be8f-0abec7b0652a", "version": 2, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/datasource-testdata/demo1.json b/devenv/dev-dashboards/datasource-testdata/demo1.json index 56a57f50b9c..a2400c1716e 100644 --- a/devenv/dev-dashboards/datasource-testdata/demo1.json +++ b/devenv/dev-dashboards/datasource-testdata/demo1.json @@ -23,8 +23,7 @@ "panels": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -196,8 +195,7 @@ { "alias": "memory", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "A", @@ -207,8 +205,7 @@ { "alias": "cpu", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk", @@ -220,8 +217,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -349,8 +345,7 @@ { "alias": "logins", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -359,8 +354,7 @@ { "alias": "logins (-1h)", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk", @@ -373,8 +367,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -426,9 +419,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -440,8 +431,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "target": "scale(apps.backend.backend_01.counters.requests.count, 0.4)" @@ -452,8 +442,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -503,9 +492,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -517,8 +504,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "target": "apps.backend.backend_02.counters.requests.count" @@ -529,8 +515,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -582,9 +567,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -596,8 +579,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "target": "scale(apps.backend.backend_01.counters.requests.count, 0.8)" @@ -608,8 +590,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -659,9 +640,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -673,8 +652,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "target": "apps.backend.backend_04.counters.requests.count" @@ -685,8 +663,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -829,8 +806,7 @@ { "alias": "web_server_01", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -839,8 +815,7 @@ { "alias": "web_server_02", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk" @@ -848,8 +823,7 @@ { "alias": "web_server_03", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "random_walk" @@ -857,8 +831,7 @@ { "alias": "web_server_04", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "random_walk" @@ -869,8 +842,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -922,9 +894,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -936,8 +906,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "target": "scale(apps.backend.backend_01.counters.requests.count, 0.2)" @@ -948,8 +917,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -999,9 +967,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -1013,8 +979,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "target": "scale(apps.backend.backend_01.counters.requests.count, 0.7)" @@ -1025,8 +990,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1076,9 +1040,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -1090,8 +1052,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "target": "scale(apps.backend.backend_03.counters.requests.count, 0.3)" @@ -1102,8 +1063,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1155,9 +1115,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -1169,8 +1127,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "target": "scale(apps.backend.backend_01.counters.requests.count, 0.2)" @@ -1181,8 +1138,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1309,8 +1265,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -1325,10 +1280,7 @@ "preload": false, "refresh": false, "schemaVersion": 41, - "tags": [ - "gdev", - "demo" - ], + "tags": ["gdev", "demo"], "templating": { "list": [] }, @@ -1341,4 +1293,4 @@ "title": "TestData - Demo Dashboard", "uid": "000000003", "version": 2 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/datasource-testdata/new_features_in_v74.json b/devenv/dev-dashboards/datasource-testdata/new_features_in_v74.json index ae996d5a3af..3f495d65f8c 100644 --- a/devenv/dev-dashboards/datasource-testdata/new_features_in_v74.json +++ b/devenv/dev-dashboards/datasource-testdata/new_features_in_v74.json @@ -64,7 +64,9 @@ "type": "row" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -177,7 +179,9 @@ "type": "timeseries" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -290,7 +294,9 @@ "type": "timeseries" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -404,7 +410,9 @@ }, { "cacheTimeout": null, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": {}, @@ -456,7 +464,9 @@ "type": "row" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -555,7 +565,9 @@ "type": "timeseries" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -656,7 +668,9 @@ "type": "timeseries" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "", "fieldConfig": { "defaults": { @@ -758,7 +772,9 @@ "type": "timeseries" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "", "fieldConfig": { "defaults": { @@ -861,7 +877,9 @@ }, { "cacheTimeout": null, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": {}, @@ -913,7 +931,9 @@ "type": "row" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1018,9 +1038,7 @@ "maxDataPoints": 50, "options": { "legend": { - "calcs": [ - "last" - ], + "calcs": ["last"], "displayMode": "list", "placement": "bottom" }, @@ -1121,7 +1139,9 @@ }, { "cacheTimeout": null, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": {}, @@ -1173,7 +1193,9 @@ "type": "row" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1202,10 +1224,7 @@ }, "lineInterpolation": "linear", "lineStyle": { - "dash": [ - 10, - 10 - ], + "dash": [10, 10], "fill": "dash" }, "lineWidth": 2, @@ -1242,10 +1261,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 10, - 20 - ], + "dash": [10, 20], "fill": "dash" } } @@ -1260,10 +1276,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 10, - 30 - ], + "dash": [10, 30], "fill": "dash" } } @@ -1278,11 +1291,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 30, - 3, - 3 - ], + "dash": [30, 3, 3], "fill": "dash" } } @@ -1308,10 +1317,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 0, - 10 - ], + "dash": [0, 10], "fill": "dot" } } @@ -1499,7 +1505,9 @@ "type": "timeseries" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1525,10 +1533,7 @@ }, "lineInterpolation": "linear", "lineStyle": { - "dash": [ - 10, - 10 - ], + "dash": [10, 10], "fill": "solid" }, "lineWidth": 1, @@ -1625,7 +1630,9 @@ "type": "timeseries" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1651,10 +1658,7 @@ }, "lineInterpolation": "linear", "lineStyle": { - "dash": [ - 10, - 10 - ], + "dash": [10, 10], "fill": "solid" }, "lineWidth": 1, @@ -1752,7 +1756,9 @@ }, { "cacheTimeout": null, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": {}, @@ -1790,7 +1796,9 @@ "type": "text" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1929,7 +1937,9 @@ }, { "cacheTimeout": null, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": {}, @@ -1981,7 +1991,9 @@ "type": "row" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -2079,9 +2091,7 @@ "maxDataPoints": 500, "options": { "legend": { - "calcs": [ - "last" - ], + "calcs": ["last"], "displayMode": "list", "placement": "bottom" }, @@ -2125,7 +2135,9 @@ }, { "cacheTimeout": null, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": {}, @@ -2165,11 +2177,7 @@ ], "refresh": false, "schemaVersion": 27, - "tags": [ - "gdev", - "graph-ng", - "demo" - ], + "tags": ["gdev", "graph-ng", "demo"], "templating": { "list": [] }, @@ -2178,17 +2186,7 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "America/New_York", "title": "New Features in v7.4", diff --git a/devenv/dev-dashboards/datasource-testdata/new_features_in_v8.json b/devenv/dev-dashboards/datasource-testdata/new_features_in_v8.json index 75c322564af..797ec076556 100644 --- a/devenv/dev-dashboards/datasource-testdata/new_features_in_v8.json +++ b/devenv/dev-dashboards/datasource-testdata/new_features_in_v8.json @@ -41,7 +41,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "gridPos": { "h": 8, @@ -68,7 +68,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -165,7 +165,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "gridPos": { "h": 15, @@ -345,7 +345,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "gridPos": { "h": 13, @@ -372,7 +372,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -437,7 +437,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -527,7 +527,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "gridPos": { "h": 3, @@ -554,7 +554,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -674,7 +674,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -767,7 +767,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "gridPos": { "h": 3, @@ -794,7 +794,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "gridPos": { "h": 6, @@ -821,7 +821,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -942,7 +942,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1063,7 +1063,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1184,7 +1184,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "gridPos": { "h": 8, @@ -1211,7 +1211,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1315,7 +1315,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { @@ -1422,7 +1422,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { @@ -1529,7 +1529,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "gridPos": { "h": 5, @@ -1556,7 +1556,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1669,9 +1669,7 @@ "maxDataPoints": 50, "options": { "legend": { - "calcs": [ - "last" - ], + "calcs": ["last"], "displayMode": "list", "placement": "bottom" }, @@ -1773,7 +1771,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "gridPos": { "h": 5, @@ -1800,7 +1798,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1821,10 +1819,7 @@ }, "lineInterpolation": "linear", "lineStyle": { - "dash": [ - 10, - 10 - ], + "dash": [10, 10], "fill": "dash" }, "lineWidth": 2, @@ -1866,10 +1861,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 10, - 20 - ], + "dash": [10, 20], "fill": "dash" } } @@ -1884,10 +1876,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 10, - 30 - ], + "dash": [10, 30], "fill": "dash" } } @@ -1902,11 +1891,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 30, - 3, - 3 - ], + "dash": [30, 3, 3], "fill": "dash" } } @@ -1932,10 +1917,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 0, - 10 - ], + "dash": [0, 10], "fill": "dot" } } @@ -2125,7 +2107,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2146,10 +2128,7 @@ }, "lineInterpolation": "linear", "lineStyle": { - "dash": [ - 10, - 10 - ], + "dash": [10, 10], "fill": "dash" }, "lineWidth": 2, @@ -2191,10 +2170,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 10, - 20 - ], + "dash": [10, 20], "fill": "dash" } } @@ -2209,10 +2185,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 10, - 30 - ], + "dash": [10, 30], "fill": "dash" } } @@ -2227,11 +2200,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 30, - 3, - 3 - ], + "dash": [30, 3, 3], "fill": "dash" } } @@ -2257,10 +2226,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 0, - 10 - ], + "dash": [0, 10], "fill": "dot" } } @@ -2450,7 +2416,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2471,10 +2437,7 @@ }, "lineInterpolation": "linear", "lineStyle": { - "dash": [ - 10, - 10 - ], + "dash": [10, 10], "fill": "solid" }, "lineWidth": 1, @@ -2578,7 +2541,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "gridPos": { "h": 3, @@ -2605,7 +2568,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2710,7 +2673,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2814,11 +2777,7 @@ ], "refresh": false, "schemaVersion": 33, - "tags": [ - "gdev", - "graph-ng", - "demo" - ], + "tags": ["gdev", "graph-ng", "demo"], "templating": { "list": [] }, @@ -2827,17 +2786,7 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "", "title": "New Features in v8.0", diff --git a/devenv/dev-dashboards/e2e-repeats/Repeating-Kitchen-Sink.json b/devenv/dev-dashboards/e2e-repeats/Repeating-Kitchen-Sink.json index bdb3ab46b5c..82f271830fb 100644 --- a/devenv/dev-dashboards/e2e-repeats/Repeating-Kitchen-Sink.json +++ b/devenv/dev-dashboards/e2e-repeats/Repeating-Kitchen-Sink.json @@ -27,7 +27,7 @@ "panels": [ { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -115,7 +115,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { @@ -192,7 +192,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { @@ -267,7 +267,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { @@ -350,12 +350,8 @@ { "current": { "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, @@ -391,12 +387,8 @@ { "current": { "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, @@ -432,12 +424,8 @@ { "current": { "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, diff --git a/devenv/dev-dashboards/e2e-repeats/Repeating-a-panel-horizontally.json b/devenv/dev-dashboards/e2e-repeats/Repeating-a-panel-horizontally.json index 2def57915d9..d90b2f02fdb 100644 --- a/devenv/dev-dashboards/e2e-repeats/Repeating-a-panel-horizontally.json +++ b/devenv/dev-dashboards/e2e-repeats/Repeating-a-panel-horizontally.json @@ -30,7 +30,7 @@ "panels": [ { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -112,12 +112,8 @@ { "current": { "selected": false, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, @@ -153,12 +149,8 @@ { "current": { "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, diff --git a/devenv/dev-dashboards/e2e-repeats/Repeating-a-panel-vertically.json b/devenv/dev-dashboards/e2e-repeats/Repeating-a-panel-vertically.json index 9a450a79b4e..f64a8b06ed0 100644 --- a/devenv/dev-dashboards/e2e-repeats/Repeating-a-panel-vertically.json +++ b/devenv/dev-dashboards/e2e-repeats/Repeating-a-panel-vertically.json @@ -26,7 +26,7 @@ "panels": [ { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -108,12 +108,8 @@ { "current": { "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, @@ -149,12 +145,8 @@ { "current": { "selected": true, - "text": [ - "1" - ], - "value": [ - "1" - ] + "text": ["1"], + "value": ["1"] }, "hide": 0, "includeAll": true, diff --git a/devenv/dev-dashboards/e2e-repeats/Repeating-a-row-with-a-repeating-horizontal-panel.json b/devenv/dev-dashboards/e2e-repeats/Repeating-a-row-with-a-repeating-horizontal-panel.json index 5278ec5f319..f0b1ad3dedf 100644 --- a/devenv/dev-dashboards/e2e-repeats/Repeating-a-row-with-a-repeating-horizontal-panel.json +++ b/devenv/dev-dashboards/e2e-repeats/Repeating-a-row-with-a-repeating-horizontal-panel.json @@ -41,7 +41,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { @@ -124,12 +124,8 @@ { "current": { "selected": false, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, @@ -165,12 +161,8 @@ { "current": { "selected": false, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, @@ -206,12 +198,8 @@ { "current": { "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, diff --git a/devenv/dev-dashboards/e2e-repeats/Repeating-a-row-with-a-repeating-vertical-panel.json b/devenv/dev-dashboards/e2e-repeats/Repeating-a-row-with-a-repeating-vertical-panel.json index 34cfd58c81d..b19b4b8d2c9 100644 --- a/devenv/dev-dashboards/e2e-repeats/Repeating-a-row-with-a-repeating-vertical-panel.json +++ b/devenv/dev-dashboards/e2e-repeats/Repeating-a-row-with-a-repeating-vertical-panel.json @@ -41,7 +41,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -123,12 +123,8 @@ { "current": { "selected": false, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, @@ -164,12 +160,8 @@ { "current": { "selected": false, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, @@ -205,12 +197,8 @@ { "current": { "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, diff --git a/devenv/dev-dashboards/e2e-repeats/Repeating-an-empty-row.json b/devenv/dev-dashboards/e2e-repeats/Repeating-an-empty-row.json index 9220c5d1d7b..8ac2547df4b 100644 --- a/devenv/dev-dashboards/e2e-repeats/Repeating-an-empty-row.json +++ b/devenv/dev-dashboards/e2e-repeats/Repeating-an-empty-row.json @@ -47,12 +47,8 @@ { "current": { "selected": false, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, @@ -88,12 +84,8 @@ { "current": { "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, @@ -129,12 +121,8 @@ { "current": { "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, diff --git a/devenv/dev-dashboards/extensions/link-onclick-extensions.json b/devenv/dev-dashboards/extensions/link-onclick-extensions.json index 5119eb4c1b9..b7217bdca36 100644 --- a/devenv/dev-dashboards/extensions/link-onclick-extensions.json +++ b/devenv/dev-dashboards/extensions/link-onclick-extensions.json @@ -23,7 +23,7 @@ "panels": [ { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -101,7 +101,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -144,9 +144,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true, @@ -158,7 +156,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -191,9 +189,7 @@ }, "pieType": "pie", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -205,7 +201,7 @@ "targets": [ { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -213,7 +209,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "B", @@ -226,7 +222,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -302,7 +298,7 @@ "targets": [ { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -310,7 +306,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "B", @@ -339,4 +335,4 @@ "uid": "dbfb47c5-e5e5-4d28-8ac7-35f349b95946", "version": 1, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/extensions/link-path-extensions.json b/devenv/dev-dashboards/extensions/link-path-extensions.json index 6ef0669e371..821a3b00bdb 100644 --- a/devenv/dev-dashboards/extensions/link-path-extensions.json +++ b/devenv/dev-dashboards/extensions/link-path-extensions.json @@ -1,237 +1,233 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 1, - "links": [], - "liveNow": false, - "panels": [ + "annotations": { + "list": [ { + "builtIn": 1, "datasource": { - "type": "testdata" + "type": "grafana", + "uid": "-- Grafana --" }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 6, - "x": 0, - "y": 0 - }, - "id": 6, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "showRowNums": false - }, - "pluginVersion": "9.5.0-53420pre", - "title": "No extensions", - "type": "table" - }, - { - "datasource": { - "type": "testdata" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - } - }, - "mappings": [] - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 6, - "x": 6, - "y": 0 - }, - "id": 4, - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "pieType": "pie", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "testdata" - }, - "refId": "A", - "scenarioId": "random_walk", - "seriesCount": 4 - } - ], - "title": "Link with new name", - "type": "piechart" - }, - { - "datasource": { - "type": "testdata" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 6, - "x": 0, - "y": 8 - }, - "id": 2, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "title": "Link with defaults", - "type": "timeseries" + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" } - ], - "refresh": "", - "schemaVersion": 38, - "style": "dark", - "tags": [], - "templating": { - "list": [] + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true, + "showRowNums": false + }, + "pluginVersion": "9.5.0-53420pre", + "title": "No extensions", + "type": "table" }, - "time": { - "from": "now-6h", - "to": "now" + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [] + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 6, + "y": 0 + }, + "id": 4, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "pieType": "pie", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 4 + } + ], + "title": "Link with new name", + "type": "piechart" }, - "timepicker": {}, - "timezone": "", - "title": "Link Extensions (path)", - "uid": "d1fbb077-cd44-4738-8c8a-d4e66748b719", - "version": 3, - "weekStart": "" - } \ No newline at end of file + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "title": "Link with defaults", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Link Extensions (path)", + "uid": "d1fbb077-cd44-4738-8c8a-d4e66748b719", + "version": 3, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/feature-templating/datadata-macros.json b/devenv/dev-dashboards/feature-templating/datadata-macros.json index a0068fea71e..815ad3f7259 100644 --- a/devenv/dev-dashboards/feature-templating/datadata-macros.json +++ b/devenv/dev-dashboards/feature-templating/datadata-macros.json @@ -1,870 +1,832 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 1267, - "links": [], - "liveNow": false, - "panels": [ + "annotations": { + "list": [ { + "builtIn": 1, "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana", + "uid": "-- Grafana --" }, - "gridPos": { - "h": 3, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 8, - "options": { - "code": { - "language": "plaintext", - "showLineNumbers": false, - "showMiniMap": false - }, - "content": "* `__all_variables`=${__all_variables}\n* `__url_time_range`=${__url_time_range}", - "mode": "markdown" - }, - "pluginVersion": "9.5.0-pre", - "title": "Panel Title", - "type": "text" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "links": [ - { - "targetBlank": true, - "title": "value=${__value.raw}&time=${__value.time}&__value:percentencode=${__value:percentencode}&text=${__value.text}", - "url": "value=${__value.raw}&time=${__value.time}justvalue=${__value:percentencode}&text=${__value.text}" - } - ], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 3 - }, - "id": 2, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "showRowNums": false - }, - "pluginVersion": "9.5.0-pre", - "title": "DataLink: with __value.raw=&__value.time=&__value:percentencode=", - "type": "table" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "links": [ - { - "targetBlank": true, - "title": "Value link", - "url": "value=${__value.raw}" - } - ], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 3 - }, - "id": 3, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.5.0-pre", - "targets": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "random_walk", - "seriesCount": 5 - } - ], - "title": "Stat panel with __value.raw ", - "type": "stat" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "continuous-GrYlRd" - }, - "links": [ - { - "title": "${__value.raw}", - "url": "${__value.raw}" - } - ], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 10 - }, - "id": 6, - "options": { - "displayMode": "basic", - "minVizHeight": 10, - "minVizWidth": 0, - "orientation": "horizontal", - "reduceOptions": { - "calcs": [], - "fields": "", - "values": true - }, - "showUnfilled": true, - "valueMode": "color" - }, - "pluginVersion": "9.5.0-pre", - "targets": [ - { - "csvFileName": "browser_marketshare.csv", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_file" - } - ], - "title": "data link __value.raw", - "transformations": [ - { - "id": "limit", - "options": { - "limitField": 5 - } - } - ], - "type": "bargauge" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "description": "Since this is using getFrameDisplayName it works kind badly (especially with testdata) and only returns the `Series (refId)`. \n\nSo this should show:\n* Series (Query1)\n* Series (Query2)", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "displayName": "${__series.name}", - "links": [ - { - "targetBlank": true, - "title": "Value link", - "url": "value=${__calc}" - } - ], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 10 - }, - "id": 12, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.5.0-pre", - "targets": [ - { - "alias": "", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "Query1", - "scenarioId": "random_walk", - "seriesCount": 1 - }, - { - "alias": "", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "hide": false, - "refId": "Query2", - "scenarioId": "random_walk", - "seriesCount": 1 - } - ], - "title": "${series.name} in display name", - "type": "stat" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "links": [ - { - "title": "__data.refId=${__data.refId}&__data.fields[0]=${__data.fields[0]}&cluster=${__field.labels.cluster}", - "url": "refId=${__data.refId}&__data.fields[0]=${__data.fields[0]}&cluster=${__field.labels.cluster}" - } - ], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 17 - }, - "id": 11, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "showRowNums": false - }, - "pluginVersion": "9.5.0-pre", - "targets": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "labels": "cluster=US", - "refId": "A", - "scenarioId": "random_walk" - } - ], - "title": "DataLink: refId=${__data.refId}&__data.fields[0]=${__data.fields[0]}&cluster=${__field.labels.cluster}", - "type": "table" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [ - { - "title": "${__value.raw}", - "url": "${__value.raw}" - } - ], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 17 - }, - "id": 10, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "alias": "10,20,30,40", - "csvContent": "Time, value, test\n\"2023-03-24T17:12:12.347Z\", 10,hello\n\"2023-03-24T17:22:12.347Z\", 20,asd\n\"2023-03-24T17:32:12.347Z\", 30,asd2\n\"2023-03-24T17:42:12.347Z\", 40,as34\n", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_content" - }, - { - "alias": "5,6,7", - "csvContent": "Time, value, test\n\"2023-03-24T17:12:12.347Z\", 5,hello\n\"2023-03-24T17:22:12.347Z\", 6,asd\n\"2023-03-24T17:42:12.347Z\", 7,as34\n", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "B", - "scenarioId": "csv_content" - } - ], - "title": "Data links with ${__value.raw}", - "transformations": [ - { - "id": "joinByField", - "options": {} - } - ], - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "links": [ - { - "title": "__field.name=${__field.name}&__field.labels.cluster=${__field.labels.cluster}", - "url": "__field.name=${__field.name}&__field.labels.cluster=${__field.labels.cluster}" - } - ], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 24 - }, - "id": 13, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "showRowNums": false - }, - "pluginVersion": "9.5.0-pre", - "targets": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "labels": "cluster=US", - "refId": "A", - "scenarioId": "random_walk" - } - ], - "title": "DataLink: __field.name=&__field.labels.cluster", - "type": "table" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "description": "The stat display names should be \n* Stockholm = Bad\n* New York = Good \n", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "displayName": "$__cell_0 = $__cell_2", - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 24 - }, - "id": 14, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": true - }, - "textMode": "auto" - }, - "pluginVersion": "9.5.0-pre", - "targets": [ - { - "alias": "", - "csvContent": "name, value, name2\nStockholm, 10, Good\nNew York, 15, Bad", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "DisplayName with __cell_0 = __cell_2", - "type": "stat" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "description": "The stat display names should be \n* Stockholm = Bad\n* New York = Good \n", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "displayName": "${__field.name}", - "links": [ - { - "targetBlank": true, - "title": "Value link", - "url": "value=${__calc}" - } - ], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 31 - }, - "id": 15, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "showRowNums": false - }, - "pluginVersion": "9.5.0-pre", - "targets": [ - { - "alias": "", - "csvContent": "name, value, name2\nStockholm, 10, Good\nNew York, 15, Bad", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "DisplayName: __field.name", - "type": "table" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "description": "The stat display names should be \n* Stockholm = Bad\n* New York = Good \n", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "displayName": "${__data.fields[0]} = ${__data.fields[2]}", - "links": [ - { - "targetBlank": true, - "title": "__data.fields[0] = ${__data.fields[0]} = __value.raw = ${__value.raw}", - "url": "__data.fields[0] = ${__data.fields[0]} = __value.raw = ${__value.raw}" - } - ], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 31 - }, - "id": 16, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": true - }, - "textMode": "auto" - }, - "pluginVersion": "9.5.0-pre", - "targets": [ - { - "alias": "", - "csvContent": "name, value, name2\nStockholm, 10, Good\nNew York, 15, Bad", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "$__data.fields[0] = $__data.fields[2] with datalinks", - "type": "stat" + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" } - ], - "refresh": "", - "schemaVersion": 38, - "tags": ["gdev", "templating"], - "templating": { - "list": [ + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1267, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 8, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "* `__all_variables`=${__all_variables}\n* `__url_time_range`=${__url_time_range}", + "mode": "markdown" + }, + "pluginVersion": "9.5.0-pre", + "title": "Panel Title", + "type": "text" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "links": [ + { + "targetBlank": true, + "title": "value=${__value.raw}&time=${__value.time}&__value:percentencode=${__value:percentencode}&text=${__value.text}", + "url": "value=${__value.raw}&time=${__value.time}justvalue=${__value:percentencode}&text=${__value.text}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 3 + }, + "id": 2, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true, + "showRowNums": false + }, + "pluginVersion": "9.5.0-pre", + "title": "DataLink: with __value.raw=&__value.time=&__value:percentencode=", + "type": "table" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "links": [ + { + "targetBlank": true, + "title": "Value link", + "url": "value=${__value.raw}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 3 + }, + "id": 3, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.0-pre", + "targets": [ { - "current": { - "selected": false, + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 5 + } + ], + "title": "Stat panel with __value.raw ", + "type": "stat" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "links": [ + { + "title": "${__value.raw}", + "url": "${__value.raw}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 6, + "options": { + "displayMode": "basic", + "minVizHeight": 10, + "minVizWidth": 0, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": true + }, + "showUnfilled": true, + "valueMode": "color" + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "csvFileName": "browser_marketshare.csv", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_file" + } + ], + "title": "data link __value.raw", + "transformations": [ + { + "id": "limit", + "options": { + "limitField": 5 + } + } + ], + "type": "bargauge" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "Since this is using getFrameDisplayName it works kind badly (especially with testdata) and only returns the `Series (refId)`. \n\nSo this should show:\n* Series (Query1)\n* Series (Query2)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "displayName": "${__series.name}", + "links": [ + { + "targetBlank": true, + "title": "Value link", + "url": "value=${__calc}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 12, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "Query1", + "scenarioId": "random_walk", + "seriesCount": 1 + }, + { + "alias": "", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "hide": false, + "refId": "Query2", + "scenarioId": "random_walk", + "seriesCount": 1 + } + ], + "title": "${series.name} in display name", + "type": "stat" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "links": [ + { + "title": "__data.refId=${__data.refId}&__data.fields[0]=${__data.fields[0]}&cluster=${__field.labels.cluster}", + "url": "refId=${__data.refId}&__data.fields[0]=${__data.fields[0]}&cluster=${__field.labels.cluster}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 11, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true, + "showRowNums": false + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "labels": "cluster=US", + "refId": "A", + "scenarioId": "random_walk" + } + ], + "title": "DataLink: refId=${__data.refId}&__data.fields[0]=${__data.fields[0]}&cluster=${__field.labels.cluster}", + "type": "table" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "title": "${__value.raw}", + "url": "${__value.raw}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "10,20,30,40", + "csvContent": "Time, value, test\n\"2023-03-24T17:12:12.347Z\", 10,hello\n\"2023-03-24T17:22:12.347Z\", 20,asd\n\"2023-03-24T17:32:12.347Z\", 30,asd2\n\"2023-03-24T17:42:12.347Z\", 40,as34\n", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_content" + }, + { + "alias": "5,6,7", + "csvContent": "Time, value, test\n\"2023-03-24T17:12:12.347Z\", 5,hello\n\"2023-03-24T17:22:12.347Z\", 6,asd\n\"2023-03-24T17:42:12.347Z\", 7,as34\n", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "B", + "scenarioId": "csv_content" + } + ], + "title": "Data links with ${__value.raw}", + "transformations": [ + { + "id": "joinByField", + "options": {} + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "links": [ + { + "title": "__field.name=${__field.name}&__field.labels.cluster=${__field.labels.cluster}", + "url": "__field.name=${__field.name}&__field.labels.cluster=${__field.labels.cluster}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 13, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true, + "showRowNums": false + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "labels": "cluster=US", + "refId": "A", + "scenarioId": "random_walk" + } + ], + "title": "DataLink: __field.name=&__field.labels.cluster", + "type": "table" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "The stat display names should be \n* Stockholm = Bad\n* New York = Good \n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "displayName": "$__cell_0 = $__cell_2", + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 14, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": true + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "csvContent": "name, value, name2\nStockholm, 10, Good\nNew York, 15, Bad", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "DisplayName with __cell_0 = __cell_2", + "type": "stat" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "The stat display names should be \n* Stockholm = Bad\n* New York = Good \n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "displayName": "${__field.name}", + "links": [ + { + "targetBlank": true, + "title": "Value link", + "url": "value=${__calc}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 31 + }, + "id": 15, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true, + "showRowNums": false + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "csvContent": "name, value, name2\nStockholm, 10, Good\nNew York, 15, Bad", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "DisplayName: __field.name", + "type": "table" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "description": "The stat display names should be \n* Stockholm = Bad\n* New York = Good \n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "displayName": "${__data.fields[0]} = ${__data.fields[2]}", + "links": [ + { + "targetBlank": true, + "title": "__data.fields[0] = ${__data.fields[0]} = __value.raw = ${__value.raw}", + "url": "__data.fields[0] = ${__data.fields[0]} = __value.raw = ${__value.raw}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 31 + }, + "id": 16, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": true + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "csvContent": "name, value, name2\nStockholm, 10, Good\nNew York, 15, Bad", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "$__data.fields[0] = $__data.fields[2] with datalinks", + "type": "stat" + } + ], + "refresh": "", + "schemaVersion": 38, + "tags": ["gdev", "templating"], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "A", + "value": "A" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "customVar", + "options": [ + { + "selected": true, "text": "A", "value": "A" }, - "hide": 0, - "includeAll": false, - "multi": false, - "name": "customVar", - "options": [ - { - "selected": true, - "text": "A", - "value": "A" - }, - { - "selected": false, - "text": "B", - "value": "B" - }, - { - "selected": false, - "text": "C", - "value": "C" - } - ], - "query": "A,B,C", - "queryValue": "", - "skipUrlSync": false, - "type": "custom" - } - ] - }, - "time": { - "from": "2023-03-24T17:12:12.347Z", - "to": "2023-03-24T17:42:12.347Z" - }, - "timepicker": {}, - "timezone": "", - "title": "Templating - Macros", - "uid": "e7c29343-6d1e-4167-9c13-803fe5be8c46", - "version": 48, - "weekStart": "" - } + { + "selected": false, + "text": "B", + "value": "B" + }, + { + "selected": false, + "text": "C", + "value": "C" + } + ], + "query": "A,B,C", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "2023-03-24T17:12:12.347Z", + "to": "2023-03-24T17:42:12.347Z" + }, + "timepicker": {}, + "timezone": "", + "title": "Templating - Macros", + "uid": "e7c29343-6d1e-4167-9c13-803fe5be8c46", + "version": 48, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/feature-templating/templating-repeating-panels.json b/devenv/dev-dashboards/feature-templating/templating-repeating-panels.json index ee69cd7e110..ebf8b77d814 100644 --- a/devenv/dev-dashboards/feature-templating/templating-repeating-panels.json +++ b/devenv/dev-dashboards/feature-templating/templating-repeating-panels.json @@ -42,7 +42,9 @@ "type": "text" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -123,8 +125,7 @@ { "alias": "server = $server", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -156,7 +157,9 @@ "type": "text" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -239,8 +242,7 @@ { "alias": "host = ${host:text} / id = $host", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -259,16 +261,8 @@ { "current": { "selected": false, - "text": [ - "A", - "B", - "C" - ], - "value": [ - "A", - "B", - "C" - ] + "text": ["A", "B", "C"], + "value": ["A", "B", "C"] }, "hide": 0, "includeAll": true, @@ -354,12 +348,8 @@ { "current": { "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "hide": 0, "includeAll": true, @@ -414,4 +404,4 @@ "uid": "templating-repeating-panels", "version": 37, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/feature-templating/templating-repeating-rows.json b/devenv/dev-dashboards/feature-templating/templating-repeating-rows.json index af630afd1f5..1c407e4a0e5 100644 --- a/devenv/dev-dashboards/feature-templating/templating-repeating-rows.json +++ b/devenv/dev-dashboards/feature-templating/templating-repeating-rows.json @@ -69,7 +69,9 @@ "type": "row" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -150,8 +152,7 @@ { "alias": "server = $server, pod id = $pod ", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -198,23 +199,14 @@ ], "refresh": "", "schemaVersion": 38, - "tags": [ - "templating", - "gdev" - ], + "tags": ["templating", "gdev"], "templating": { "list": [ { "current": { "selected": true, - "text": [ - "A", - "B" - ], - "value": [ - "A", - "B" - ] + "text": ["A", "B"], + "value": ["A", "B"] }, "hide": 0, "includeAll": true, @@ -300,14 +292,8 @@ { "current": { "selected": true, - "text": [ - "Bob", - "Rob" - ], - "value": [ - "1", - "2" - ] + "text": ["Bob", "Rob"], + "value": ["1", "2"] }, "hide": 0, "includeAll": true, @@ -362,4 +348,4 @@ "uid": "Repeating-rows-uid", "version": 1, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/feature-templating/testdata-nested-variables-drilldown.json b/devenv/dev-dashboards/feature-templating/testdata-nested-variables-drilldown.json index 73b9a970880..357a764f2c6 100644 --- a/devenv/dev-dashboards/feature-templating/testdata-nested-variables-drilldown.json +++ b/devenv/dev-dashboards/feature-templating/testdata-nested-variables-drilldown.json @@ -128,7 +128,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 0, "gridPos": { @@ -221,7 +223,9 @@ "text": "A", "value": ["A"] }, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "definition": "*", "hide": 0, "includeAll": true, @@ -246,7 +250,9 @@ "text": "AA", "value": ["AA"] }, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "definition": "$datacenter.*", "hide": 0, "includeAll": true, @@ -271,7 +277,9 @@ "text": "All", "value": ["$__all"] }, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "definition": "$datacenter.$server.*", "hide": 0, "includeAll": true, diff --git a/devenv/dev-dashboards/feature-templating/testdata-nested-variables.json b/devenv/dev-dashboards/feature-templating/testdata-nested-variables.json index 6c3b9760e66..ede752ed948 100644 --- a/devenv/dev-dashboards/feature-templating/testdata-nested-variables.json +++ b/devenv/dev-dashboards/feature-templating/testdata-nested-variables.json @@ -51,7 +51,9 @@ "colorBackground": false, "colorValue": false, "colors": ["#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a"], - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "custom": {} @@ -345,7 +347,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "custom": {} @@ -446,7 +450,9 @@ "text": "A", "value": ["A"] }, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "definition": "*", "hide": 0, "includeAll": true, @@ -472,7 +478,9 @@ "text": "AA", "value": ["AA"] }, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "definition": "$datacenter.*", "hide": 0, "includeAll": true, @@ -498,7 +506,9 @@ "text": "All", "value": ["$__all"] }, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "definition": "$datacenter.$server.*", "hide": 0, "includeAll": true, diff --git a/devenv/dev-dashboards/feature-templating/testdata-variables-that-update-on-time-change.json b/devenv/dev-dashboards/feature-templating/testdata-variables-that-update-on-time-change.json index b7d1b02a9ab..48d6dce2277 100644 --- a/devenv/dev-dashboards/feature-templating/testdata-variables-that-update-on-time-change.json +++ b/devenv/dev-dashboards/feature-templating/testdata-variables-that-update-on-time-change.json @@ -123,7 +123,9 @@ "text": "value.1584434137814", "value": "value.1584434137814" }, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "definition": "value.$__from", "hide": 0, "includeAll": false, @@ -149,7 +151,9 @@ "text": "value.value.1584434072074", "value": "value.value.1584434072074" }, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "definition": "value.$updatesOnTime", "hide": 0, "includeAll": false, diff --git a/devenv/dev-dashboards/home.json b/devenv/dev-dashboards/home.json index 410e1bcf290..5f87229e532 100644 --- a/devenv/dev-dashboards/home.json +++ b/devenv/dev-dashboards/home.json @@ -29,7 +29,7 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "gridPos": { "h": 26, "w": 6, @@ -53,7 +53,7 @@ "type": "dashlist" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "gridPos": { "h": 13, "w": 6, @@ -69,19 +69,15 @@ "showRecentlyViewed": false, "showSearch": true, "showStarred": false, - "tags": [ - "panel-tests" - ] + "tags": ["panel-tests"] }, "pluginVersion": "9.0.0-pre", - "tags": [ - "panel-tests" - ], + "tags": ["panel-tests"], "title": "tag: panel-tests", "type": "dashlist" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "gridPos": { "h": 13, "w": 6, @@ -97,21 +93,15 @@ "showRecentlyViewed": false, "showSearch": true, "showStarred": false, - "tags": [ - "gdev", - "demo" - ] + "tags": ["gdev", "demo"] }, "pluginVersion": "9.0.0-pre", - "tags": [ - "gdev", - "demo" - ], + "tags": ["gdev", "demo"], "title": "tag: dashboard-demo", "type": "dashlist" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "gridPos": { "h": 26, "w": 6, @@ -127,21 +117,15 @@ "showRecentlyViewed": false, "showSearch": true, "showStarred": false, - "tags": [ - "gdev", - "datasource-test" - ] + "tags": ["gdev", "datasource-test"] }, "pluginVersion": "9.0.0-pre", - "tags": [ - "gdev", - "datasource-test" - ], + "tags": ["gdev", "datasource-test"], "title": "Data source tests", "type": "dashlist" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "gridPos": { "h": 13, "w": 6, @@ -157,21 +141,15 @@ "showRecentlyViewed": false, "showSearch": true, "showStarred": false, - "tags": [ - "templating", - "gdev" - ] + "tags": ["templating", "gdev"] }, "pluginVersion": "9.0.0-pre", - "tags": [ - "templating", - "gdev" - ], + "tags": ["templating", "gdev"], "title": "tag: templating ", "type": "dashlist" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "gridPos": { "h": 13, "w": 6, @@ -187,16 +165,10 @@ "showRecentlyViewed": false, "showSearch": true, "showStarred": false, - "tags": [ - "gdev", - "transform" - ] + "tags": ["gdev", "transform"] }, "pluginVersion": "9.0.0-pre", - "tags": [ - "gdev", - "demo" - ], + "tags": ["gdev", "demo"], "title": "tag: transforms", "type": "dashlist" } @@ -211,18 +183,7 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "", "title": "Grafana Dev Overview & Home", diff --git a/devenv/dev-dashboards/live/live-flakey-refresh.json b/devenv/dev-dashboards/live/live-flakey-refresh.json index c68dd267f9c..2fb5f98261f 100644 --- a/devenv/dev-dashboards/live/live-flakey-refresh.json +++ b/devenv/dev-dashboards/live/live-flakey-refresh.json @@ -1,377 +1,368 @@ { - "annotations": { - "list": [ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 220, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": false, + "keepTime": false, + "tags": ["live-tests"], + "targetBlank": false, + "title": "gdev live tests", + "tooltip": "", + "type": "dashboards", + "url": "" + } + ], + "liveNow": true, + "panels": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 2, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 9, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "## Note the consistent refresh rate (liveNow = true)", + "mode": "markdown" + }, + "pluginVersion": "11.1.0-pre", + "type": "text" + }, + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 4, + "w": 11, + "x": 0, + "y": 2 + }, + "id": 2, + "options": { + "channel": { + "namespace": "devenv", + "path": "weather", + "scope": "stream" + }, + "display": "none", + "json": { + "hello": "world" + }, + "message": "weather,location=west,sensor=A temperature=82\nweather,location=east,sensor=A temperature=76", + "publish": "influx" + }, + "title": "Enter weather data", + "type": "live" + }, + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 13, + "x": 11, + "y": 2 + }, + "id": 4, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "11.1.0-pre", + "targets": [ { - "builtIn": 1, + "channel": "stream/devenv/weather", "datasource": { - "type": "grafana", - "uid": "-- Grafana --" + "type": "datasource", + "uid": "grafana" }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" + "queryType": "measurements", + "refId": "A" } - ] + ], + "title": "Weather (values)", + "transformations": [ + { + "id": "reduce", + "options": { + "includeTimeField": true, + "labelsToFields": false, + "mode": "reduceFields", + "reducers": ["last"] + } + } + ], + "type": "table" }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 220, - "links": [ - { - "asDropdown": false, - "icon": "external link", - "includeVars": false, - "keepTime": false, - "tags": [ - "live-tests" - ], - "targetBlank": false, - "title": "gdev live tests", - "tooltip": "", - "type": "dashboards", - "url": "" - } - ], - "liveNow": true, - "panels": [ - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "gridPos": { - "h": 2, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 9, - "options": { - "code": { - "language": "plaintext", - "showLineNumbers": false, - "showMiniMap": false - }, - "content": "## Note the consistent refresh rate (liveNow = true)", - "mode": "markdown" - }, - "pluginVersion": "11.1.0-pre", - "type": "text" + { + "datasource": { + "type": "datasource", + "uid": "grafana" }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "gridPos": { - "h": 4, - "w": 11, - "x": 0, - "y": 2 - }, - "id": 2, - "options": { - "channel": { - "namespace": "devenv", - "path": "weather", - "scope": "stream" + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" }, - "display": "none", - "json": { - "hello": "world" - }, - "message": "weather,location=west,sensor=A temperature=82\nweather,location=east,sensor=A temperature=76", - "publish": "influx" - }, - "title": "Enter weather data", - "type": "live" - }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 7, + "scaleDistribution": { + "type": "linear" }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] + "showPoints": "always", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] - }, - "gridPos": { - "h": 4, - "w": 13, - "x": 11, - "y": 2 - }, - "id": 4, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "11.1.0-pre", - "targets": [ - { - "channel": "stream/devenv/weather", - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "queryType": "measurements", - "refId": "A" - } - ], - "title": "Weather (values)", - "transformations": [ - { - "id": "reduce", - "options": { - "includeTimeField": true, - "labelsToFields": false, - "mode": "reduceFields", - "reducers": [ - "last" - ] - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 7, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "always", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 6 - }, - "id": 1, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" + ] } }, - "targets": [ - { - "channel": "stream/devenv/weather", - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "queryType": "measurements", - "refId": "A" - } - ], - "title": "Manually entered weather points", - "type": "timeseries" + "overrides": [] }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "channel": "stream/devenv/weather", + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "queryType": "measurements", + "refId": "A" + } + ], + "title": "Manually entered weather points", + "type": "timeseries" + }, + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 7, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "always", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 7, + "scaleDistribution": { + "type": "linear" }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] + "showPoints": "always", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } }, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 13 + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 13 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 10, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "channel": "plugin/testdata/random-flakey-stream", + "datasource": { + "type": "datasource", + "uid": "grafana" }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "channel": "plugin/testdata/random-flakey-stream", - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "queryType": "measurements", - "refId": "A" - } - ], - "title": "Random flakey stream", - "type": "timeseries" - } - ], - "schemaVersion": 39, - "tags": [ - "gdev", - "live-tests" - ], - "templating": { - "list": [] - }, - "time": { - "from": "now-30s", - "to": "now" - }, - "timeRangeUpdatedDuringEditOrView": false, - "timepicker": {}, - "timezone": "browser", - "title": "Live flakey stream (w/ liveNow)", - "uid": "liveddluze", - "version": 4, - "weekStart": "" - } \ No newline at end of file + "queryType": "measurements", + "refId": "A" + } + ], + "title": "Random flakey stream", + "type": "timeseries" + } + ], + "schemaVersion": 39, + "tags": ["gdev", "live-tests"], + "templating": { + "list": [] + }, + "time": { + "from": "now-30s", + "to": "now" + }, + "timeRangeUpdatedDuringEditOrView": false, + "timepicker": {}, + "timezone": "browser", + "title": "Live flakey stream (w/ liveNow)", + "uid": "liveddluze", + "version": 4, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/live/live-flakey.json b/devenv/dev-dashboards/live/live-flakey.json index e8ae8a7d1b0..d7ff8d6cb0b 100644 --- a/devenv/dev-dashboards/live/live-flakey.json +++ b/devenv/dev-dashboards/live/live-flakey.json @@ -1,377 +1,368 @@ { - "annotations": { - "list": [ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 220, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": false, + "keepTime": false, + "tags": ["live-tests"], + "targetBlank": false, + "title": "gdev live tests", + "tooltip": "", + "type": "dashboards", + "url": "" + } + ], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 2, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 9, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "## Note the flakey refresh rate (liveNow = false). Also the time axis is not the same for all panels.", + "mode": "markdown" + }, + "pluginVersion": "11.1.0-pre", + "type": "text" + }, + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 4, + "w": 11, + "x": 0, + "y": 2 + }, + "id": 2, + "options": { + "channel": { + "namespace": "devenv", + "path": "weather", + "scope": "stream" + }, + "display": "none", + "json": { + "hello": "world" + }, + "message": "weather,location=west,sensor=A temperature=82\nweather,location=east,sensor=A temperature=76", + "publish": "influx" + }, + "title": "Enter weather data", + "type": "live" + }, + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 13, + "x": 11, + "y": 2 + }, + "id": 4, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "11.1.0-pre", + "targets": [ { - "builtIn": 1, + "channel": "stream/devenv/weather", "datasource": { - "type": "grafana", - "uid": "-- Grafana --" + "type": "datasource", + "uid": "grafana" }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" + "queryType": "measurements", + "refId": "A" } - ] + ], + "title": "Weather (values)", + "transformations": [ + { + "id": "reduce", + "options": { + "includeTimeField": true, + "labelsToFields": false, + "mode": "reduceFields", + "reducers": ["last"] + } + } + ], + "type": "table" }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 220, - "links": [ - { - "asDropdown": false, - "icon": "external link", - "includeVars": false, - "keepTime": false, - "tags": [ - "live-tests" - ], - "targetBlank": false, - "title": "gdev live tests", - "tooltip": "", - "type": "dashboards", - "url": "" - } - ], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "gridPos": { - "h": 2, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 9, - "options": { - "code": { - "language": "plaintext", - "showLineNumbers": false, - "showMiniMap": false - }, - "content": "## Note the flakey refresh rate (liveNow = false). Also the time axis is not the same for all panels.", - "mode": "markdown" - }, - "pluginVersion": "11.1.0-pre", - "type": "text" + { + "datasource": { + "type": "datasource", + "uid": "grafana" }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "gridPos": { - "h": 4, - "w": 11, - "x": 0, - "y": 2 - }, - "id": 2, - "options": { - "channel": { - "namespace": "devenv", - "path": "weather", - "scope": "stream" + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" }, - "display": "none", - "json": { - "hello": "world" - }, - "message": "weather,location=west,sensor=A temperature=82\nweather,location=east,sensor=A temperature=76", - "publish": "influx" - }, - "title": "Enter weather data", - "type": "live" - }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 7, + "scaleDistribution": { + "type": "linear" }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] + "showPoints": "always", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] - }, - "gridPos": { - "h": 4, - "w": 13, - "x": 11, - "y": 2 - }, - "id": 4, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "11.1.0-pre", - "targets": [ - { - "channel": "stream/devenv/weather", - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "queryType": "measurements", - "refId": "A" - } - ], - "title": "Weather (values)", - "transformations": [ - { - "id": "reduce", - "options": { - "includeTimeField": true, - "labelsToFields": false, - "mode": "reduceFields", - "reducers": [ - "last" - ] - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 7, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "always", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 6 - }, - "id": 1, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" + ] } }, - "targets": [ - { - "channel": "stream/devenv/weather", - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "queryType": "measurements", - "refId": "A" - } - ], - "title": "Manually entered weather points", - "type": "timeseries" + "overrides": [] }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "channel": "stream/devenv/weather", + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "queryType": "measurements", + "refId": "A" + } + ], + "title": "Manually entered weather points", + "type": "timeseries" + }, + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 7, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "always", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 7, + "scaleDistribution": { + "type": "linear" }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] + "showPoints": "always", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } }, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 13 + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 13 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 10, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "channel": "plugin/testdata/random-flakey-stream", + "datasource": { + "type": "datasource", + "uid": "grafana" }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "channel": "plugin/testdata/random-flakey-stream", - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "queryType": "measurements", - "refId": "A" - } - ], - "title": "Random flakey stream", - "type": "timeseries" - } - ], - "schemaVersion": 39, - "tags": [ - "gdev", - "live-tests" - ], - "templating": { - "list": [] - }, - "time": { - "from": "now-30s", - "to": "now" - }, - "timeRangeUpdatedDuringEditOrView": false, - "timepicker": {}, - "timezone": "browser", - "title": "Live flakey stream", - "uid": "liveddluzy", - "version": 4, - "weekStart": "" - } \ No newline at end of file + "queryType": "measurements", + "refId": "A" + } + ], + "title": "Random flakey stream", + "type": "timeseries" + } + ], + "schemaVersion": 39, + "tags": ["gdev", "live-tests"], + "templating": { + "list": [] + }, + "time": { + "from": "now-30s", + "to": "now" + }, + "timeRangeUpdatedDuringEditOrView": false, + "timepicker": {}, + "timezone": "browser", + "title": "Live flakey stream", + "uid": "liveddluzy", + "version": 4, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/live/live-publish.json b/devenv/dev-dashboards/live/live-publish.json index 50269ad28e2..6121af7eea2 100644 --- a/devenv/dev-dashboards/live/live-publish.json +++ b/devenv/dev-dashboards/live/live-publish.json @@ -1,462 +1,453 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 209, - "links": [ + "annotations": { + "list": [ { - "asDropdown": false, - "icon": "external link", - "includeVars": false, - "keepTime": false, - "tags": [ - "live-tests" - ], - "targetBlank": false, - "title": "gdev live tests", - "tooltip": "", - "type": "dashboards", - "url": "" + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" } - ], - "panels": [ - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "gridPos": { - "h": 2, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 9, - "options": { - "code": { - "language": "plaintext", - "showLineNumbers": false, - "showMiniMap": false - }, - "content": "## This dashboard requires alpha panels to be enabled!", - "mode": "markdown" - }, - "pluginVersion": "11.0.0-pre", - "type": "text" + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 209, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": false, + "keepTime": false, + "tags": ["live-tests"], + "targetBlank": false, + "title": "gdev live tests", + "tooltip": "", + "type": "dashboards", + "url": "" + } + ], + "panels": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "gridPos": { - "h": 4, - "w": 15, - "x": 0, - "y": 2 - }, - "id": 2, - "options": { - "channel": { - "namespace": "devenv", - "path": "weather", - "scope": "stream" - }, - "display": "none", - "json": { - "hello": "world" - }, - "message": "weather,location=west,sensor=A temperature=82\nweather,location=east,sensor=A temperature=76", - "publish": "influx" - }, - "title": "Panel Title", - "type": "live" + "gridPos": { + "h": 2, + "w": 24, + "x": 0, + "y": 0 }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" + "id": 9, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 9, - "x": 15, - "y": 2 - }, - "id": 4, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [] - }, - "pluginVersion": "11.0.0-pre", - "targets": [ - { - "channel": "stream/devenv/weather", - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "queryType": "measurements", - "refId": "A" - } - ], - "title": "Weather (values)", - "transformations": [ - { - "id": "sortBy", - "options": { - "fields": {}, - "sort": [ - { - "desc": true, - "field": "time" - } - ] - } - } - ], - "type": "table" + "content": "## This dashboard requires alpha panels to be enabled!", + "mode": "markdown" }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "gridPos": { - "h": 4, - "w": 15, - "x": 0, - "y": 6 - }, - "id": 5, - "options": { - "channel": { - "namespace": "devenv", - "path": "weather", - "scope": "stream" - }, - "display": "none", - "json": { - "hello": "world" - }, - "message": "weather,location=west,sensor=A temperature=90\nweather,location=east,sensor=A temperature=80", - "publish": "influx" - }, - "title": "Timeseries with multiple streaming queries", - "type": "live" + "pluginVersion": "11.0.0-pre", + "type": "text" + }, + { + "datasource": { + "type": "datasource", + "uid": "grafana" }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" + "gridPos": { + "h": 4, + "w": 15, + "x": 0, + "y": 2 + }, + "id": 2, + "options": { + "channel": { + "namespace": "devenv", + "path": "weather", + "scope": "stream" }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" + "display": "none", + "json": { + "hello": "world" + }, + "message": "weather,location=west,sensor=A temperature=82\nweather,location=east,sensor=A temperature=76", + "publish": "influx" + }, + "title": "Panel Title", + "type": "live" + }, + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 9, + "x": 15, + "y": 2 + }, + "id": 4, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "11.0.0-pre", + "targets": [ + { + "channel": "stream/devenv/weather", + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "queryType": "measurements", + "refId": "A" + } + ], + "title": "Weather (values)", + "transformations": [ + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "desc": true, + "field": "time" + } + ] + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 4, + "w": 15, + "x": 0, + "y": 6 + }, + "id": 5, + "options": { + "channel": { + "namespace": "devenv", + "path": "weather", + "scope": "stream" + }, + "display": "none", + "json": { + "hello": "world" + }, + "message": "weather,location=west,sensor=A temperature=90\nweather,location=east,sensor=A temperature=80", + "publish": "influx" + }, + "title": "Timeseries with multiple streaming queries", + "type": "live" + }, + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 1, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "channel": "stream/devenv/weather", - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "queryType": "measurements", - "refId": "A" - }, - { - "channel": "stream/devenv/weatherX", - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "hide": false, - "queryType": "measurements", - "refId": "B" - } - ], - "title": "Panel Title", - "type": "timeseries" - }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "gridPos": { - "h": 4, - "w": 15, - "x": 0, - "y": 17 - }, - "id": 6, - "options": { - "channel": { - "namespace": "devenv", - "path": "weather", - "scope": "stream" - }, - "display": "none", - "json": { - "hello": "world" - }, - "message": "weatherX,location=west,sensor=X temperature=82\nweatherX,location=east,sensor=X temperature=76", - "publish": "influx" - }, - "title": "Panel Title", - "type": "live" - }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 9, - "x": 15, - "y": 17 - }, - "id": 7, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [] - }, - "pluginVersion": "11.0.0-pre", - "targets": [ - { - "channel": "stream/devenv/weatherX", - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "queryType": "measurements", - "refId": "A" + { + "color": "red", + "value": 80 + } + ] } - ], - "title": "WeatherX (values)", - "transformations": [ - { - "id": "sortBy", - "options": { - "fields": {}, - "sort": [ - { - "desc": true, - "field": "time" - } - ] - } - } - ], - "type": "table" + }, + "overrides": [] }, - { - "datasource": { - "type": "datasource", - "uid": "grafana" + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "gridPos": { - "h": 4, - "w": 15, - "x": 0, - "y": 21 - }, - "id": 8, - "options": { - "channel": { - "namespace": "devenv", - "path": "weather", - "scope": "stream" + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "channel": "stream/devenv/weather", + "datasource": { + "type": "datasource", + "uid": "grafana" }, - "display": "none", - "json": { - "hello": "world" - }, - "message": "weatherX,location=west,sensor=X temperature=90\nweatherX,location=east,sensor=X temperature=22", - "publish": "influx" + "queryType": "measurements", + "refId": "A" }, - "title": "Panel Title", - "type": "live" - } - ], - "schemaVersion": 39, - "tags": [ - "gdev", - "live-tests" - ], - "templating": { - "list": [] + { + "channel": "stream/devenv/weatherX", + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "hide": false, + "queryType": "measurements", + "refId": "B" + } + ], + "title": "Panel Title", + "type": "timeseries" }, - "time": { - "from": "now-1m", - "to": "now" + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 4, + "w": 15, + "x": 0, + "y": 17 + }, + "id": 6, + "options": { + "channel": { + "namespace": "devenv", + "path": "weather", + "scope": "stream" + }, + "display": "none", + "json": { + "hello": "world" + }, + "message": "weatherX,location=west,sensor=X temperature=82\nweatherX,location=east,sensor=X temperature=76", + "publish": "influx" + }, + "title": "Panel Title", + "type": "live" }, - "timepicker": {}, - "timezone": "browser", - "title": "Live publish test", - "uid": "addoomtlivedev", - "version": 17, - "weekStart": "" - } \ No newline at end of file + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 9, + "x": 15, + "y": 17 + }, + "id": 7, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "11.0.0-pre", + "targets": [ + { + "channel": "stream/devenv/weatherX", + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "queryType": "measurements", + "refId": "A" + } + ], + "title": "WeatherX (values)", + "transformations": [ + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "desc": true, + "field": "time" + } + ] + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 4, + "w": 15, + "x": 0, + "y": 21 + }, + "id": 8, + "options": { + "channel": { + "namespace": "devenv", + "path": "weather", + "scope": "stream" + }, + "display": "none", + "json": { + "hello": "world" + }, + "message": "weatherX,location=west,sensor=X temperature=90\nweatherX,location=east,sensor=X temperature=22", + "publish": "influx" + }, + "title": "Panel Title", + "type": "live" + } + ], + "schemaVersion": 39, + "tags": ["gdev", "live-tests"], + "templating": { + "list": [] + }, + "time": { + "from": "now-1m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Live publish test", + "uid": "addoomtlivedev", + "version": 17, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/live/live-streams.json b/devenv/dev-dashboards/live/live-streams.json index f7b178ec3b7..f7598ecbd99 100644 --- a/devenv/dev-dashboards/live/live-streams.json +++ b/devenv/dev-dashboards/live/live-streams.json @@ -1,795 +1,758 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 218, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": false, + "keepTime": false, + "tags": ["live-tests"], + "targetBlank": false, + "title": "gdev live tests", + "tooltip": "", + "type": "dashboards", + "url": "" + } + ], + "liveNow": true, + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.lineWidth", + "value": 3 + }, + { + "id": "color", + "value": { + "fixedColor": "super-light-blue", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Max" + }, + "properties": [ + { + "id": "custom.fillBelowTo", + "value": "Min" + }, + { + "id": "custom.fillOpacity", + "value": 72 + }, + { + "id": "color", + "value": { + "fixedColor": "dark-blue", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Min" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 13, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" } - ] + }, + "targets": [ + { + "channel": "random-20Hz-stream", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "live" + } + ], + "title": "Random 20hs stream", + "type": "timeseries" }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 218, - "links": [ - { - "asDropdown": false, - "icon": "external link", - "includeVars": false, - "keepTime": false, - "tags": [ - "live-tests" - ], - "targetBlank": false, - "title": "gdev live tests", - "tooltip": "", - "type": "dashboards", - "url": "" - } - ], - "liveNow": true, - "panels": [ - { - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.lineWidth", - "value": 3 - }, - { - "id": "color", - "value": { - "fixedColor": "super-light-blue", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Max" - }, - "properties": [ - { - "id": "custom.fillBelowTo", - "value": "Min" - }, - { - "id": "custom.fillOpacity", - "value": 72 - }, - { - "id": "color", - "value": { - "fixedColor": "dark-blue", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Min" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "dark-blue", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 7, - "w": 13, - "x": 0, - "y": 0 - }, - "id": 1, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" + ] } }, - "targets": [ - { - "channel": "random-20Hz-stream", - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "live" - } - ], - "title": "Random 20hs stream", - "type": "timeseries" + "overrides": [] }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 7, - "x": 13, - "y": 0 - }, - "id": 5, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Time" - } - ] - }, - "pluginVersion": "11.1.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 1, - "refId": "A" - } - ], - "title": "Panel Title", - "transformations": [ - { - "id": "filterFieldsByName", - "options": { - "include": { - "names": [ - "Time", - "Value" - ] - } - } - } - ], - "type": "table" + "gridPos": { + "h": 7, + "w": 7, + "x": 13, + "y": 0 }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" + "id": 5, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false }, - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "blue", - "mode": "fixed" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 4, - "x": 20, - "y": 0 - }, - "id": 3, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.1.0-pre", - "targets": [ + "showHeader": true, + "sortBy": [ { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 1, - "refId": "A" + "desc": true, + "displayName": "Time" } - ], - "title": "Stats", - "transformations": [ - { - "id": "reduce", - "options": { - "reducers": [ - "lastNotNull", - "min", - "max", - "count" - ] - } - } - ], - "type": "stat" + ] }, - { - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } + "pluginVersion": "11.1.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 13, - "x": 0, - "y": 7 - }, - "id": 2, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "channel": "random-2s-stream", - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "live" - } - ], - "title": "Random 2s stream", - "type": "timeseries" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 7, - "x": 13, - "y": 7 - }, - "id": 6, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Time" - } - ] - }, - "pluginVersion": "11.1.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A" - } - ], - "title": "Panel Title", - "transformations": [ - { - "id": "filterFieldsByName", - "options": { - "include": { - "names": [ - "Time", - "Value" - ] - } + "panelId": 1, + "refId": "A" + } + ], + "title": "Panel Title", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": ["Time", "Value"] } } - ], - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "blue", - "mode": "fixed" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 4, - "x": 20, - "y": 7 - }, - "id": 4, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.1.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A" - } - ], - "title": "Stats", - "transformations": [ - { - "id": "reduce", - "options": { - "reducers": [ - "lastNotNull", - "min", - "max", - "count" - ] - } - } - ], - "type": "stat" - }, - { - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 13, - "x": 0, - "y": 14 - }, - "id": 7, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "channel": "random-labeled-stream", - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "live" - } - ], - "title": "Random Labeled streams", - "type": "timeseries" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 11, - "x": 13, - "y": 14 - }, - "id": 8, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Time" - } - ] - }, - "pluginVersion": "11.1.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 7, - "refId": "A" - } - ], - "title": "Labeled structure", - "type": "table" - } - ], - "schemaVersion": 39, - "tags": [ - "gdev", - "live-tests" - ], - "templating": { - "list": [] + } + ], + "type": "table" }, - "time": { - "from": "now-1m", - "to": "now" + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 20, + "y": 0 + }, + "id": 3, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 1, + "refId": "A" + } + ], + "title": "Stats", + "transformations": [ + { + "id": "reduce", + "options": { + "reducers": ["lastNotNull", "min", "max", "count"] + } + } + ], + "type": "stat" }, - "timeRangeUpdatedDuringEditOrView": false, - "timepicker": {}, - "timezone": "browser", - "title": "Live streaming examples", - "uid": "liveb94wbb", - "version": 9, - "weekStart": "" - } \ No newline at end of file + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 13, + "x": 0, + "y": 7 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "channel": "random-2s-stream", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "live" + } + ], + "title": "Random 2s stream", + "type": "timeseries" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 7, + "x": 13, + "y": 7 + }, + "id": 6, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Time" + } + ] + }, + "pluginVersion": "11.1.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "title": "Panel Title", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": ["Time", "Value"] + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 20, + "y": 7 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "title": "Stats", + "transformations": [ + { + "id": "reduce", + "options": { + "reducers": ["lastNotNull", "min", "max", "count"] + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 13, + "x": 0, + "y": 14 + }, + "id": 7, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "channel": "random-labeled-stream", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "live" + } + ], + "title": "Random Labeled streams", + "type": "timeseries" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 13, + "y": 14 + }, + "id": 8, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Time" + } + ] + }, + "pluginVersion": "11.1.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 7, + "refId": "A" + } + ], + "title": "Labeled structure", + "type": "table" + } + ], + "schemaVersion": 39, + "tags": ["gdev", "live-tests"], + "templating": { + "list": [] + }, + "time": { + "from": "now-1m", + "to": "now" + }, + "timeRangeUpdatedDuringEditOrView": false, + "timepicker": {}, + "timezone": "browser", + "title": "Live streaming examples", + "uid": "liveb94wbb", + "version": 9, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/migrations/migrations.json b/devenv/dev-dashboards/migrations/migrations.json index d872f4e6893..4c2160e1f26 100644 --- a/devenv/dev-dashboards/migrations/migrations.json +++ b/devenv/dev-dashboards/migrations/migrations.json @@ -195,7 +195,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "unit": "short" @@ -249,8 +251,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -288,7 +289,9 @@ } }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 11, "w": 8, @@ -309,8 +312,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A" } @@ -323,7 +325,9 @@ "bars": true, "dashLength": 10, "dashes": false, - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "unit": "short" @@ -377,8 +381,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"meta\": {\n \"typeVersion\": [\n 0,\n 0\n ],\n \"custom\": {\n \"customStat\": 10\n }\n },\n \"fields\": [\n {\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n },\n \"config\": {\n \"interval\": 3600000\n }\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"labels\": {\n \"pod\": \"A-pod\"\n },\n \"config\": {}\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1727107111901,\n 1727110711901,\n 1727114311901,\n 1727117911901,\n 1727121511901,\n 1727125111901\n ],\n [\n 1.907286825122581,\n 2.260951647569786,\n 1.887442338051216,\n 2.1526144400893514,\n 1.7287721375237766,\n 1.7262902137793208\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"A\",\n \"meta\": {\n \"typeVersion\": [\n 0,\n 0\n ],\n \"custom\": {\n \"customStat\": 10\n }\n },\n \"fields\": [\n {\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n },\n \"config\": {\n \"interval\": 3600000\n }\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"labels\": {\n \"pod\": \"A-pod1\"\n },\n \"config\": {}\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1727107111901,\n 1727110711901,\n 1727114311901,\n 1727117911901,\n 1727121511901,\n 1727125111901\n ],\n [\n 1.907286825122581,\n 1.589539045095202,\n 1.5914283506847613,\n 1.8976990616650726,\n 1.758223085999124,\n 2.2294649594813816\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"A\",\n \"meta\": {\n \"typeVersion\": [\n 0,\n 0\n ],\n \"custom\": {\n \"customStat\": 10\n }\n },\n \"fields\": [\n {\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n },\n \"config\": {\n \"interval\": 3600000\n }\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"labels\": {\n \"pod\": \"A-pod2\"\n },\n \"config\": {}\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1727107111901,\n 1727110711901,\n 1727114311901,\n 1727117911901,\n 1727121511901,\n 1727125111901\n ],\n [\n 1.907286825122581,\n 2.0914263380328766,\n 1.8164545521094575,\n 1.621111084665713,\n 1.3902653996444705,\n 1.482803315949775\n ]\n ]\n }\n }\n]", "refId": "A", @@ -397,9 +400,7 @@ "xaxis": { "mode": "series", "show": true, - "values": [ - "total" - ] + "values": ["total"] }, "yaxes": [ { @@ -420,7 +421,9 @@ } }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 11, "w": 8, @@ -441,8 +444,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A" } @@ -533,9 +535,7 @@ "xaxis": { "mode": "series", "show": true, - "values": [ - "total" - ] + "values": ["total"] }, "yaxes": [ { @@ -556,7 +556,9 @@ } }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 11, "w": 8, @@ -577,8 +579,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A" } @@ -591,7 +592,9 @@ "bars": true, "dashLength": 10, "dashes": false, - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "unit": "short" @@ -645,8 +648,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -686,7 +688,9 @@ } }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 11, "w": 8, @@ -707,8 +711,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A" } @@ -718,7 +721,9 @@ }, { "columns": [], - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fontSize": "100%", "gridPos": { "h": 10, @@ -732,9 +737,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true, @@ -757,11 +760,7 @@ { "alias": "", "align": "right", - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], + "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], "decimals": 2, "pattern": "/.*/", "thresholds": [], @@ -772,8 +771,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk_table" @@ -792,7 +790,9 @@ "type": "table-old" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 10, "w": 8, @@ -813,8 +813,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A" } @@ -825,12 +824,10 @@ { "colorBackground": false, "colorValue": true, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": { "type": "testdata" }, + "colors": ["#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a"], + "datasource": { + "type": "grafana-testdata-datasource" + }, "format": "areaF2", "gauge": { "maxValue": 100, @@ -880,8 +877,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A" } @@ -900,7 +896,9 @@ "valueName": "avg" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "mappings": [ @@ -945,9 +943,7 @@ "justifyMode": "auto", "orientation": "horizontal", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -959,8 +955,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A" } @@ -969,7 +964,9 @@ "type": "stat" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 8, "w": 8, @@ -990,8 +987,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A" } @@ -1000,7 +996,9 @@ "type": "text" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 10, "w": 16, @@ -1016,9 +1014,7 @@ }, "pieType": "pie", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -1031,8 +1027,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk_table" @@ -1050,7 +1045,9 @@ "type": "grafana-piechart-panel" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 10, "w": 8, @@ -1071,8 +1068,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A" } @@ -1083,14 +1079,9 @@ { "circleMaxSize": 30, "circleMinSize": 2, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], + "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "decimals": 0, "esMetric": "Count", @@ -1194,8 +1185,7 @@ { "csvFileName": "flight_info_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -1213,9 +1203,7 @@ { "id": "reduce", "options": { - "reducers": [ - "sum" - ] + "reducers": ["sum"] } } ], @@ -1225,7 +1213,9 @@ "valueName": "total" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 10, "w": 8, @@ -1246,8 +1236,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A" } @@ -1258,11 +1247,7 @@ ], "refresh": "", "schemaVersion": 39, - "tags": [ - "gdev", - "migrations", - "angular" - ], + "tags": ["gdev", "migrations", "angular"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-barchart/barchart-autosizing.json b/devenv/dev-dashboards/panel-barchart/barchart-autosizing.json index d484fabcc11..dce9167e212 100644 --- a/devenv/dev-dashboards/panel-barchart/barchart-autosizing.json +++ b/devenv/dev-dashboards/panel-barchart/barchart-autosizing.json @@ -29,7 +29,7 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -79,9 +79,7 @@ "barWidth": 1, "groupWidth": 0.82, "legend": { - "calcs": [ - "max" - ], + "calcs": ["max"], "displayMode": "list", "placement": "right" }, @@ -107,7 +105,7 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "description": "Should be smaller given the longer value", "fieldConfig": { "defaults": { @@ -159,9 +157,7 @@ "barWidth": 1, "groupWidth": 0.82, "legend": { - "calcs": [ - "max" - ], + "calcs": ["max"], "displayMode": "list", "placement": "right" }, @@ -187,7 +183,7 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -237,9 +233,7 @@ "barWidth": 1, "groupWidth": 0.89, "legend": { - "calcs": [ - "max" - ], + "calcs": ["max"], "displayMode": "list", "placement": "right" }, @@ -265,7 +259,7 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -315,9 +309,7 @@ "barWidth": 1, "groupWidth": 0.89, "legend": { - "calcs": [ - "max" - ], + "calcs": ["max"], "displayMode": "list", "placement": "right" }, @@ -424,7 +416,7 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -475,9 +467,7 @@ "barWidth": 1, "groupWidth": 0.82, "legend": { - "calcs": [ - "max" - ], + "calcs": ["max"], "displayMode": "list", "placement": "right" }, @@ -503,7 +493,7 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { "defaults": { @@ -554,9 +544,7 @@ "barWidth": 1, "groupWidth": 0.89, "legend": { - "calcs": [ - "max" - ], + "calcs": ["max"], "displayMode": "list", "placement": "right" }, @@ -584,12 +572,7 @@ ], "refresh": "", "schemaVersion": 36, - "tags": [ - "gdev", - "panel-tests", - "barchart", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "barchart", "graph-ng"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-barchart/barchart-label-rotation-skipping.json b/devenv/dev-dashboards/panel-barchart/barchart-label-rotation-skipping.json index ee99245953b..5695faa2c6f 100644 --- a/devenv/dev-dashboards/panel-barchart/barchart-label-rotation-skipping.json +++ b/devenv/dev-dashboards/panel-barchart/barchart-label-rotation-skipping.json @@ -1,319 +1,309 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 530, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "fillOpacity": 80, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineWidth": 1, - "scaleDistribution": { - "type": "linear" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "decmbytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 14, - "w": 11, - "x": 0, - "y": 0 - }, - "id": 2, - "maxDataPoints": 30, - "options": { - "barRadius": 0, - "barWidth": 0.97, - "groupWidth": 0.7, - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "orientation": "vertical", - "showValue": "auto", - "stacking": "none", - "tooltip": { - "mode": "single", - "sort": "none" - }, - "xTickLabelMaxLength": 6, - "xTickLabelRotation": 45, - "xTickLabelSpacing": 100 - }, - "targets": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"name\": \"label\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n },\n \"config\": {\n \"interval\": 600000\n }\n },\n {\n \"name\": \"A-series\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"labels\": {},\n \"config\": {}\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n \"acquisition\",\n \"extension\",\n \"conductor\",\n \"authorise\",\n \"architect\",\n \"illusion\",\n \"congress\",\n \"highlight\",\n \"partnership\",\n \"understanding\",\n \"disagreement\",\n \"personality\",\n \"commerce\",\n \"systematic\",\n \"hesitate\",\n \"business\",\n \"manufacture\",\n \"incredible\",\n \"constitutional\",\n \"prevalence\",\n \"professor\",\n \"entitlement\",\n \"cooperation\",\n \"sickness\",\n \"contrast\",\n \"reference\",\n \"audience\",\n \"discount\",\n \"apparatus\",\n \"disturbance\",\n \"automatic\",\n \"refrigerator\",\n \"elaborate\",\n \"sympathetic\",\n \"integration\",\n \"president\"\n ],\n [\n 306.78931659492116,\n 200.00696051101917,\n 164.90889283973593,\n 518.9385023737021,\n 999.9040675564702,\n 613.9689830172349,\n 773.2337077340269,\n 317.47395634701644,\n 748.3318338316539,\n 606.8039493787173,\n 426.27771317792866,\n 376.47735643253924,\n 66.30635081800493,\n 401.70654338415505,\n 108.86259550477234,\n 182.40284186231278,\n 867.7047958572101,\n 959.3957783599242,\n 396.7606089549935,\n 455.9625595614323,\n 685.4792456298062,\n 368.6567303946707,\n 157.06596562976327,\n 59.54120602048763,\n 406.72723615743973,\n 440.18247585615575,\n 516.0267558264891,\n 258.76006051667315,\n 952.966531725171,\n 554.8746357628739,\n 86.7279280805682,\n 781.2422516386563,\n 754.2723802427706,\n 435.0305712850233,\n 384.43181614983,\n 459.04164596738127\n ]\n ]\n }\n }\n]", - "refId": "A", - "scenarioId": "raw_frame" - } - ], - "title": "Panel Title", - "type": "barchart" + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 530, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource" }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "fillOpacity": 80, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineWidth": 0, - "scaleDistribution": { - "type": "linear" - }, - "thresholdsStyle": { - "mode": "off" - } + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" }, - "decimals": 7, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] - }, - "gridPos": { - "h": 14, - "w": 13, - "x": 11, - "y": 0 - }, - "id": 5, - "options": { - "barRadius": 0, - "barWidth": 1, - "groupWidth": 0.82, - "legend": { - "calcs": [ - "max" - ], - "displayMode": "list", - "placement": "right", - "showLegend": true - }, - "orientation": "horizontal", - "showValue": "auto", - "stacking": "none", - "text": {}, - "tooltip": { - "mode": "single", - "sort": "none" - }, - "xTickLabelRotation": 45, - "xTickLabelSpacing": 0 - }, - "targets": [ - { - "csvContent": "Name,Stat1,Stat2\nStockholm, 10, 15\nNew York, 19, -5\nLondon, 10, 1\nLong value, 15,10", - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "Auto sizing & auto show values", - "type": "barchart" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "fillOpacity": 80, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" }, - "lineWidth": 1, - "scaleDistribution": { - "type": "linear" - }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "decmbytes" + ] }, - "overrides": [] + "unit": "decmbytes" }, - "gridPos": { - "h": 18, - "w": 24, - "x": 0, - "y": 14 + "overrides": [] + }, + "gridPos": { + "h": 14, + "w": 11, + "x": 0, + "y": 0 + }, + "id": 2, + "maxDataPoints": 30, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 3, - "maxDataPoints": 20, - "options": { - "barRadius": 0, - "barWidth": 0.97, - "groupWidth": 0.7, - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true + "orientation": "vertical", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelMaxLength": 6, + "xTickLabelRotation": 45, + "xTickLabelSpacing": 100 + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" }, - "orientation": "horizontal", - "showValue": "auto", - "stacking": "none", - "tooltip": { - "mode": "single", - "sort": "none" + "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"name\": \"label\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n },\n \"config\": {\n \"interval\": 600000\n }\n },\n {\n \"name\": \"A-series\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"labels\": {},\n \"config\": {}\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n \"acquisition\",\n \"extension\",\n \"conductor\",\n \"authorise\",\n \"architect\",\n \"illusion\",\n \"congress\",\n \"highlight\",\n \"partnership\",\n \"understanding\",\n \"disagreement\",\n \"personality\",\n \"commerce\",\n \"systematic\",\n \"hesitate\",\n \"business\",\n \"manufacture\",\n \"incredible\",\n \"constitutional\",\n \"prevalence\",\n \"professor\",\n \"entitlement\",\n \"cooperation\",\n \"sickness\",\n \"contrast\",\n \"reference\",\n \"audience\",\n \"discount\",\n \"apparatus\",\n \"disturbance\",\n \"automatic\",\n \"refrigerator\",\n \"elaborate\",\n \"sympathetic\",\n \"integration\",\n \"president\"\n ],\n [\n 306.78931659492116,\n 200.00696051101917,\n 164.90889283973593,\n 518.9385023737021,\n 999.9040675564702,\n 613.9689830172349,\n 773.2337077340269,\n 317.47395634701644,\n 748.3318338316539,\n 606.8039493787173,\n 426.27771317792866,\n 376.47735643253924,\n 66.30635081800493,\n 401.70654338415505,\n 108.86259550477234,\n 182.40284186231278,\n 867.7047958572101,\n 959.3957783599242,\n 396.7606089549935,\n 455.9625595614323,\n 685.4792456298062,\n 368.6567303946707,\n 157.06596562976327,\n 59.54120602048763,\n 406.72723615743973,\n 440.18247585615575,\n 516.0267558264891,\n 258.76006051667315,\n 952.966531725171,\n 554.8746357628739,\n 86.7279280805682,\n 781.2422516386563,\n 754.2723802427706,\n 435.0305712850233,\n 384.43181614983,\n 459.04164596738127\n ]\n ]\n }\n }\n]", + "refId": "A", + "scenarioId": "raw_frame" + } + ], + "title": "Panel Title", + "type": "barchart" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" }, - "xTickLabelMaxLength": 5, - "xTickLabelRotation": 45, - "xTickLabelSpacing": 100 - }, - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMin": 0, + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "panelId": 2, - "refId": "A" + "lineWidth": 0, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 7, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] } - ], - "title": "Panel Title", - "type": "barchart" - } - ], - "schemaVersion": 37, - "tags": [ - "gdev", - "panel-tests", - "barchart", - "graph-ng" - ], - "templating": { - "list": [] + }, + "overrides": [] + }, + "gridPos": { + "h": 14, + "w": 13, + "x": 11, + "y": 0 + }, + "id": 5, + "options": { + "barRadius": 0, + "barWidth": 1, + "groupWidth": 0.82, + "legend": { + "calcs": ["max"], + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "orientation": "horizontal", + "showValue": "auto", + "stacking": "none", + "text": {}, + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 45, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "csvContent": "Name,Stat1,Stat2\nStockholm, 10, 15\nNew York, 19, -5\nLondon, 10, 1\nLong value, 15,10", + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Auto sizing & auto show values", + "type": "barchart" }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "BarChart - Label Rotation & Skipping", - "uid": "xCmMwXdVz", - "version": 20, - "weekStart": "" - } + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decmbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 18, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 3, + "maxDataPoints": 20, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "horizontal", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelMaxLength": 5, + "xTickLabelRotation": 45, + "xTickLabelSpacing": 100 + }, + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "title": "Panel Title", + "type": "barchart" + } + ], + "schemaVersion": 37, + "tags": ["gdev", "panel-tests", "barchart", "graph-ng"], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "BarChart - Label Rotation & Skipping", + "uid": "xCmMwXdVz", + "version": 20, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/panel-barchart/barchart-series-toggle.json b/devenv/dev-dashboards/panel-barchart/barchart-series-toggle.json index 8264f5a0315..d58523b07ea 100644 --- a/devenv/dev-dashboards/panel-barchart/barchart-series-toggle.json +++ b/devenv/dev-dashboards/panel-barchart/barchart-series-toggle.json @@ -24,8 +24,7 @@ "panels": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -104,8 +103,7 @@ { "csvContent": "Name,Stat1\nStockholm, 10\nNew York, 19\nLondon, 10\nNegative, 15\nLong value, 15", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -116,8 +114,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -196,8 +193,7 @@ { "csvContent": "Name,Stat1,Stat2\nStockholm, 10, 15\nNew York, 19, 5\nLondon, 10, 1\nNegative, 15, 5\nLong value, 15,10", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -208,8 +204,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -288,8 +283,7 @@ { "csvContent": "Name,Stat1,Stat2\nStockholm, 10, 15\nNew York, 19, 5\nLondon, 10, 1\nNegative, 15, 5\nLong value, 15,10", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -300,8 +294,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -380,8 +373,7 @@ { "csvContent": "Name,Stat1,Stat2\nStockholm, 10, 15\nNew York, 19, 5\nLondon, 10, 1\nNegative, 15, 5\nLong value, 15,10", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -392,12 +384,7 @@ } ], "schemaVersion": 39, - "tags": [ - "gdev", - "panel-tests", - "barchart", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "barchart", "graph-ng"], "templating": { "list": [] }, @@ -411,4 +398,4 @@ "uid": "adoero0hbka9sf", "version": 4, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-barchart/barchart-thresholds-mappings.json b/devenv/dev-dashboards/panel-barchart/barchart-thresholds-mappings.json index 81138940b74..7ff778a0353 100644 --- a/devenv/dev-dashboards/panel-barchart/barchart-thresholds-mappings.json +++ b/devenv/dev-dashboards/panel-barchart/barchart-thresholds-mappings.json @@ -28,7 +28,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -110,8 +112,7 @@ { "csvContent": "label,value\nx,3\na,10\nb,20\nc,30", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -121,7 +122,9 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -227,8 +230,7 @@ { "csvContent": "label,value\nx,3\na,10\nb,20\nc,30", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -238,7 +240,9 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -307,8 +311,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"name\": \"label\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"value\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"int64\",\n \"nullable\": true\n },\n \"config\": {\n \"thresholds\": {\n \"mode\": \"absolute\",\n \"steps\": [\n {\n \"color\": \"green\",\n \"value\": null\n },\n {\n \"color\": \"#EAB839\",\n \"value\": 10\n },\n {\n \"color\": \"red\",\n \"value\": 15\n },\n {\n \"color\": \"#6ED0E0\",\n \"value\": 25\n }\n ]\n }\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n \"x\",\n \"a\",\n \"b\",\n \"c\"\n ],\n [\n 3,\n 10,\n 20,\n 30\n ]\n ]\n }\n }\n]", "refId": "A", @@ -319,7 +322,9 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -389,8 +394,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"name\": \"label\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"value\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"int64\",\n \"nullable\": true\n },\n \"config\": {\n \"thresholds\": {\n \"mode\": \"absolute\",\n \"steps\": [\n {\n \"color\": \"green\",\n \"value\": null\n },\n {\n \"color\": \"#EAB839\",\n \"value\": 10\n },\n {\n \"color\": \"red\",\n \"value\": 15\n },\n {\n \"color\": \"#6ED0E0\",\n \"value\": 25\n }\n ]\n }\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n \"x\",\n \"a\",\n \"b\",\n \"c\"\n ],\n [\n 3,\n 10,\n 20,\n 30\n ]\n ]\n }\n }\n]", "refId": "A", @@ -401,7 +405,9 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -516,8 +522,7 @@ { "csvContent": "label,value\nx,3\na,10\nb,20\nc,30", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -527,7 +532,9 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -655,8 +662,7 @@ { "csvContent": "label,value\nx,3\na,10\nb,20\nc,30", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -666,7 +672,9 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -741,16 +749,14 @@ { "csvContent": "label,value\nx,3\na,10\nb,20\nc,30", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "max": 30, @@ -784,7 +790,9 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -913,8 +921,7 @@ { "csvContent": "label,value\nx,3\na,10\nb,20\nc,30", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -924,7 +931,9 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -997,8 +1006,7 @@ { "csvContent": "label,value\nx,3\na,10\nb,20\nc,30", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -1008,7 +1016,9 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1081,8 +1091,7 @@ { "csvContent": "label,value\nx,3\na,10\nb,20\nc,30", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -1092,7 +1101,9 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1165,8 +1176,7 @@ { "csvContent": "label,value\nx,3\na,10\nb,20\nc,30", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -1176,7 +1186,9 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1279,8 +1291,7 @@ { "csvContent": "label,value\nx,3\na,10\nb,20\nc,30", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -1291,12 +1302,7 @@ } ], "schemaVersion": 38, - "tags": [ - "gdev", - "panel-tests", - "barchart", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "barchart", "graph-ng"], "templating": { "list": [] }, @@ -1310,4 +1316,4 @@ "uid": "2I2uMSB7z", "version": 7, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-barchart/barchart-tooltips-legends.json b/devenv/dev-dashboards/panel-barchart/barchart-tooltips-legends.json index 7dc1b0ee08c..c99a5a7903b 100644 --- a/devenv/dev-dashboards/panel-barchart/barchart-tooltips-legends.json +++ b/devenv/dev-dashboards/panel-barchart/barchart-tooltips-legends.json @@ -163,8 +163,7 @@ { "csvContent": "id,column1,column2\r\nA,1,2", "datasource": { - "type": "testdata", - "uid": "o63ntNT4z" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -172,8 +171,7 @@ { "csvContent": "id,column1,column2\r\nB,2,1", "datasource": { - "type": "testdata", - "uid": "o63ntNT4z" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "B", @@ -318,8 +316,7 @@ { "csvContent": "id,column1,column2\r\nA,1,2", "datasource": { - "type": "testdata", - "uid": "o63ntNT4z" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -327,8 +324,7 @@ { "csvContent": "id,column1,column2\r\nB,2,1", "datasource": { - "type": "testdata", - "uid": "o63ntNT4z" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "B", @@ -358,7 +354,9 @@ "type": "row" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -451,8 +449,7 @@ { "csvContent": "id, field 1, field 2, field 3\na, 20, 30, 40\nb, 40, 50, 60", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -462,7 +459,9 @@ "type": "barchart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -555,8 +554,7 @@ { "csvContent": "id, field 1, field 2, field 3\na, 20, 30, 40\nb, 40, 50, 60", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -580,8 +578,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -640,12 +637,7 @@ "fullHighlight": false, "groupWidth": 0.7, "legend": { - "calcs": [ - "min", - "max", - "mean", - "variance" - ], + "calcs": ["min", "max", "mean", "variance"], "displayMode": "table", "placement": "bottom", "showLegend": true @@ -664,8 +656,7 @@ { "csvContent": "time, value\n100000, 10\n200000, 20\n300000, 30\n400000, 40", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -673,8 +664,7 @@ { "csvContent": "time, value\n100000, 500\n200000, 220\n300000, 10\n400000, 550", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "B", @@ -686,8 +676,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -779,8 +768,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"fields\": [\n {\n \"name\": \"TimeGenerated\",\n \"type\": \"time\",\n \"values\": [\n 1687200000000\n ]\n },\n {\n \"name\": \"Total\",\n \"type\": \"number\",\n \"values\": [\n 200\n ],\n \"labels\": {\n \"name\": \"A\"\n }\n },\n {\n \"name\": \"Total\",\n \"type\": \"number\",\n \"values\": [\n 180\n ],\n \"labels\": {\n \"name\": \"B\"\n }\n }\n ],\n \"refId\": \"A\",\n \"meta\": {\n \"custom\": {\n \"azureColumnTypes\": [\n \"string\",\n \"datetime\",\n \"long\"\n ]\n },\n \"type\": \"timeseries-wide\",\n \"typeVersion\": [\n 0,\n 0\n ]\n }\n }\n]", "refId": "A", @@ -792,8 +780,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -869,8 +856,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"config\": {},\n \"values\": [\n 1700488200000,\n 1700488500000,\n 1700488800000,\n 1700489100000,\n 1700489400000\n ]\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"config\": {\n \"displayNameFromDS\": \"f141\"\n },\n \"values\": [\n 11834,\n 26195,\n 27496,\n 21417\n ],\n \"labels\": {\n \"nodename\": \"z141\"\n }\n }\n ],\n \"refId\": \"A\",\n \"meta\": {\n \"type\": \"timeseries-multi\",\n \"typeVersion\": [\n 0,\n 0\n ]\n }\n },\n {\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"config\": {},\n \"values\": [\n 1700488200000,\n 1700488500000,\n 1700488800000,\n 1700489100000,\n 1700489400000\n ]\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"config\": {\n \"displayNameFromDS\": \"f131\"\n },\n \"values\": [\n 11042,\n 26646,\n 27120,\n 21508,\n 19905\n ],\n \"labels\": {\n \"nodename\": \"t131\"\n }\n }\n ],\n \"refId\": \"A\",\n \"meta\": {\n \"type\": \"timeseries-multi\",\n \"typeVersion\": [\n 0,\n 0\n ]\n }\n },\n {\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"config\": {},\n \"values\": [\n 1700488200000,\n 1700488500000,\n 1700488800000,\n 1700489100000,\n 1700489400000\n ]\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"config\": {\n \"displayNameFromDS\": \"f121\"\n },\n \"values\": [\n 12095,\n 26718,\n 26907,\n 21483,\n 20272\n ],\n \"labels\": {\n \"nodename\": \"k121\"\n }\n }\n ],\n \"refId\": \"A\",\n \"meta\": {\n \"type\": \"timeseries-multi\",\n \"typeVersion\": [\n 0,\n 0\n ]\n }\n },\n {\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"config\": {},\n \"values\": [\n 1700488200000,\n 1700488500000,\n 1700488800000,\n 1700489100000,\n 1700489400000\n ]\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"config\": {\n \"displayNameFromDS\": \"f111\"\n },\n \"values\": [\n 641,\n 1015,\n 791,\n 752,\n 758\n ],\n \"labels\": {\n \"nodename\": \"n111\"\n }\n }\n ],\n \"refId\": \"A\",\n \"meta\": {\n \"type\": \"timeseries-multi\",\n \"typeVersion\": [\n 0,\n 0\n ]\n }\n },\n {\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"config\": {},\n \"values\": [\n 1700488200000,\n 1700488500000,\n 1700488800000,\n 1700489100000,\n 1700489400000\n ]\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"config\": {\n \"displayNameFromDS\": \"f102\"\n },\n \"values\": [\n 101,\n 167,\n 205,\n 181,\n 172\n ],\n \"labels\": {\n \"nodename\": \"a102\"\n }\n }\n ],\n \"refId\": \"A\",\n \"meta\": {\n \"type\": \"timeseries-multi\",\n \"typeVersion\": [\n 0,\n 0\n ]\n }\n },\n {\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"config\": {},\n \"values\": [\n 1700488200000,\n 1700488500000,\n 1700488800000,\n 1700489100000,\n 1700489400000\n ]\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"config\": {\n \"displayNameFromDS\": \"f100\"\n },\n \"values\": [\n 89,\n 137,\n 161,\n 150,\n 161\n ],\n \"labels\": {\n \"nodename\": \"v100\"\n }\n }\n ],\n \"refId\": \"A\",\n \"meta\": {\n \"type\": \"timeseries-multi\",\n \"typeVersion\": [\n 0,\n 0\n ]\n }\n },\n {\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"config\": {},\n \"values\": [\n 1700488200000,\n 1700488500000,\n 1700488800000,\n 1700489100000,\n 1700489400000\n ]\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"config\": {\n \"displayNameFromDS\": \"d141\"\n },\n \"values\": [\n 11616,\n 26053,\n 25586,\n 21023,\n 19787\n ],\n \"labels\": {\n \"nodename\": \"e141\"\n }\n }\n ],\n \"refId\": \"A\",\n \"meta\": {\n \"type\": \"timeseries-multi\",\n \"typeVersion\": [\n 0,\n 0\n ]\n }\n },\n {\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"config\": {},\n \"values\": [\n 1700488200000,\n 1700488500000,\n 1700488800000,\n 1700489100000,\n 1700489400000\n ]\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"config\": {\n \"displayNameFromDS\": \"d131\"\n },\n \"values\": [\n 11682,\n 26851,\n 26985,\n 22475,\n 20852\n ],\n \"labels\": {\n \"nodename\": \"r131\"\n }\n }\n ],\n \"refId\": \"A\",\n \"meta\": {\n \"type\": \"timeseries-multi\",\n \"typeVersion\": [\n 0,\n 0\n ]\n }\n },\n {\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"config\": {},\n \"values\": [\n 1700488200000,\n 1700488500000,\n 1700488800000,\n 1700489100000,\n 1700489400000\n ]\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"config\": {\n \"displayNameFromDS\": \"d121\"\n },\n \"values\": [\n 12108,\n 26379,\n 25734,\n 20145,\n 19310\n ],\n \"labels\": {\n \"nodename\": \"g121\"\n }\n }\n ],\n \"refId\": \"A\",\n \"meta\": {\n \"type\": \"timeseries-multi\",\n \"typeVersion\": [\n 0,\n 0\n ]\n }\n },\n {\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"config\": {},\n \"values\": [\n 1700488200000,\n 1700488500000,\n 1700488800000,\n 1700489100000,\n 1700489400000\n ]\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"config\": {\n \"displayNameFromDS\": \"d111\"\n },\n \"values\": [\n 11254,\n 24739,\n 25406,\n 21239,\n 19426\n ],\n \"labels\": {\n \"nodename\": \"q111\"\n }\n }\n ],\n \"refId\": \"A\",\n \"meta\": {\n \"type\": \"timeseries-multi\",\n \"typeVersion\": [\n 0,\n 0\n ]\n }\n },\n {\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"config\": {},\n \"values\": [\n 1700488200000,\n 1700488500000,\n 1700488800000,\n 1700489100000,\n 1700489400000\n ]\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"config\": {\n \"displayNameFromDS\": \"d102\"\n },\n \"values\": [\n 168,\n 264,\n 288,\n 283,\n 267\n ],\n \"labels\": {\n \"nodename\": \"d102\"\n }\n }\n ],\n \"refId\": \"A\",\n \"meta\": {\n \"type\": \"timeseries-multi\",\n \"typeVersion\": [\n 0,\n 0\n ]\n }\n }\n]", "refId": "A", @@ -883,12 +869,7 @@ ], "refresh": "", "schemaVersion": 39, - "tags": [ - "gdev", - "panel-tests", - "barchart", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "barchart", "graph-ng"], "templating": { "list": [] }, @@ -902,4 +883,4 @@ "uid": "ea33320b-bd97-4fe1-a27c-24bc61a48b41", "version": 5, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-bargauge/bar_gauge_demo.json b/devenv/dev-dashboards/panel-bargauge/bar_gauge_demo.json index eda6ccfe996..ebfdf855286 100644 --- a/devenv/dev-dashboards/panel-bargauge/bar_gauge_demo.json +++ b/devenv/dev-dashboards/panel-bargauge/bar_gauge_demo.json @@ -19,7 +19,9 @@ "links": [], "panels": [ { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 7, "w": 24, @@ -149,7 +151,9 @@ "type": "bargauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 10, "w": 16, @@ -231,7 +235,9 @@ "type": "bargauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 10, "w": 6, @@ -328,7 +334,9 @@ "type": "bargauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 22, "w": 2, @@ -375,7 +383,9 @@ "type": "bargauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 12, "w": 22, @@ -509,7 +519,9 @@ "type": "bargauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 8, "w": 24, diff --git a/devenv/dev-dashboards/panel-bargauge/panel_tests_bar_gauge.json b/devenv/dev-dashboards/panel-bargauge/panel_tests_bar_gauge.json index cc8f600140f..d2f6271be2b 100644 --- a/devenv/dev-dashboards/panel-bargauge/panel_tests_bar_gauge.json +++ b/devenv/dev-dashboards/panel-bargauge/panel_tests_bar_gauge.json @@ -28,7 +28,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -79,9 +81,7 @@ "minVizWidth": 0, "orientation": "horizontal", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -93,8 +93,7 @@ { "alias": "Inside", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "H", "scenarioId": "csv_metric_values", @@ -103,16 +102,14 @@ { "alias": "Outhouse", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "random_walk" @@ -122,7 +119,9 @@ "type": "bargauge" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -173,9 +172,7 @@ "minVizWidth": 0, "orientation": "horizontal", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -187,8 +184,7 @@ { "alias": "Inside", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "H", "scenarioId": "csv_metric_values", @@ -197,32 +193,28 @@ { "alias": "Outhouse", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "random_walk" @@ -232,7 +224,9 @@ "type": "bargauge" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -283,9 +277,7 @@ "minVizWidth": 0, "orientation": "horizontal", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -297,8 +289,7 @@ { "alias": "Inside", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "H", "scenarioId": "csv_metric_values", @@ -307,32 +298,28 @@ { "alias": "Outhouse", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "random_walk" @@ -342,7 +329,9 @@ "type": "bargauge" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -393,9 +382,7 @@ "minVizWidth": 0, "orientation": "horizontal", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -407,8 +394,7 @@ { "alias": "Inside", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "H", "scenarioId": "csv_metric_values", @@ -417,32 +403,28 @@ { "alias": "Outhouse", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "random_walk" @@ -452,7 +434,9 @@ "type": "bargauge" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -503,9 +487,7 @@ "minVizWidth": 0, "orientation": "horizontal", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -517,8 +499,7 @@ { "alias": "Inside", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "H", "scenarioId": "csv_metric_values", @@ -527,32 +508,28 @@ { "alias": "Outhouse", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "random_walk" @@ -562,7 +539,9 @@ "type": "bargauge" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -613,9 +592,7 @@ "minVizWidth": 0, "orientation": "horizontal", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -627,8 +604,7 @@ { "alias": "Inside", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "H", "scenarioId": "csv_metric_values", @@ -637,32 +613,28 @@ { "alias": "Outhouse", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "random_walk" @@ -672,7 +644,9 @@ "type": "bargauge" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -718,9 +692,7 @@ "minVizWidth": 0, "orientation": "vertical", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -731,8 +703,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "E", "scenarioId": "csv_metric_values", @@ -740,24 +711,21 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "G", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "H", "scenarioId": "csv_metric_values", @@ -765,56 +733,49 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "I", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "J", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "K", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "L", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "M", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "N", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "O", "scenarioId": "random_walk" @@ -824,7 +785,9 @@ "type": "bargauge" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -870,9 +833,7 @@ "minVizWidth": 0, "orientation": "vertical", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -883,8 +844,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "H", "scenarioId": "csv_metric_values", @@ -892,104 +852,91 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "I", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "J", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "K", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "L", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "M", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "N", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "O", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "P", "scenarioId": "random_walk" }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "Q", "scenarioId": "random_walk" @@ -999,7 +946,9 @@ "type": "bargauge" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1044,9 +993,7 @@ "minVizWidth": 0, "orientation": "horizontal", "reduceOptions": { - "calcs": [ - "last" - ], + "calcs": ["last"], "fields": "", "values": false }, @@ -1057,8 +1004,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1069,7 +1015,9 @@ "type": "bargauge" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1114,9 +1062,7 @@ "minVizWidth": 0, "orientation": "vertical", "reduceOptions": { - "calcs": [ - "last" - ], + "calcs": ["last"], "fields": "", "values": false }, @@ -1127,8 +1073,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1139,7 +1084,9 @@ "type": "bargauge" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1184,9 +1131,7 @@ "minVizWidth": 0, "orientation": "vertical", "reduceOptions": { - "calcs": [ - "last" - ], + "calcs": ["last"], "fields": "", "values": false }, @@ -1197,8 +1142,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1209,7 +1153,9 @@ "type": "bargauge" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1259,9 +1205,7 @@ "minVizWidth": 0, "orientation": "vertical", "reduceOptions": { - "calcs": [ - "last" - ], + "calcs": ["last"], "fields": "", "values": false }, @@ -1272,8 +1216,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1284,7 +1227,9 @@ "type": "bargauge" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1334,9 +1279,7 @@ "minVizWidth": 0, "orientation": "vertical", "reduceOptions": { - "calcs": [ - "last" - ], + "calcs": ["last"], "fields": "", "values": false }, @@ -1347,8 +1290,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1361,10 +1303,7 @@ ], "revision": 1, "schemaVersion": 38, - "tags": [ - "gdev", - "panel-tests" - ], + "tags": ["gdev", "panel-tests"], "templating": { "list": [] }, @@ -1373,18 +1312,7 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "", "title": "Panel Tests - Bar Gauge", diff --git a/devenv/dev-dashboards/panel-candlestick/candlestick.json b/devenv/dev-dashboards/panel-candlestick/candlestick.json index 63a57ad394b..40c153d092c 100644 --- a/devenv/dev-dashboards/panel-candlestick/candlestick.json +++ b/devenv/dev-dashboards/panel-candlestick/candlestick.json @@ -29,7 +29,7 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -49,10 +49,7 @@ }, "lineInterpolation": "linear", "lineStyle": { - "dash": [ - 10, - 10 - ], + "dash": [10, 10], "fill": "dash" }, "lineWidth": 1, @@ -106,10 +103,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 0, - 20 - ], + "dash": [0, 20], "fill": "dot" } } @@ -174,7 +168,7 @@ "type": "candlestick" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -260,7 +254,7 @@ "type": "candlestick" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -346,7 +340,7 @@ "type": "candlestick" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -467,11 +461,7 @@ ], "refresh": false, "schemaVersion": 36, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-canvas/canvas-connection-examples.json b/devenv/dev-dashboards/panel-canvas/canvas-connection-examples.json index aedd6be604f..943ba719303 100644 --- a/devenv/dev-dashboards/panel-canvas/canvas-connection-examples.json +++ b/devenv/dev-dashboards/panel-canvas/canvas-connection-examples.json @@ -29,8 +29,7 @@ "panels": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2213,8 +2212,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -2225,7 +2223,9 @@ "type": "canvas" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -2843,8 +2843,7 @@ { "csvContent": "gateway, product-details, product-reviews, reviews-ratings, details-checkout\n100, 56, 44, 22, 28", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -2854,7 +2853,9 @@ "type": "canvas" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -3609,8 +3610,7 @@ { "csvContent": "database_server, server_database, server_region, region_server, database2_server, server_database2\n10, 53, 35, 12, 22, 81", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -3623,11 +3623,7 @@ "refresh": "", "revision": 1, "schemaVersion": 39, - "tags": [ - "gdev", - "panel-tests", - "canvas" - ], + "tags": ["gdev", "panel-tests", "canvas"], "templating": { "list": [] }, @@ -3642,4 +3638,4 @@ "uid": "Pu8lwQAVz", "version": 6, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-canvas/canvas-datalinks.json b/devenv/dev-dashboards/panel-canvas/canvas-datalinks.json index 7ecbdd30838..5ec2bd179a6 100644 --- a/devenv/dev-dashboards/panel-canvas/canvas-datalinks.json +++ b/devenv/dev-dashboards/panel-canvas/canvas-datalinks.json @@ -1,3449 +1,2264 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "description": "", - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "links": [], - "panels": [ - { - "datasource": { - "type": "grafana", - "uid": "grafana" + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana", + "uid": "grafana" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "A-hehwzd" }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "A-hehwzd" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "A-series data link", - "url": "http://localhost:3000/d/dddouk2ygsb9cc/6114e28a-4041-5fbd-878f-b98718a90c4d?${__url_time_range}" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Count (transformation)" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "Count data link", - "url": "http://localhost:3000/d/dddouk2ygsb9cc/6114e28a-4041-5fbd-878f-b98718a90c4d${__data.fields.A-series}" - } - ] - } - ] - } + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "A-series data link", + "url": "http://localhost:3000/d/dddouk2ygsb9cc/6114e28a-4041-5fbd-878f-b98718a90c4d?${__url_time_range}" + } ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Count (transformation)" }, - "gridPos": { - "h": 30, - "w": 24, - "x": 0, - "y": 0 + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Count data link", + "url": "http://localhost:3000/d/dddouk2ygsb9cc/6114e28a-4041-5fbd-878f-b98718a90c4d${__data.fields.A-series}" + } + ] + } + ] + } + ] + }, + "gridPos": { + "h": 30, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "infinitePan": false, + "inlineEditing": false, + "panZoom": false, + "root": { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" }, - "id": 1, - "options": { - "infinitePan": false, - "inlineEditing": false, - "panZoom": false, - "root": { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - }, - "width": 0 - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "elements": [ - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "rgb(204, 204, 220)" - }, - "size": 24, - "text": { - "fixed": "Metric Value" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 1", - "placement": { - "height": 50, - "left": 38, - "top": 23, - "width": 144 - }, - "type": "text" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "size": 20, - "text": { - "field": "A-hehwzd", - "fixed": "", - "mode": "field" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 2", - "placement": { - "height": 50, - "left": 16, - "top": 91, - "width": 188 - }, - "type": "metric-value" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "field": "A-hehwzd", - "fixed": "#000000" - }, - "size": 20, - "text": { - "fixed": "Text color", - "mode": "fixed" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 3", - "placement": { - "height": 50, - "left": 16, - "top": 170, - "width": 188 - }, - "type": "metric-value" - }, - { - "background": { - "color": { - "fixed": "transparent" - }, - "image": { - "field": "Count (transformation)", - "mode": "field" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "text" - }, - "size": 20, - "text": { - "fixed": "Background image", - "mode": "fixed" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 4", - "placement": { - "height": 50, - "left": 16, - "top": 249, - "width": 188 - }, - "type": "metric-value" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "field": "A-hehwzd", - "fixed": "dark-green" - }, - "width": 2 - }, - "config": { - "align": "center", - "color": { - "fixed": "text" - }, - "size": 20, - "text": { - "fixed": "Border", - "mode": "fixed" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 5", - "placement": { - "height": 50, - "left": 16, - "top": 328, - "width": 188 - }, - "type": "metric-value" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "text" - }, - "size": 16, - "text": { - "field": "A-hehwzd", - "mode": "field" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 6", - "placement": { - "height": 50, - "left": 262, - "top": 91, - "width": 188 - }, - "type": "text" - }, - { - "background": { - "color": { - "fixed": "transparent" - }, - "image": { - "fixed": "" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "field": "A-hehwzd", - "fixed": "rgb(204, 204, 220)" - }, - "size": 16, - "text": { - "fixed": "Text color" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 7", - "placement": { - "height": 50, - "left": 262, - "top": 170, - "width": 188 - }, - "type": "text" - }, - { - "background": { - "color": { - "fixed": "transparent" - }, - "image": { - "field": "Count (transformation)", - "mode": "field" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "rgb(204, 204, 220)" - }, - "size": 16, - "text": { - "fixed": "Background image" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 8", - "placement": { - "height": 50, - "left": 262, - "top": 249, - "width": 188 - }, - "type": "text" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "field": "A-hehwzd", - "fixed": "dark-green" - }, - "width": 2 - }, - "config": { - "align": "center", - "color": { - "fixed": "rgb(204, 204, 220)" - }, - "size": 16, - "text": { - "fixed": "Border" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 9", - "placement": { - "height": 50, - "left": 262, - "top": 328, - "width": 188 - }, - "type": "text" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "rgb(204, 204, 220)" - }, - "size": 24, - "text": { - "fixed": "Text" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 10", - "placement": { - "height": 50, - "left": 284, - "top": 23, - "width": 144 - }, - "type": "text" - }, - { - "background": { - "fixed": "#D9D9D9" - }, - "border": { - "color": { - "fixed": "transparent" - }, - "width": 1 - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "text": { - "field": "A-hehwzd", - "mode": "field" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 11", - "placement": { - "height": 50, - "left": 530, - "top": 91, - "width": 188 - }, - "type": "ellipse" - }, - { - "background": { - "fixed": "#D9D9D9" - }, - "border": { - "color": { - "fixed": "transparent" - }, - "width": 1 - }, - "config": { - "align": "center", - "color": { - "field": "A-hehwzd", - "fixed": "#000000" - }, - "text": { - "fixed": "Text color" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 12", - "placement": { - "height": 50, - "left": 530, - "top": 170, - "width": 188 - }, - "type": "ellipse" - }, - { - "background": { - "fixed": "#D9D9D9", - "image": { - "field": "Count (transformation)", - "fixed": "", - "mode": "field" - } - }, - "border": { - "color": { - "fixed": "transparent" - }, - "width": 1 - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "text": { - "fixed": "Background image" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 13", - "placement": { - "height": 50, - "left": 530, - "top": 248.33333333333334, - "width": 187.99997965494794 - }, - "type": "ellipse" - }, - { - "background": { - "fixed": "#D9D9D9" - }, - "border": { - "color": { - "field": "A-hehwzd", - "fixed": "transparent" - }, - "radius": 0, - "width": 2 - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "text": { - "fixed": "Border" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 14", - "placement": { - "height": 50, - "left": 530, - "top": 328.33333333333337, - "width": 187.99997965494794 - }, - "type": "ellipse" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "rgb(204, 204, 220)" - }, - "size": 24, - "text": { - "fixed": "Ellipse" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 15", - "placement": { - "height": 50, - "left": 552, - "top": 23, - "width": 144 - }, - "type": "text" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "text": { - "field": "A-hehwzd", - "mode": "field" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 16", - "placement": { - "height": 50, - "left": 798, - "top": 91, - "width": 188 - }, - "type": "rectangle" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "field": "A-hehwzd", - "fixed": "#000000" - }, - "text": { - "fixed": "Text color" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 17", - "placement": { - "height": 50, - "left": 798, - "top": 170, - "width": 188 - }, - "type": "rectangle" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - }, - "image": { - "field": "Count (transformation)", - "mode": "field" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "text": { - "fixed": "Background image" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 18", - "placement": { - "height": 50, - "left": 798.3333333333334, - "top": 248.33333333333334, - "width": 187.99997965494794 - }, - "type": "rectangle" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "field": "A-hehwzd", - "fixed": "dark-green" - }, - "width": 2 - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "text": { - "fixed": "Border" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 19", - "placement": { - "height": 50, - "left": 798.3333333333334, - "top": 328.33333333333337, - "width": 187.99235026041669 - }, - "type": "rectangle" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "rgb(204, 204, 220)" - }, - "size": 24, - "text": { - "fixed": "Rectangle" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 20", - "placement": { - "height": 50, - "left": 820, - "top": 23, - "width": 144 - }, - "type": "text" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "fill": { - "fixed": "#D9D9D9" - }, - "path": { - "field": "A-hehwzd", - "fixed": "img/icons/unicons/question-circle.svg", - "mode": "field" - } - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 21", - "placement": { - "height": 50, - "left": 1066, - "top": 91, - "width": 188 - }, - "type": "icon" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "fill": { - "field": "A-hehwzd", - "fixed": "#D9D9D9" - }, - "path": { - "fixed": "img/icons/unicons/question-circle.svg", - "mode": "fixed" - } - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 22", - "placement": { - "height": 50, - "left": 1066, - "top": 170, - "width": 188 - }, - "type": "icon" - }, - { - "background": { - "color": { - "fixed": "transparent" - }, - "image": { - "field": "Count (transformation)", - "mode": "field" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "fill": { - "fixed": "#D9D9D9" - }, - "path": { - "fixed": "img/icons/unicons/question-circle.svg", - "mode": "fixed" - } - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 23", - "placement": { - "height": 50, - "left": 1066, - "top": 249, - "width": 188 - }, - "type": "icon" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "field": "A-hehwzd", - "fixed": "dark-green" - }, - "width": 2 - }, - "config": { - "fill": { - "fixed": "#D9D9D9" - }, - "path": { - "fixed": "img/icons/unicons/question-circle.svg", - "mode": "fixed" - } - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 24", - "placement": { - "height": 50, - "left": 1066, - "top": 328, - "width": 188 - }, - "type": "icon" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "rgb(204, 204, 220)" - }, - "size": 24, - "text": { - "fixed": "Icon" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 25", - "placement": { - "height": 50, - "left": 1088, - "top": 23, - "width": 144 - }, - "type": "text" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "statusColor": { - "field": "A-hehwzd" - }, - "type": "Single" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 26", - "placement": { - "height": 90, - "left": 65, - "top": 516, - "width": 90 - }, - "type": "server" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "field": "A-hehwzd", - "fixed": "dark-green" - }, - "width": 2 - }, - "config": { - "type": "Single" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 29", - "placement": { - "height": 90, - "left": 65, - "top": 870, - "width": 90 - }, - "type": "server" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "rgb(204, 204, 220)" - }, - "size": 24, - "text": { - "fixed": "Server" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 30", - "placement": { - "height": 50, - "left": 38, - "top": 438, - "width": 144 - }, - "type": "text" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "bulbColor": { - "field": "A-hehwzd" - }, - "statusColor": { - "fixed": "transparent" - }, - "type": "Single" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 31", - "placement": { - "height": 90, - "left": 65, - "top": 634, - "width": 90 - }, - "type": "server" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "blinkRate": { - "field": "A-hehwzd" - }, - "bulbColor": { - "fixed": "#000000" - }, - "statusColor": { - "fixed": "transparent" - }, - "type": "Single" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 32", - "placement": { - "height": 90, - "left": 65, - "top": 752, - "width": 90 - }, - "type": "server" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "rpm": { - "field": "A-hehwzd" - }, - "statusColor": { - "field": "A-hehwzd" - }, - "type": "Single" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 33", - "placement": { - "height": 55, - "left": 329, - "top": 516, - "width": 55 - }, - "type": "windTurbine" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "rgb(204, 204, 220)" - }, - "size": 24, - "text": { - "fixed": "Wind Turbine" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 35", - "placement": { - "height": 50, - "left": 270, - "top": 438, - "width": 172 - }, - "type": "text" - }, - { - "background": { - "color": { - "field": "A-hehwzd", - "fixed": "transparent" - }, - "image": { - "field": "Count (transformation)", - "mode": "field" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "bulbColor": { - "field": "A-hehwzd" - }, - "statusColor": { - "fixed": "transparent" - }, - "type": "Single" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 36", - "placement": { - "height": 55, - "left": 329, - "top": 633, - "width": 55 - }, - "type": "windTurbine" - }, - { - "background": { - "color": { - "field": "Count (transformation)", - "fixed": "transparent" - }, - "image": { - "field": "A-hehwzd", - "mode": "field" - } - }, - "border": { - "color": { - "fixed": "dark-green" - }, - "width": 0 - }, - "config": { - "type": "Single" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 38", - "placement": { - "height": 90, - "left": 65, - "top": 988, - "width": 90 - }, - "type": "server" - }, - { - "background": { - "color": { - "fixed": "transparent" - }, - "image": { - "field": "", - "mode": "field" - } - }, - "border": { - "color": { - "field": "A-hehwzd", - "fixed": "dark-green" - }, - "width": 1 - }, - "config": { - "bulbColor": { - "field": "A-hehwzd" - }, - "statusColor": { - "fixed": "transparent" - }, - "type": "Single" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 37", - "placement": { - "height": 55, - "left": 329, - "top": 752, - "width": 55 - }, - "type": "windTurbine" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "rgb(204, 204, 220)" - }, - "size": 24, - "text": { - "fixed": "Cloud" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 39", - "placement": { - "height": 50, - "left": 530, - "top": 438, - "width": 172 - }, - "type": "text" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "text": { - "field": "A-hehwzd", - "mode": "field" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 40", - "placement": { - "height": 50, - "left": 530, - "top": 517, - "width": 188 - }, - "type": "cloud" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "field": "A-hehwzd", - "fixed": "#000000" - }, - "text": { - "fixed": "Text color" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 41", - "placement": { - "height": 50, - "left": 530, - "top": 596, - "width": 188 - }, - "type": "cloud" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - }, - "image": { - "field": "Count (transformation)", - "mode": "field" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "left", - "color": { - "fixed": "#000000" - }, - "text": { - "fixed": "Background image" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 42", - "placement": { - "height": 50, - "left": 530, - "top": 675, - "width": 188 - }, - "type": "cloud" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "field": "A-hehwzd", - "fixed": "dark-green" - }, - "width": 5 - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "text": { - "fixed": "Border" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 43", - "placement": { - "height": 50, - "left": 530, - "top": 754, - "width": 188 - }, - "type": "cloud" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "rgb(204, 204, 220)" - }, - "size": 24, - "text": { - "fixed": "Parallelogram" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 44", - "placement": { - "height": 50, - "left": 806, - "top": 438, - "width": 172 - }, - "type": "text" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "text": { - "field": "A-hehwzd", - "fixed": "", - "mode": "field" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 45", - "placement": { - "height": 50, - "left": 798, - "top": 516, - "width": 188 - }, - "type": "parallelogram" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "field": "A-hehwzd", - "fixed": "#000000" - }, - "text": { - "fixed": "Text color" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 46", - "placement": { - "height": 50, - "left": 798, - "top": 595, - "width": 188 - }, - "type": "parallelogram" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - }, - "image": { - "field": "Count (transformation)", - "mode": "field" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "left", - "color": { - "fixed": "#000000" - }, - "text": { - "fixed": "Background image" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 47", - "placement": { - "height": 50, - "left": 798, - "top": 674, - "width": 188 - }, - "type": "parallelogram" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "field": "A-hehwzd", - "fixed": "dark-green" - }, - "width": 5 - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "text": { - "fixed": "Border" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 48", - "placement": { - "height": 50, - "left": 798, - "top": 753, - "width": 188 - }, - "type": "parallelogram" - }, - { - "background": { - "color": { - "fixed": "transparent" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "rgb(204, 204, 220)" - }, - "size": 24, - "text": { - "fixed": "Triangle" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 49", - "placement": { - "height": 50, - "left": 1074, - "top": 438, - "width": 172 - }, - "type": "text" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "text": { - "field": "A-hehwzd", - "fixed": "", - "mode": "field" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 50", - "placement": { - "height": 50, - "left": 1066, - "top": 516, - "width": 188 - }, - "type": "triangle" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "center", - "color": { - "field": "A-hehwzd", - "fixed": "#000000" - }, - "text": { - "fixed": "Text color" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 51", - "placement": { - "height": 50, - "left": 1066, - "top": 595, - "width": 188 - }, - "type": "triangle" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - }, - "image": { - "field": "Count (transformation)", - "mode": "field" - } - }, - "border": { - "color": { - "fixed": "dark-green" - } - }, - "config": { - "align": "left", - "color": { - "fixed": "#000000" - }, - "text": { - "fixed": "Background image" - }, - "valign": "bottom" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 52", - "placement": { - "height": 50, - "left": 1066, - "top": 674, - "width": 188 - }, - "type": "triangle" - }, - { - "background": { - "color": { - "fixed": "#D9D9D9" - } - }, - "border": { - "color": { - "field": "A-hehwzd", - "fixed": "dark-green" - }, - "width": 5 - }, - "config": { - "align": "center", - "color": { - "fixed": "#000000" - }, - "text": { - "fixed": "Border" - }, - "valign": "middle" - }, - "constraint": { - "horizontal": "left", - "vertical": "top" - }, - "name": "Element 53", - "placement": { - "height": 50, - "left": 1066, - "top": 753, - "width": 188 - }, - "type": "triangle" - } - ], - "name": "Element 1708700648848", - "placement": { - "height": 100, - "left": 0, - "rotation": 0, - "top": 0, - "width": 100 - }, - "type": "frame" + "width": 0 + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "elements": [ + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "rgb(204, 204, 220)" }, - "showAdvancedTypes": true + "size": 24, + "text": { + "fixed": "Metric Value" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 1", + "placement": { + "height": 50, + "left": 38, + "top": 23, + "width": 144 + }, + "type": "text" }, - "pluginVersion": "11.1.0-pre", - "targets": [ - { - "datasource": { - "type": "grafana", - "uid": "grafana" + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "size": 20, + "text": { + "field": "A-hehwzd", + "fixed": "", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 2", + "placement": { + "height": 50, + "left": 16, + "top": 91, + "width": 188 + }, + "type": "metric-value" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "field": "A-hehwzd", + "fixed": "#000000" + }, + "size": 20, + "text": { + "fixed": "Text color", + "mode": "fixed" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 3", + "placement": { + "height": 50, + "left": 16, + "top": 170, + "width": 188 + }, + "type": "metric-value" + }, + { + "background": { + "color": { + "fixed": "transparent" + }, + "image": { + "field": "Count (transformation)", + "mode": "field" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "text" + }, + "size": 20, + "text": { + "fixed": "Background image", + "mode": "fixed" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 4", + "placement": { + "height": 50, + "left": 16, + "top": 249, + "width": 188 + }, + "type": "metric-value" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "field": "A-hehwzd", + "fixed": "dark-green" + }, + "width": 2 + }, + "config": { + "align": "center", + "color": { + "fixed": "text" + }, + "size": 20, + "text": { + "fixed": "Border", + "mode": "fixed" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 5", + "placement": { + "height": 50, + "left": 16, + "top": 328, + "width": 188 + }, + "type": "metric-value" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "text" + }, + "size": 16, + "text": { + "field": "A-hehwzd", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 6", + "placement": { + "height": 50, + "left": 262, + "top": 91, + "width": 188 + }, + "type": "text" + }, + { + "background": { + "color": { + "fixed": "transparent" + }, + "image": { + "fixed": "" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "field": "A-hehwzd", + "fixed": "rgb(204, 204, 220)" + }, + "size": 16, + "text": { + "fixed": "Text color" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 7", + "placement": { + "height": 50, + "left": 262, + "top": 170, + "width": 188 + }, + "type": "text" + }, + { + "background": { + "color": { + "fixed": "transparent" + }, + "image": { + "field": "Count (transformation)", + "mode": "field" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "rgb(204, 204, 220)" + }, + "size": 16, + "text": { + "fixed": "Background image" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 8", + "placement": { + "height": 50, + "left": 262, + "top": 249, + "width": 188 + }, + "type": "text" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "field": "A-hehwzd", + "fixed": "dark-green" + }, + "width": 2 + }, + "config": { + "align": "center", + "color": { + "fixed": "rgb(204, 204, 220)" + }, + "size": 16, + "text": { + "fixed": "Border" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 9", + "placement": { + "height": 50, + "left": 262, + "top": 328, + "width": 188 + }, + "type": "text" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "rgb(204, 204, 220)" + }, + "size": 24, + "text": { + "fixed": "Text" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 10", + "placement": { + "height": 50, + "left": 284, + "top": 23, + "width": 144 + }, + "type": "text" + }, + { + "background": { + "fixed": "#D9D9D9" + }, + "border": { + "color": { + "fixed": "transparent" + }, + "width": 1 + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "text": { + "field": "A-hehwzd", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 11", + "placement": { + "height": 50, + "left": 530, + "top": 91, + "width": 188 + }, + "type": "ellipse" + }, + { + "background": { + "fixed": "#D9D9D9" + }, + "border": { + "color": { + "fixed": "transparent" + }, + "width": 1 + }, + "config": { + "align": "center", + "color": { + "field": "A-hehwzd", + "fixed": "#000000" + }, + "text": { + "fixed": "Text color" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 12", + "placement": { + "height": 50, + "left": 530, + "top": 170, + "width": 188 + }, + "type": "ellipse" + }, + { + "background": { + "fixed": "#D9D9D9", + "image": { + "field": "Count (transformation)", + "fixed": "", + "mode": "field" + } + }, + "border": { + "color": { + "fixed": "transparent" + }, + "width": 1 + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "text": { + "fixed": "Background image" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 13", + "placement": { + "height": 50, + "left": 530, + "top": 248.33333333333334, + "width": 187.99997965494794 + }, + "type": "ellipse" + }, + { + "background": { + "fixed": "#D9D9D9" + }, + "border": { + "color": { + "field": "A-hehwzd", + "fixed": "transparent" + }, + "radius": 0, + "width": 2 + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "text": { + "fixed": "Border" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 14", + "placement": { + "height": 50, + "left": 530, + "top": 328.33333333333337, + "width": 187.99997965494794 + }, + "type": "ellipse" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "rgb(204, 204, 220)" + }, + "size": 24, + "text": { + "fixed": "Ellipse" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 15", + "placement": { + "height": 50, + "left": 552, + "top": 23, + "width": 144 + }, + "type": "text" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "text": { + "field": "A-hehwzd", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 16", + "placement": { + "height": 50, + "left": 798, + "top": 91, + "width": 188 + }, + "type": "rectangle" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "field": "A-hehwzd", + "fixed": "#000000" + }, + "text": { + "fixed": "Text color" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 17", + "placement": { + "height": 50, + "left": 798, + "top": 170, + "width": 188 + }, + "type": "rectangle" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + }, + "image": { + "field": "Count (transformation)", + "mode": "field" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "text": { + "fixed": "Background image" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 18", + "placement": { + "height": 50, + "left": 798.3333333333334, + "top": 248.33333333333334, + "width": 187.99997965494794 + }, + "type": "rectangle" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "field": "A-hehwzd", + "fixed": "dark-green" + }, + "width": 2 + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "text": { + "fixed": "Border" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 19", + "placement": { + "height": 50, + "left": 798.3333333333334, + "top": 328.33333333333337, + "width": 187.99235026041669 + }, + "type": "rectangle" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "rgb(204, 204, 220)" + }, + "size": 24, + "text": { + "fixed": "Rectangle" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 20", + "placement": { + "height": 50, + "left": 820, + "top": 23, + "width": 144 + }, + "type": "text" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "fill": { + "fixed": "#D9D9D9" + }, + "path": { + "field": "A-hehwzd", + "fixed": "img/icons/unicons/question-circle.svg", + "mode": "field" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 21", + "placement": { + "height": 50, + "left": 1066, + "top": 91, + "width": 188 + }, + "type": "icon" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "fill": { + "field": "A-hehwzd", + "fixed": "#D9D9D9" + }, + "path": { + "fixed": "img/icons/unicons/question-circle.svg", + "mode": "fixed" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 22", + "placement": { + "height": 50, + "left": 1066, + "top": 170, + "width": 188 + }, + "type": "icon" + }, + { + "background": { + "color": { + "fixed": "transparent" + }, + "image": { + "field": "Count (transformation)", + "mode": "field" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "fill": { + "fixed": "#D9D9D9" + }, + "path": { + "fixed": "img/icons/unicons/question-circle.svg", + "mode": "fixed" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 23", + "placement": { + "height": 50, + "left": 1066, + "top": 249, + "width": 188 + }, + "type": "icon" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "field": "A-hehwzd", + "fixed": "dark-green" + }, + "width": 2 + }, + "config": { + "fill": { + "fixed": "#D9D9D9" + }, + "path": { + "fixed": "img/icons/unicons/question-circle.svg", + "mode": "fixed" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 24", + "placement": { + "height": 50, + "left": 1066, + "top": 328, + "width": 188 + }, + "type": "icon" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "rgb(204, 204, 220)" + }, + "size": 24, + "text": { + "fixed": "Icon" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 25", + "placement": { + "height": 50, + "left": 1088, + "top": 23, + "width": 144 + }, + "type": "text" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "statusColor": { + "field": "A-hehwzd" + }, + "type": "Single" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 26", + "placement": { + "height": 90, + "left": 65, + "top": 516, + "width": 90 + }, + "type": "server" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "field": "A-hehwzd", + "fixed": "dark-green" + }, + "width": 2 + }, + "config": { + "type": "Single" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 29", + "placement": { + "height": 90, + "left": 65, + "top": 870, + "width": 90 + }, + "type": "server" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "rgb(204, 204, 220)" + }, + "size": 24, + "text": { + "fixed": "Server" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 30", + "placement": { + "height": 50, + "left": 38, + "top": 438, + "width": 144 + }, + "type": "text" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "bulbColor": { + "field": "A-hehwzd" + }, + "statusColor": { + "fixed": "transparent" + }, + "type": "Single" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 31", + "placement": { + "height": 90, + "left": 65, + "top": 634, + "width": 90 + }, + "type": "server" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "blinkRate": { + "field": "A-hehwzd" + }, + "bulbColor": { + "fixed": "#000000" + }, + "statusColor": { + "fixed": "transparent" + }, + "type": "Single" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 32", + "placement": { + "height": 90, + "left": 65, + "top": 752, + "width": 90 + }, + "type": "server" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "rpm": { + "field": "A-hehwzd" + }, + "statusColor": { + "field": "A-hehwzd" + }, + "type": "Single" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 33", + "placement": { + "height": 55, + "left": 329, + "top": 516, + "width": 55 + }, + "type": "windTurbine" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "rgb(204, 204, 220)" + }, + "size": 24, + "text": { + "fixed": "Wind Turbine" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 35", + "placement": { + "height": 50, + "left": 270, + "top": 438, + "width": 172 + }, + "type": "text" + }, + { + "background": { + "color": { + "field": "A-hehwzd", + "fixed": "transparent" + }, + "image": { + "field": "Count (transformation)", + "mode": "field" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "bulbColor": { + "field": "A-hehwzd" + }, + "statusColor": { + "fixed": "transparent" + }, + "type": "Single" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 36", + "placement": { + "height": 55, + "left": 329, + "top": 633, + "width": 55 + }, + "type": "windTurbine" + }, + { + "background": { + "color": { + "field": "Count (transformation)", + "fixed": "transparent" + }, + "image": { + "field": "A-hehwzd", + "mode": "field" + } + }, + "border": { + "color": { + "fixed": "dark-green" + }, + "width": 0 + }, + "config": { + "type": "Single" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 38", + "placement": { + "height": 90, + "left": 65, + "top": 988, + "width": 90 + }, + "type": "server" + }, + { + "background": { + "color": { + "fixed": "transparent" + }, + "image": { + "field": "", + "mode": "field" + } + }, + "border": { + "color": { + "field": "A-hehwzd", + "fixed": "dark-green" + }, + "width": 1 + }, + "config": { + "bulbColor": { + "field": "A-hehwzd" + }, + "statusColor": { + "fixed": "transparent" + }, + "type": "Single" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 37", + "placement": { + "height": 55, + "left": 329, + "top": 752, + "width": 55 + }, + "type": "windTurbine" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "rgb(204, 204, 220)" + }, + "size": 24, + "text": { + "fixed": "Cloud" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 39", + "placement": { + "height": 50, + "left": 530, + "top": 438, + "width": 172 + }, + "type": "text" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "text": { + "field": "A-hehwzd", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 40", + "placement": { + "height": 50, + "left": 530, + "top": 517, + "width": 188 + }, + "type": "cloud" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "field": "A-hehwzd", + "fixed": "#000000" + }, + "text": { + "fixed": "Text color" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 41", + "placement": { + "height": 50, + "left": 530, + "top": 596, + "width": 188 + }, + "type": "cloud" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + }, + "image": { + "field": "Count (transformation)", + "mode": "field" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "left", + "color": { + "fixed": "#000000" + }, + "text": { + "fixed": "Background image" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 42", + "placement": { + "height": 50, + "left": 530, + "top": 675, + "width": 188 + }, + "type": "cloud" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "field": "A-hehwzd", + "fixed": "dark-green" + }, + "width": 5 + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "text": { + "fixed": "Border" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 43", + "placement": { + "height": 50, + "left": 530, + "top": 754, + "width": 188 + }, + "type": "cloud" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "rgb(204, 204, 220)" + }, + "size": 24, + "text": { + "fixed": "Parallelogram" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 44", + "placement": { + "height": 50, + "left": 806, + "top": 438, + "width": 172 + }, + "type": "text" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "text": { + "field": "A-hehwzd", + "fixed": "", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 45", + "placement": { + "height": 50, + "left": 798, + "top": 516, + "width": 188 + }, + "type": "parallelogram" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "field": "A-hehwzd", + "fixed": "#000000" + }, + "text": { + "fixed": "Text color" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 46", + "placement": { + "height": 50, + "left": 798, + "top": 595, + "width": 188 + }, + "type": "parallelogram" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + }, + "image": { + "field": "Count (transformation)", + "mode": "field" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "left", + "color": { + "fixed": "#000000" + }, + "text": { + "fixed": "Background image" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 47", + "placement": { + "height": 50, + "left": 798, + "top": 674, + "width": 188 + }, + "type": "parallelogram" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "field": "A-hehwzd", + "fixed": "dark-green" + }, + "width": 5 + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "text": { + "fixed": "Border" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 48", + "placement": { + "height": 50, + "left": 798, + "top": 753, + "width": 188 + }, + "type": "parallelogram" + }, + { + "background": { + "color": { + "fixed": "transparent" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "rgb(204, 204, 220)" + }, + "size": 24, + "text": { + "fixed": "Triangle" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 49", + "placement": { + "height": 50, + "left": 1074, + "top": 438, + "width": 172 + }, + "type": "text" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "text": { + "field": "A-hehwzd", + "fixed": "", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 50", + "placement": { + "height": 50, + "left": 1066, + "top": 516, + "width": 188 + }, + "type": "triangle" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "center", + "color": { + "field": "A-hehwzd", + "fixed": "#000000" + }, + "text": { + "fixed": "Text color" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 51", + "placement": { + "height": 50, + "left": 1066, + "top": 595, + "width": 188 + }, + "type": "triangle" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + }, + "image": { + "field": "Count (transformation)", + "mode": "field" + } + }, + "border": { + "color": { + "fixed": "dark-green" + } + }, + "config": { + "align": "left", + "color": { + "fixed": "#000000" + }, + "text": { + "fixed": "Background image" + }, + "valign": "bottom" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 52", + "placement": { + "height": 50, + "left": 1066, + "top": 674, + "width": 188 + }, + "type": "triangle" + }, + { + "background": { + "color": { + "fixed": "#D9D9D9" + } + }, + "border": { + "color": { + "field": "A-hehwzd", + "fixed": "dark-green" + }, + "width": 5 + }, + "config": { + "align": "center", + "color": { + "fixed": "#000000" + }, + "text": { + "fixed": "Border" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Element 53", + "placement": { + "height": 50, + "left": 1066, + "top": 753, + "width": 188 + }, + "type": "triangle" + } + ], + "name": "Element 1708700648848", + "placement": { + "height": 100, + "left": 0, + "rotation": 0, + "top": 0, + "width": 100 + }, + "type": "frame" + }, + "showAdvancedTypes": true + }, + "pluginVersion": "11.1.0-pre", + "targets": [ + { + "datasource": { + "type": "grafana", + "uid": "grafana" + }, + "queryType": "snapshot", + "refId": "A", + "snapshot": [ + { + "data": { + "values": [ + [ + 1708679336805, 1708679366805, 1708679396805, 1708679426805, 1708679456805, 1708679486805, + 1708679516805, 1708679546805, 1708679576805, 1708679606805, 1708679636805, 1708679666805, + 1708679696805, 1708679726805, 1708679756805, 1708679786805, 1708679816805, 1708679846805, + 1708679876805, 1708679906805, 1708679936805, 1708679966805, 1708679996805, 1708680026805, + 1708680056805, 1708680086805, 1708680116805, 1708680146805, 1708680176805, 1708680206805, + 1708680236805, 1708680266805, 1708680296805, 1708680326805, 1708680356805, 1708680386805, + 1708680416805, 1708680446805, 1708680476805, 1708680506805, 1708680536805, 1708680566805, + 1708680596805, 1708680626805, 1708680656805, 1708680686805, 1708680716805, 1708680746805, + 1708680776805, 1708680806805, 1708680836805, 1708680866805, 1708680896805, 1708680926805, + 1708680956805, 1708680986805, 1708681016805, 1708681046805, 1708681076805, 1708681106805, + 1708681136805, 1708681166805, 1708681196805, 1708681226805, 1708681256805, 1708681286805, + 1708681316805, 1708681346805, 1708681376805, 1708681406805, 1708681436805, 1708681466805, + 1708681496805, 1708681526805, 1708681556805, 1708681586805, 1708681616805, 1708681646805, + 1708681676805, 1708681706805, 1708681736805, 1708681766805, 1708681796805, 1708681826805, + 1708681856805, 1708681886805, 1708681916805, 1708681946805, 1708681976805, 1708682006805, + 1708682036805, 1708682066805, 1708682096805, 1708682126805, 1708682156805, 1708682186805, + 1708682216805, 1708682246805, 1708682276805, 1708682306805, 1708682336805, 1708682366805, + 1708682396805, 1708682426805, 1708682456805, 1708682486805, 1708682516805, 1708682546805, + 1708682576805, 1708682606805, 1708682636805, 1708682666805, 1708682696805, 1708682726805, + 1708682756805, 1708682786805, 1708682816805, 1708682846805, 1708682876805, 1708682906805, + 1708682936805, 1708682966805, 1708682996805, 1708683026805, 1708683056805, 1708683086805, + 1708683116805, 1708683146805, 1708683176805, 1708683206805, 1708683236805, 1708683266805, + 1708683296805, 1708683326805, 1708683356805, 1708683386805, 1708683416805, 1708683446805, + 1708683476805, 1708683506805, 1708683536805, 1708683566805, 1708683596805, 1708683626805, + 1708683656805, 1708683686805, 1708683716805, 1708683746805, 1708683776805, 1708683806805, + 1708683836805, 1708683866805, 1708683896805, 1708683926805, 1708683956805, 1708683986805, + 1708684016805, 1708684046805, 1708684076805, 1708684106805, 1708684136805, 1708684166805, + 1708684196805, 1708684226805, 1708684256805, 1708684286805, 1708684316805, 1708684346805, + 1708684376805, 1708684406805, 1708684436805, 1708684466805, 1708684496805, 1708684526805, + 1708684556805, 1708684586805, 1708684616805, 1708684646805, 1708684676805, 1708684706805, + 1708684736805, 1708684766805, 1708684796805, 1708684826805, 1708684856805, 1708684886805, + 1708684916805, 1708684946805, 1708684976805, 1708685006805, 1708685036805, 1708685066805, + 1708685096805, 1708685126805, 1708685156805, 1708685186805, 1708685216805, 1708685246805, + 1708685276805, 1708685306805, 1708685336805, 1708685366805, 1708685396805, 1708685426805, + 1708685456805, 1708685486805, 1708685516805, 1708685546805, 1708685576805, 1708685606805, + 1708685636805, 1708685666805, 1708685696805, 1708685726805, 1708685756805, 1708685786805, + 1708685816805, 1708685846805, 1708685876805, 1708685906805, 1708685936805, 1708685966805, + 1708685996805, 1708686026805, 1708686056805, 1708686086805, 1708686116805, 1708686146805, + 1708686176805, 1708686206805, 1708686236805, 1708686266805, 1708686296805, 1708686326805, + 1708686356805, 1708686386805, 1708686416805, 1708686446805, 1708686476805, 1708686506805, + 1708686536805, 1708686566805, 1708686596805, 1708686626805, 1708686656805, 1708686686805, + 1708686716805, 1708686746805, 1708686776805, 1708686806805, 1708686836805, 1708686866805, + 1708686896805, 1708686926805, 1708686956805, 1708686986805, 1708687016805, 1708687046805, + 1708687076805, 1708687106805, 1708687136805, 1708687166805, 1708687196805, 1708687226805, + 1708687256805, 1708687286805, 1708687316805, 1708687346805, 1708687376805, 1708687406805, + 1708687436805, 1708687466805, 1708687496805, 1708687526805, 1708687556805, 1708687586805, + 1708687616805, 1708687646805, 1708687676805, 1708687706805, 1708687736805, 1708687766805, + 1708687796805, 1708687826805, 1708687856805, 1708687886805, 1708687916805, 1708687946805, + 1708687976805, 1708688006805, 1708688036805, 1708688066805, 1708688096805, 1708688126805, + 1708688156805, 1708688186805, 1708688216805, 1708688246805, 1708688276805, 1708688306805, + 1708688336805, 1708688366805, 1708688396805, 1708688426805, 1708688456805, 1708688486805, + 1708688516805, 1708688546805, 1708688576805, 1708688606805, 1708688636805, 1708688666805, + 1708688696805, 1708688726805, 1708688756805, 1708688786805, 1708688816805, 1708688846805, + 1708688876805, 1708688906805, 1708688936805, 1708688966805, 1708688996805, 1708689026805, + 1708689056805, 1708689086805, 1708689116805, 1708689146805, 1708689176805, 1708689206805, + 1708689236805, 1708689266805, 1708689296805, 1708689326805, 1708689356805, 1708689386805, + 1708689416805, 1708689446805, 1708689476805, 1708689506805, 1708689536805, 1708689566805, + 1708689596805, 1708689626805, 1708689656805, 1708689686805, 1708689716805, 1708689746805, + 1708689776805, 1708689806805, 1708689836805, 1708689866805, 1708689896805, 1708689926805, + 1708689956805, 1708689986805, 1708690016805, 1708690046805, 1708690076805, 1708690106805, + 1708690136805, 1708690166805, 1708690196805, 1708690226805, 1708690256805, 1708690286805, + 1708690316805, 1708690346805, 1708690376805, 1708690406805, 1708690436805, 1708690466805, + 1708690496805, 1708690526805, 1708690556805, 1708690586805, 1708690616805, 1708690646805, + 1708690676805, 1708690706805, 1708690736805, 1708690766805, 1708690796805, 1708690826805, + 1708690856805, 1708690886805, 1708690916805, 1708690946805, 1708690976805, 1708691006805, + 1708691036805, 1708691066805, 1708691096805, 1708691126805, 1708691156805, 1708691186805, + 1708691216805, 1708691246805, 1708691276805, 1708691306805, 1708691336805, 1708691366805, + 1708691396805, 1708691426805, 1708691456805, 1708691486805, 1708691516805, 1708691546805, + 1708691576805, 1708691606805, 1708691636805, 1708691666805, 1708691696805, 1708691726805, + 1708691756805, 1708691786805, 1708691816805, 1708691846805, 1708691876805, 1708691906805, + 1708691936805, 1708691966805, 1708691996805, 1708692026805, 1708692056805, 1708692086805, + 1708692116805, 1708692146805, 1708692176805, 1708692206805, 1708692236805, 1708692266805, + 1708692296805, 1708692326805, 1708692356805, 1708692386805, 1708692416805, 1708692446805, + 1708692476805, 1708692506805, 1708692536805, 1708692566805, 1708692596805, 1708692626805, + 1708692656805, 1708692686805, 1708692716805, 1708692746805, 1708692776805, 1708692806805, + 1708692836805, 1708692866805, 1708692896805, 1708692926805, 1708692956805, 1708692986805, + 1708693016805, 1708693046805, 1708693076805, 1708693106805, 1708693136805, 1708693166805, + 1708693196805, 1708693226805, 1708693256805, 1708693286805, 1708693316805, 1708693346805, + 1708693376805, 1708693406805, 1708693436805, 1708693466805, 1708693496805, 1708693526805, + 1708693556805, 1708693586805, 1708693616805, 1708693646805, 1708693676805, 1708693706805, + 1708693736805, 1708693766805, 1708693796805, 1708693826805, 1708693856805, 1708693886805, + 1708693916805, 1708693946805, 1708693976805, 1708694006805, 1708694036805, 1708694066805, + 1708694096805, 1708694126805, 1708694156805, 1708694186805, 1708694216805, 1708694246805, + 1708694276805, 1708694306805, 1708694336805, 1708694366805, 1708694396805, 1708694426805, + 1708694456805, 1708694486805, 1708694516805, 1708694546805, 1708694576805, 1708694606805, + 1708694636805, 1708694666805, 1708694696805, 1708694726805, 1708694756805, 1708694786805, + 1708694816805, 1708694846805, 1708694876805, 1708694906805, 1708694936805, 1708694966805, + 1708694996805, 1708695026805, 1708695056805, 1708695086805, 1708695116805, 1708695146805, + 1708695176805, 1708695206805, 1708695236805, 1708695266805, 1708695296805, 1708695326805, + 1708695356805, 1708695386805, 1708695416805, 1708695446805, 1708695476805, 1708695506805, + 1708695536805, 1708695566805, 1708695596805, 1708695626805, 1708695656805, 1708695686805, + 1708695716805, 1708695746805, 1708695776805, 1708695806805, 1708695836805, 1708695866805, + 1708695896805, 1708695926805, 1708695956805, 1708695986805, 1708696016805, 1708696046805, + 1708696076805, 1708696106805, 1708696136805, 1708696166805, 1708696196805, 1708696226805, + 1708696256805, 1708696286805, 1708696316805, 1708696346805, 1708696376805, 1708696406805, + 1708696436805, 1708696466805, 1708696496805, 1708696526805, 1708696556805, 1708696586805, + 1708696616805, 1708696646805, 1708696676805, 1708696706805, 1708696736805, 1708696766805, + 1708696796805, 1708696826805, 1708696856805, 1708696886805, 1708696916805, 1708696946805, + 1708696976805, 1708697006805, 1708697036805, 1708697066805, 1708697096805, 1708697126805, + 1708697156805, 1708697186805, 1708697216805, 1708697246805, 1708697276805, 1708697306805, + 1708697336805, 1708697366805, 1708697396805, 1708697426805, 1708697456805, 1708697486805, + 1708697516805, 1708697546805, 1708697576805, 1708697606805, 1708697636805, 1708697666805, + 1708697696805, 1708697726805, 1708697756805, 1708697786805, 1708697816805, 1708697846805, + 1708697876805, 1708697906805, 1708697936805, 1708697966805, 1708697996805, 1708698026805, + 1708698056805, 1708698086805, 1708698116805, 1708698146805, 1708698176805, 1708698206805, + 1708698236805, 1708698266805, 1708698296805, 1708698326805, 1708698356805, 1708698386805, + 1708698416805, 1708698446805, 1708698476805, 1708698506805, 1708698536805, 1708698566805, + 1708698596805, 1708698626805, 1708698656805, 1708698686805, 1708698716805, 1708698746805, + 1708698776805, 1708698806805, 1708698836805, 1708698866805, 1708698896805, 1708698926805, + 1708698956805, 1708698986805, 1708699016805, 1708699046805, 1708699076805, 1708699106805, + 1708699136805, 1708699166805, 1708699196805, 1708699226805, 1708699256805, 1708699286805, + 1708699316805, 1708699346805, 1708699376805, 1708699406805, 1708699436805, 1708699466805, + 1708699496805, 1708699526805, 1708699556805, 1708699586805, 1708699616805, 1708699646805, + 1708699676805, 1708699706805, 1708699736805, 1708699766805, 1708699796805, 1708699826805, + 1708699856805, 1708699886805, 1708699916805, 1708699946805, 1708699976805, 1708700006805, + 1708700036805, 1708700066805, 1708700096805, 1708700126805, 1708700156805, 1708700186805, + 1708700216805, 1708700246805, 1708700276805, 1708700306805, 1708700336805, 1708700366805, + 1708700396805, 1708700426805, 1708700456805, 1708700486805, 1708700516805, 1708700546805, + 1708700576805, 1708700606805, 1708700636805, 1708700666805, 1708700696805, 1708700726805, + 1708700756805, 1708700786805, 1708700816805, 1708700846805, 1708700876805, 1708700906805 + ], + [ + 61.7880220958275, 61.81270791445456, 61.829208768453746, 61.3952804521061, 61.54378204663586, + 61.793292376739025, 61.89508181687579, 62.032346031223305, 62.090954811114734, 61.788446359641156, + 61.34681406228381, 61.37147422434034, 61.40948125782848, 61.69144945060843, 61.790001610516114, + 61.9726511399688, 62.17186395369245, 61.841593279449114, 61.81351577982158, 61.774548608665306, + 61.45071912098117, 61.837381696515884, 61.65059114296433, 61.1939165193637, 61.251406089255795, + 60.90456801094042, 60.56801269725712, 60.79736902333104, 60.9367183948152, 61.40785835680261, + 61.621326272755965, 61.53478423246078, 61.616180375313114, 61.56950269911591, 61.419724817297585, + 61.76631225002593, 62.12897242834343, 62.123394668856335, 61.84384351878861, 61.784342739352965, + 61.946359707479985, 62.00854561243485, 61.949378148238175, 61.83251536870273, 62.10046102360543, + 62.51955528279164, 62.43194543555232, 61.93563724102479, 61.61222776112464, 61.706572968014584, + 61.25653135192282, 61.356339636867965, 61.699918128409436, 61.700832273918536, 61.48680261436916, + 61.23885493750151, 60.88064816100224, 60.8061115971784, 60.48689168723215, 60.55420316390225, + 60.78326551379002, 60.71763616746389, 61.0384027799684, 61.361681117105356, 61.819694140841825, + 61.60303629180282, 61.13531779096821, 61.59247554276454, 62.073700396192514, 62.257393021269124, + 62.433793965222456, 62.250955190991135, 61.85027922321473, 61.991414140632, 62.103475488499456, + 62.1675085033716, 61.81759701584563, 61.44204189561965, 61.39004247589699, 61.84841370788845, + 62.01982884908544, 62.29261477385842, 62.1881407732118, 61.77974858108549, 61.30269030921595, + 61.72885233653658, 62.160061928899516, 62.13127060574461, 61.99860014382346, 62.2713524353439, + 62.45360209624644, 62.45033536766769, 62.74579940152534, 62.652379007396135, 62.50461375528075, + 62.4923739782267, 62.87608071230181, 62.979684959589086, 63.376138214369306, 63.66354651661235, + 63.77873383844567, 64.02365055931571, 63.57333739418103, 63.569251641994995, 63.51940188659398, + 63.81887126104792, 64.10808860762592, 64.26214829221084, 63.81353904099011, 63.792123977174654, + 64.09459044217124, 64.49651926575704, 64.87380353415439, 65.22102686208456, 65.49078940759729, + 65.83529933530703, 66.06313506256244, 66.36902912666964, 66.78048161957578, 66.85326316970041, + 67.14736719324404, 67.55927886414139, 67.497025942169, 67.84593513490577, 67.47441764273138, + 67.94871645670011, 68.32729017349827, 68.0857872436968, 67.93500201308075, 67.75781760651351, + 67.62321694227796, 67.87687655718156, 68.03974600191707, 67.82627187210018, 68.29863099170737, + 67.95842239244082, 67.56173819267319, 67.11089985276264, 67.58721546400895, 67.43817707268052, + 67.63734474285276, 67.8608900819446, 68.2491098921388, 68.64222598287019, 68.93436090180123, + 68.58516897681044, 68.88556663186037, 68.82509258379442, 68.43122435581691, 68.01151775860062, + 68.31539501569645, 68.01224489043588, 68.21383479637454, 67.85864255481124, 67.85285437130011, + 67.68770174333852, 67.78834746198736, 68.07096889676643, 68.06340992932907, 68.37116739265392, + 68.25606363201948, 68.0308569092854, 68.0279418148109, 67.68837311892736, 67.98015788941186, + 68.39001231797856, 68.55810426314746, 68.67055538403375, 68.24669275435873, 68.3542775530211, + 67.99792233705742, 67.93848132742042, 67.54327434886798, 67.86541640645122, 67.63715332453567, + 67.44863373545599, 67.54029786855584, 67.3799227903252, 67.272800723832, 67.65752571426705, + 67.27217330871126, 67.36259068699385, 67.6920166495926, 67.99237921892899, 68.00526928940994, + 67.67665255949264, 67.82106088034847, 68.22225474161398, 68.17103508007338, 68.1016199190692, + 67.9715626706774, 68.32706440829391, 67.87634330533211, 67.97207720874553, 67.87493382264455, + 67.38357737752105, 66.94768029712087, 66.67493510394992, 66.48367657533245, 66.77035937087237, + 66.87685661575208, 66.68590889792685, 67.11545823298368, 67.39896920212514, 67.34979904565203, + 67.19769898467558, 67.45512207826779, 67.07906680752531, 67.41541723819202, 67.15472798048341, + 67.15672773264464, 67.6290223056695, 68.11240707910342, 68.40594352628086, 67.92798893549167, + 67.46919856375305, 67.4835115803936, 67.63236807133978, 67.17328415938867, 67.24458272746313, + 66.84593455247185, 67.01430262963748, 67.05291762336604, 67.23817875420809, 66.98941509949245, + 66.68717338595964, 67.12826784930103, 66.74586515933792, 67.12397362624425, 66.91465424208462, + 66.68655917540693, 66.19881496899525, 66.68817057925634, 66.37134623059349, 66.596971028669, + 67.08641642499875, 67.12758650919066, 67.38518121414808, 67.46997153732326, 67.33145553844577, + 67.65363406004056, 67.45595043797628, 67.24978988019829, 67.39677514651268, 67.5978323405599, + 67.96140308646021, 68.00477049936622, 67.75104436464927, 67.99988077010511, 68.19366044789288, + 68.49848829432483, 68.25947149341026, 68.6317723773926, 68.91668608614779, 68.8159923502771, + 69.17513974647629, 69.23356802652235, 69.25309375298245, 69.21125949874141, 69.20726323550102, + 68.78019883289588, 69.24667107728621, 69.1153426259508, 69.56206231608063, 69.72141422867662, + 69.541238907092, 69.81884141217625, 69.53432369593423, 69.43315031151812, 69.01688148574168, + 68.90923934889648, 69.13664462290991, 69.31984528071725, 69.14875943039056, 69.48885652654923, + 69.88297168977773, 69.42462273878934, 69.12679413148601, 68.98123233159377, 68.7762758442149, + 68.48846507574687, 68.02689832504595, 68.02852643078998, 67.555096330903, 67.4639788904284, + 67.61277291577984, 67.70121565906206, 67.66817331556194, 67.84767253849441, 68.18538578924706, + 68.29860737971661, 68.53693780239855, 68.59722904625475, 68.72061222893264, 68.6709989466837, + 69.09400533816238, 69.20295511428635, 69.04258759148102, 68.77139467473914, 68.57756213054044, + 68.67449080482191, 68.60860533532343, 69.01676017621124, 69.3052161196497, 68.89017381442457, + 68.87423335356772, 68.94718162265079, 69.07199142609447, 68.79769510366016, 68.65106890757201, + 68.77703094552813, 68.28258034480257, 68.39479364216955, 68.34220719427985, 68.64253416645396, + 68.87725555362057, 68.5131252571485, 68.89127035251008, 68.67886068136877, 68.4447624537287, + 68.00181105736998, 68.16998112143412, 68.43591872875314, 68.02705208136817, 68.45211203302853, + 68.53289570629535, 68.58200283313724, 68.25718933019785, 68.36370956465593, 68.05020228727913, + 68.50658655636543, 68.66449948753682, 68.2241732330651, 68.09791466418139, 67.88940531760399, + 68.36978817923638, 67.96433264274425, 68.36349840881765, 68.48435193949715, 68.79844380614031, + 69.02017361165895, 68.52624119834393, 68.74005315812674, 68.76067653657759, 68.27918960695276, + 68.65714329915559, 68.42872809873309, 67.98192094490678, 68.02723949195821, 68.36423058076824, + 68.71132274325691, 68.6730162618873, 68.2039400216969, 67.86554691576616, 67.49988053949725, + 67.16307215146469, 67.0353669125758, 67.25486895820083, 66.95629780399439, 67.11477592840751, + 66.64323746050167, 66.20269172026232, 66.48026858749327, 66.4824015740555, 66.09931551662274, + 66.52915019033718, 66.45576884782787, 66.24667785942938, 65.81418399593981, 65.5611498094969, + 65.3398959293035, 65.77646026507297, 65.39346792956597, 65.41692492067247, 65.80888038895401, + 66.01134945900266, 65.80681809031556, 65.32295296805074, 65.37373854104783, 64.93533382859144, + 64.7705026812803, 65.17813748381224, 65.361732144628, 64.9021692008158, 64.7544901225187, + 64.89471070898715, 64.74868721773261, 65.00087272748908, 65.13124433830268, 64.86532668113782, + 64.51108629312537, 64.48208116580882, 64.86340417937541, 64.5927354669956, 64.1183990008181, + 63.66603997870095, 63.670535114339415, 63.179312479687646, 62.71414451358941, 62.349677869382184, + 62.73321111245177, 62.63668992149067, 62.246656820357686, 62.12151749467506, 62.09114940207692, + 62.13652644719604, 62.59170540130276, 62.28435878005047, 62.62555470862962, 62.73559453227453, + 62.63492310358647, 62.99493118502586, 63.2621260239913, 62.99279716454684, 62.8629723908099, + 63.01324605242161, 63.27456767760901, 63.11585082867133, 63.04279509050621, 63.10999097814922, + 63.544265738869036, 63.11822935137409, 63.01523903936018, 63.20403674621687, 62.83896086980938, + 62.41843196460615, 62.11985404869429, 62.07986319614809, 61.99277704632526, 61.668764434861785, + 61.24484474074755, 61.461440830656386, 61.276838934561326, 61.190724244624434, 61.55613660124493, + 61.12078454699415, 61.3276958600818, 61.6042219184118, 61.25513892816126, 61.31664892177688, + 61.688070650858535, 62.01190639528168, 62.08869564629636, 61.97211569824653, 62.06419901170042, + 62.32586483758532, 62.23902878995992, 62.10813808603461, 61.85578175807045, 62.23028871528028, + 62.632050281179744, 62.94816419819628, 62.73043921369783, 62.23627146727455, 62.584832680453275, + 62.62993353336442, 62.8749075179418, 62.48040775408503, 62.21373335340891, 61.79955494265226, + 61.833015907179636, 61.39273179502193, 61.269508387088344, 61.72530078527864, 62.09495330426252, + 62.151597131318645, 62.03375578347783, 62.417839543433374, 62.857582366978384, 62.57434410206618, + 63.025461247334185, 62.891637883802545, 62.74129737438404, 62.686344200077194, 62.74668907124072, + 62.8988624768576, 62.60573732388666, 63.025949401766745, 62.67167444177004, 62.90064380635685, + 62.864966632927896, 62.75573606469665, 62.64819512833622, 62.568258206957815, 62.60577268655998, + 62.15762551315059, 62.567239861872935, 62.2060758300364, 62.31900525191699, 62.28916506290531, + 62.44905922260444, 62.461296429876256, 62.500385909925505, 62.650801268022704, 62.56666212391569, + 62.40046878730333, 62.094243157050244, 62.53663695990193, 62.42300679544488, 62.36921559899188, + 62.24670139180489, 62.569517596988945, 62.66647211282815, 62.665771463959715, 62.876380887882625, + 62.45928337880216, 62.909344895815984, 62.792949925824054, 62.83068709163355, 62.69318202524612, + 62.87621607310353, 63.31283919698538, 63.25629003985129, 63.705604438529726, 63.273909526061956, + 63.5892070912608, 63.25172069842234, 63.29295380191922, 63.37827406047424, 63.40692971848919, + 62.91617622008834, 62.78539371994352, 62.67023463643756, 62.778172553545886, 62.47010093156481, + 62.73229570857713, 62.59545419552364, 63.021765325598885, 63.12625341655425, 62.78539970673421, + 62.48947067386955, 62.50019409861797, 62.27827076256643, 62.32133231940964, 62.28201148707485, + 62.75074499118775, 62.2850034814543, 62.11551149639342, 62.19275216451308, 61.99131816833137, + 61.53708598957499, 61.935909883441674, 61.982544659526965, 62.47356745991423, 62.54325753022373, + 62.146857201138765, 62.189218538018835, 62.06268691181029, 62.33603183556959, 62.82869197777662, + 63.18597742858942, 63.032993740715966, 63.5325845753775, 63.562424373715885, 63.50147245681481, + 63.9167851513779, 64.41348447594058, 64.47641931732102, 64.00422787602398, 63.84372934402268, + 63.57536630107787, 64.06767133087304, 63.857109831163605, 63.594856285335126, 64.01811161431772, + 64.07634398750827, 64.53914449236566, 64.0503925198368, 63.65098131727389, 63.68701372362301, + 63.69177696813634, 63.37477814620089, 62.9056011078514, 62.51297543133976, 62.59250225336332, + 62.80712544689635, 62.841367040210486, 63.01245999144349, 63.05987075936997, 62.7064932753452, + 62.53562962324097, 62.31063278405174, 62.266535846784436, 62.302218124559445, 62.342098988884466, + 61.85031656038063, 62.236466943962625, 62.38666354433638, 62.50448443527158, 62.2386149786552, + 62.43706094747305, 62.48167927367151, 62.53256313135768, 62.78282604117919, 62.610692060658806, + 62.60559562844521, 62.522478905756024, 62.11039441006909, 62.455676051055406, 62.12208142671207, + 62.08989132214651, 61.60556028504288, 61.72080384449528, 61.67203415718332, 61.300028102691506, + 61.2882234681282, 61.67414171824772, 61.663919195939215, 61.82126261684866, 62.14747753168045, + 61.90000454947883, 61.550477655414085, 61.823665895055534, 62.2914692558774, 61.97827489307881, + 62.373656454593686, 62.77509964777066, 63.03123026432718, 62.71959998560016, 62.798641799535915, + 62.36309802737797, 62.187803490902276, 61.86629603436246, 61.51332614924758, 61.670529134596514, + 62.01614193494398, 62.42759829956865, 62.04049015814663, 62.4879050225676, 62.534578908118796, + 62.53729183335963, 62.507213724278294, 62.91741156445245, 62.80078558969012, 62.89530940332275, + 62.82952275179085, 62.931001539540134, 62.715893011718826, 63.176668587903144, 63.25804897932602, + 63.715274804489724, 63.25110762353138, 63.703759539930466, 63.9121877763375, 63.74483403967367, + 63.278090432146044, 63.25689283100131, 63.5587547259249, 63.99611056226184, 63.711033213960846, + 63.61430481648302, 63.37762519043254, 63.825084284030204, 63.65971618383464, 64.11513361026066, + 64.55773804769903, 64.72114634405787, 64.92113863156139, 64.74299967907277, 64.58315181550863, + 64.53895512079164, 64.29203322638713, 64.35539787981175, 64.51347297698413, 64.41240397641245, + 64.37002365296716, 64.54885534394022, 65.0387758477243, 64.77700441309366, 65.18362739291737, + 65.05949296204716, 64.57684960686204, 64.47443633413799, 64.25660237904727, 64.56848853603353, + 64.13857108098799, 63.779464548765795, 63.940686810035814, 63.47280572727399, 63.75027671584932, + 63.72842205520389, 63.28631208752196, 63.54806381048302, 63.89145142689777, 63.77801877620565, + 64.22035568724904, 63.99613288560804, 64.03027098363421, 64.45100338093056, 64.4954103610469, + 64.0379570128468, 64.509809400983, 64.24776908391132, 64.18308085450447, 64.02686567211323, + 64.00949969057655, 64.08790624904579, 64.44413148646105, 64.436667344197, 64.925560935662, + 64.4380208837763, 64.63611397061874, 64.53720467943039, 64.89043109965093, 65.02933526203901, + 65.38083597755491, 65.63733460002958, 66.04889884599933, 66.15611674378638, 66.58017724018646, + 66.13733327264003, 65.69321107501534, 65.92059175869956, 65.73905913370584, 65.39714875503125, + 65.31355908128221, 65.75886616744013, 66.05775873128395, 65.93022978097021, 66.3107650269844 + ] + ] + }, + "schema": { + "fields": [ + { + "config": { + "interval": 30000 }, - "queryType": "snapshot", - "refId": "A", - "snapshot": [ - { - "data": { - "values": [ - [ - 1708679336805, - 1708679366805, - 1708679396805, - 1708679426805, - 1708679456805, - 1708679486805, - 1708679516805, - 1708679546805, - 1708679576805, - 1708679606805, - 1708679636805, - 1708679666805, - 1708679696805, - 1708679726805, - 1708679756805, - 1708679786805, - 1708679816805, - 1708679846805, - 1708679876805, - 1708679906805, - 1708679936805, - 1708679966805, - 1708679996805, - 1708680026805, - 1708680056805, - 1708680086805, - 1708680116805, - 1708680146805, - 1708680176805, - 1708680206805, - 1708680236805, - 1708680266805, - 1708680296805, - 1708680326805, - 1708680356805, - 1708680386805, - 1708680416805, - 1708680446805, - 1708680476805, - 1708680506805, - 1708680536805, - 1708680566805, - 1708680596805, - 1708680626805, - 1708680656805, - 1708680686805, - 1708680716805, - 1708680746805, - 1708680776805, - 1708680806805, - 1708680836805, - 1708680866805, - 1708680896805, - 1708680926805, - 1708680956805, - 1708680986805, - 1708681016805, - 1708681046805, - 1708681076805, - 1708681106805, - 1708681136805, - 1708681166805, - 1708681196805, - 1708681226805, - 1708681256805, - 1708681286805, - 1708681316805, - 1708681346805, - 1708681376805, - 1708681406805, - 1708681436805, - 1708681466805, - 1708681496805, - 1708681526805, - 1708681556805, - 1708681586805, - 1708681616805, - 1708681646805, - 1708681676805, - 1708681706805, - 1708681736805, - 1708681766805, - 1708681796805, - 1708681826805, - 1708681856805, - 1708681886805, - 1708681916805, - 1708681946805, - 1708681976805, - 1708682006805, - 1708682036805, - 1708682066805, - 1708682096805, - 1708682126805, - 1708682156805, - 1708682186805, - 1708682216805, - 1708682246805, - 1708682276805, - 1708682306805, - 1708682336805, - 1708682366805, - 1708682396805, - 1708682426805, - 1708682456805, - 1708682486805, - 1708682516805, - 1708682546805, - 1708682576805, - 1708682606805, - 1708682636805, - 1708682666805, - 1708682696805, - 1708682726805, - 1708682756805, - 1708682786805, - 1708682816805, - 1708682846805, - 1708682876805, - 1708682906805, - 1708682936805, - 1708682966805, - 1708682996805, - 1708683026805, - 1708683056805, - 1708683086805, - 1708683116805, - 1708683146805, - 1708683176805, - 1708683206805, - 1708683236805, - 1708683266805, - 1708683296805, - 1708683326805, - 1708683356805, - 1708683386805, - 1708683416805, - 1708683446805, - 1708683476805, - 1708683506805, - 1708683536805, - 1708683566805, - 1708683596805, - 1708683626805, - 1708683656805, - 1708683686805, - 1708683716805, - 1708683746805, - 1708683776805, - 1708683806805, - 1708683836805, - 1708683866805, - 1708683896805, - 1708683926805, - 1708683956805, - 1708683986805, - 1708684016805, - 1708684046805, - 1708684076805, - 1708684106805, - 1708684136805, - 1708684166805, - 1708684196805, - 1708684226805, - 1708684256805, - 1708684286805, - 1708684316805, - 1708684346805, - 1708684376805, - 1708684406805, - 1708684436805, - 1708684466805, - 1708684496805, - 1708684526805, - 1708684556805, - 1708684586805, - 1708684616805, - 1708684646805, - 1708684676805, - 1708684706805, - 1708684736805, - 1708684766805, - 1708684796805, - 1708684826805, - 1708684856805, - 1708684886805, - 1708684916805, - 1708684946805, - 1708684976805, - 1708685006805, - 1708685036805, - 1708685066805, - 1708685096805, - 1708685126805, - 1708685156805, - 1708685186805, - 1708685216805, - 1708685246805, - 1708685276805, - 1708685306805, - 1708685336805, - 1708685366805, - 1708685396805, - 1708685426805, - 1708685456805, - 1708685486805, - 1708685516805, - 1708685546805, - 1708685576805, - 1708685606805, - 1708685636805, - 1708685666805, - 1708685696805, - 1708685726805, - 1708685756805, - 1708685786805, - 1708685816805, - 1708685846805, - 1708685876805, - 1708685906805, - 1708685936805, - 1708685966805, - 1708685996805, - 1708686026805, - 1708686056805, - 1708686086805, - 1708686116805, - 1708686146805, - 1708686176805, - 1708686206805, - 1708686236805, - 1708686266805, - 1708686296805, - 1708686326805, - 1708686356805, - 1708686386805, - 1708686416805, - 1708686446805, - 1708686476805, - 1708686506805, - 1708686536805, - 1708686566805, - 1708686596805, - 1708686626805, - 1708686656805, - 1708686686805, - 1708686716805, - 1708686746805, - 1708686776805, - 1708686806805, - 1708686836805, - 1708686866805, - 1708686896805, - 1708686926805, - 1708686956805, - 1708686986805, - 1708687016805, - 1708687046805, - 1708687076805, - 1708687106805, - 1708687136805, - 1708687166805, - 1708687196805, - 1708687226805, - 1708687256805, - 1708687286805, - 1708687316805, - 1708687346805, - 1708687376805, - 1708687406805, - 1708687436805, - 1708687466805, - 1708687496805, - 1708687526805, - 1708687556805, - 1708687586805, - 1708687616805, - 1708687646805, - 1708687676805, - 1708687706805, - 1708687736805, - 1708687766805, - 1708687796805, - 1708687826805, - 1708687856805, - 1708687886805, - 1708687916805, - 1708687946805, - 1708687976805, - 1708688006805, - 1708688036805, - 1708688066805, - 1708688096805, - 1708688126805, - 1708688156805, - 1708688186805, - 1708688216805, - 1708688246805, - 1708688276805, - 1708688306805, - 1708688336805, - 1708688366805, - 1708688396805, - 1708688426805, - 1708688456805, - 1708688486805, - 1708688516805, - 1708688546805, - 1708688576805, - 1708688606805, - 1708688636805, - 1708688666805, - 1708688696805, - 1708688726805, - 1708688756805, - 1708688786805, - 1708688816805, - 1708688846805, - 1708688876805, - 1708688906805, - 1708688936805, - 1708688966805, - 1708688996805, - 1708689026805, - 1708689056805, - 1708689086805, - 1708689116805, - 1708689146805, - 1708689176805, - 1708689206805, - 1708689236805, - 1708689266805, - 1708689296805, - 1708689326805, - 1708689356805, - 1708689386805, - 1708689416805, - 1708689446805, - 1708689476805, - 1708689506805, - 1708689536805, - 1708689566805, - 1708689596805, - 1708689626805, - 1708689656805, - 1708689686805, - 1708689716805, - 1708689746805, - 1708689776805, - 1708689806805, - 1708689836805, - 1708689866805, - 1708689896805, - 1708689926805, - 1708689956805, - 1708689986805, - 1708690016805, - 1708690046805, - 1708690076805, - 1708690106805, - 1708690136805, - 1708690166805, - 1708690196805, - 1708690226805, - 1708690256805, - 1708690286805, - 1708690316805, - 1708690346805, - 1708690376805, - 1708690406805, - 1708690436805, - 1708690466805, - 1708690496805, - 1708690526805, - 1708690556805, - 1708690586805, - 1708690616805, - 1708690646805, - 1708690676805, - 1708690706805, - 1708690736805, - 1708690766805, - 1708690796805, - 1708690826805, - 1708690856805, - 1708690886805, - 1708690916805, - 1708690946805, - 1708690976805, - 1708691006805, - 1708691036805, - 1708691066805, - 1708691096805, - 1708691126805, - 1708691156805, - 1708691186805, - 1708691216805, - 1708691246805, - 1708691276805, - 1708691306805, - 1708691336805, - 1708691366805, - 1708691396805, - 1708691426805, - 1708691456805, - 1708691486805, - 1708691516805, - 1708691546805, - 1708691576805, - 1708691606805, - 1708691636805, - 1708691666805, - 1708691696805, - 1708691726805, - 1708691756805, - 1708691786805, - 1708691816805, - 1708691846805, - 1708691876805, - 1708691906805, - 1708691936805, - 1708691966805, - 1708691996805, - 1708692026805, - 1708692056805, - 1708692086805, - 1708692116805, - 1708692146805, - 1708692176805, - 1708692206805, - 1708692236805, - 1708692266805, - 1708692296805, - 1708692326805, - 1708692356805, - 1708692386805, - 1708692416805, - 1708692446805, - 1708692476805, - 1708692506805, - 1708692536805, - 1708692566805, - 1708692596805, - 1708692626805, - 1708692656805, - 1708692686805, - 1708692716805, - 1708692746805, - 1708692776805, - 1708692806805, - 1708692836805, - 1708692866805, - 1708692896805, - 1708692926805, - 1708692956805, - 1708692986805, - 1708693016805, - 1708693046805, - 1708693076805, - 1708693106805, - 1708693136805, - 1708693166805, - 1708693196805, - 1708693226805, - 1708693256805, - 1708693286805, - 1708693316805, - 1708693346805, - 1708693376805, - 1708693406805, - 1708693436805, - 1708693466805, - 1708693496805, - 1708693526805, - 1708693556805, - 1708693586805, - 1708693616805, - 1708693646805, - 1708693676805, - 1708693706805, - 1708693736805, - 1708693766805, - 1708693796805, - 1708693826805, - 1708693856805, - 1708693886805, - 1708693916805, - 1708693946805, - 1708693976805, - 1708694006805, - 1708694036805, - 1708694066805, - 1708694096805, - 1708694126805, - 1708694156805, - 1708694186805, - 1708694216805, - 1708694246805, - 1708694276805, - 1708694306805, - 1708694336805, - 1708694366805, - 1708694396805, - 1708694426805, - 1708694456805, - 1708694486805, - 1708694516805, - 1708694546805, - 1708694576805, - 1708694606805, - 1708694636805, - 1708694666805, - 1708694696805, - 1708694726805, - 1708694756805, - 1708694786805, - 1708694816805, - 1708694846805, - 1708694876805, - 1708694906805, - 1708694936805, - 1708694966805, - 1708694996805, - 1708695026805, - 1708695056805, - 1708695086805, - 1708695116805, - 1708695146805, - 1708695176805, - 1708695206805, - 1708695236805, - 1708695266805, - 1708695296805, - 1708695326805, - 1708695356805, - 1708695386805, - 1708695416805, - 1708695446805, - 1708695476805, - 1708695506805, - 1708695536805, - 1708695566805, - 1708695596805, - 1708695626805, - 1708695656805, - 1708695686805, - 1708695716805, - 1708695746805, - 1708695776805, - 1708695806805, - 1708695836805, - 1708695866805, - 1708695896805, - 1708695926805, - 1708695956805, - 1708695986805, - 1708696016805, - 1708696046805, - 1708696076805, - 1708696106805, - 1708696136805, - 1708696166805, - 1708696196805, - 1708696226805, - 1708696256805, - 1708696286805, - 1708696316805, - 1708696346805, - 1708696376805, - 1708696406805, - 1708696436805, - 1708696466805, - 1708696496805, - 1708696526805, - 1708696556805, - 1708696586805, - 1708696616805, - 1708696646805, - 1708696676805, - 1708696706805, - 1708696736805, - 1708696766805, - 1708696796805, - 1708696826805, - 1708696856805, - 1708696886805, - 1708696916805, - 1708696946805, - 1708696976805, - 1708697006805, - 1708697036805, - 1708697066805, - 1708697096805, - 1708697126805, - 1708697156805, - 1708697186805, - 1708697216805, - 1708697246805, - 1708697276805, - 1708697306805, - 1708697336805, - 1708697366805, - 1708697396805, - 1708697426805, - 1708697456805, - 1708697486805, - 1708697516805, - 1708697546805, - 1708697576805, - 1708697606805, - 1708697636805, - 1708697666805, - 1708697696805, - 1708697726805, - 1708697756805, - 1708697786805, - 1708697816805, - 1708697846805, - 1708697876805, - 1708697906805, - 1708697936805, - 1708697966805, - 1708697996805, - 1708698026805, - 1708698056805, - 1708698086805, - 1708698116805, - 1708698146805, - 1708698176805, - 1708698206805, - 1708698236805, - 1708698266805, - 1708698296805, - 1708698326805, - 1708698356805, - 1708698386805, - 1708698416805, - 1708698446805, - 1708698476805, - 1708698506805, - 1708698536805, - 1708698566805, - 1708698596805, - 1708698626805, - 1708698656805, - 1708698686805, - 1708698716805, - 1708698746805, - 1708698776805, - 1708698806805, - 1708698836805, - 1708698866805, - 1708698896805, - 1708698926805, - 1708698956805, - 1708698986805, - 1708699016805, - 1708699046805, - 1708699076805, - 1708699106805, - 1708699136805, - 1708699166805, - 1708699196805, - 1708699226805, - 1708699256805, - 1708699286805, - 1708699316805, - 1708699346805, - 1708699376805, - 1708699406805, - 1708699436805, - 1708699466805, - 1708699496805, - 1708699526805, - 1708699556805, - 1708699586805, - 1708699616805, - 1708699646805, - 1708699676805, - 1708699706805, - 1708699736805, - 1708699766805, - 1708699796805, - 1708699826805, - 1708699856805, - 1708699886805, - 1708699916805, - 1708699946805, - 1708699976805, - 1708700006805, - 1708700036805, - 1708700066805, - 1708700096805, - 1708700126805, - 1708700156805, - 1708700186805, - 1708700216805, - 1708700246805, - 1708700276805, - 1708700306805, - 1708700336805, - 1708700366805, - 1708700396805, - 1708700426805, - 1708700456805, - 1708700486805, - 1708700516805, - 1708700546805, - 1708700576805, - 1708700606805, - 1708700636805, - 1708700666805, - 1708700696805, - 1708700726805, - 1708700756805, - 1708700786805, - 1708700816805, - 1708700846805, - 1708700876805, - 1708700906805 - ], - [ - 61.7880220958275, - 61.81270791445456, - 61.829208768453746, - 61.3952804521061, - 61.54378204663586, - 61.793292376739025, - 61.89508181687579, - 62.032346031223305, - 62.090954811114734, - 61.788446359641156, - 61.34681406228381, - 61.37147422434034, - 61.40948125782848, - 61.69144945060843, - 61.790001610516114, - 61.9726511399688, - 62.17186395369245, - 61.841593279449114, - 61.81351577982158, - 61.774548608665306, - 61.45071912098117, - 61.837381696515884, - 61.65059114296433, - 61.1939165193637, - 61.251406089255795, - 60.90456801094042, - 60.56801269725712, - 60.79736902333104, - 60.9367183948152, - 61.40785835680261, - 61.621326272755965, - 61.53478423246078, - 61.616180375313114, - 61.56950269911591, - 61.419724817297585, - 61.76631225002593, - 62.12897242834343, - 62.123394668856335, - 61.84384351878861, - 61.784342739352965, - 61.946359707479985, - 62.00854561243485, - 61.949378148238175, - 61.83251536870273, - 62.10046102360543, - 62.51955528279164, - 62.43194543555232, - 61.93563724102479, - 61.61222776112464, - 61.706572968014584, - 61.25653135192282, - 61.356339636867965, - 61.699918128409436, - 61.700832273918536, - 61.48680261436916, - 61.23885493750151, - 60.88064816100224, - 60.8061115971784, - 60.48689168723215, - 60.55420316390225, - 60.78326551379002, - 60.71763616746389, - 61.0384027799684, - 61.361681117105356, - 61.819694140841825, - 61.60303629180282, - 61.13531779096821, - 61.59247554276454, - 62.073700396192514, - 62.257393021269124, - 62.433793965222456, - 62.250955190991135, - 61.85027922321473, - 61.991414140632, - 62.103475488499456, - 62.1675085033716, - 61.81759701584563, - 61.44204189561965, - 61.39004247589699, - 61.84841370788845, - 62.01982884908544, - 62.29261477385842, - 62.1881407732118, - 61.77974858108549, - 61.30269030921595, - 61.72885233653658, - 62.160061928899516, - 62.13127060574461, - 61.99860014382346, - 62.2713524353439, - 62.45360209624644, - 62.45033536766769, - 62.74579940152534, - 62.652379007396135, - 62.50461375528075, - 62.4923739782267, - 62.87608071230181, - 62.979684959589086, - 63.376138214369306, - 63.66354651661235, - 63.77873383844567, - 64.02365055931571, - 63.57333739418103, - 63.569251641994995, - 63.51940188659398, - 63.81887126104792, - 64.10808860762592, - 64.26214829221084, - 63.81353904099011, - 63.792123977174654, - 64.09459044217124, - 64.49651926575704, - 64.87380353415439, - 65.22102686208456, - 65.49078940759729, - 65.83529933530703, - 66.06313506256244, - 66.36902912666964, - 66.78048161957578, - 66.85326316970041, - 67.14736719324404, - 67.55927886414139, - 67.497025942169, - 67.84593513490577, - 67.47441764273138, - 67.94871645670011, - 68.32729017349827, - 68.0857872436968, - 67.93500201308075, - 67.75781760651351, - 67.62321694227796, - 67.87687655718156, - 68.03974600191707, - 67.82627187210018, - 68.29863099170737, - 67.95842239244082, - 67.56173819267319, - 67.11089985276264, - 67.58721546400895, - 67.43817707268052, - 67.63734474285276, - 67.8608900819446, - 68.2491098921388, - 68.64222598287019, - 68.93436090180123, - 68.58516897681044, - 68.88556663186037, - 68.82509258379442, - 68.43122435581691, - 68.01151775860062, - 68.31539501569645, - 68.01224489043588, - 68.21383479637454, - 67.85864255481124, - 67.85285437130011, - 67.68770174333852, - 67.78834746198736, - 68.07096889676643, - 68.06340992932907, - 68.37116739265392, - 68.25606363201948, - 68.0308569092854, - 68.0279418148109, - 67.68837311892736, - 67.98015788941186, - 68.39001231797856, - 68.55810426314746, - 68.67055538403375, - 68.24669275435873, - 68.3542775530211, - 67.99792233705742, - 67.93848132742042, - 67.54327434886798, - 67.86541640645122, - 67.63715332453567, - 67.44863373545599, - 67.54029786855584, - 67.3799227903252, - 67.272800723832, - 67.65752571426705, - 67.27217330871126, - 67.36259068699385, - 67.6920166495926, - 67.99237921892899, - 68.00526928940994, - 67.67665255949264, - 67.82106088034847, - 68.22225474161398, - 68.17103508007338, - 68.1016199190692, - 67.9715626706774, - 68.32706440829391, - 67.87634330533211, - 67.97207720874553, - 67.87493382264455, - 67.38357737752105, - 66.94768029712087, - 66.67493510394992, - 66.48367657533245, - 66.77035937087237, - 66.87685661575208, - 66.68590889792685, - 67.11545823298368, - 67.39896920212514, - 67.34979904565203, - 67.19769898467558, - 67.45512207826779, - 67.07906680752531, - 67.41541723819202, - 67.15472798048341, - 67.15672773264464, - 67.6290223056695, - 68.11240707910342, - 68.40594352628086, - 67.92798893549167, - 67.46919856375305, - 67.4835115803936, - 67.63236807133978, - 67.17328415938867, - 67.24458272746313, - 66.84593455247185, - 67.01430262963748, - 67.05291762336604, - 67.23817875420809, - 66.98941509949245, - 66.68717338595964, - 67.12826784930103, - 66.74586515933792, - 67.12397362624425, - 66.91465424208462, - 66.68655917540693, - 66.19881496899525, - 66.68817057925634, - 66.37134623059349, - 66.596971028669, - 67.08641642499875, - 67.12758650919066, - 67.38518121414808, - 67.46997153732326, - 67.33145553844577, - 67.65363406004056, - 67.45595043797628, - 67.24978988019829, - 67.39677514651268, - 67.5978323405599, - 67.96140308646021, - 68.00477049936622, - 67.75104436464927, - 67.99988077010511, - 68.19366044789288, - 68.49848829432483, - 68.25947149341026, - 68.6317723773926, - 68.91668608614779, - 68.8159923502771, - 69.17513974647629, - 69.23356802652235, - 69.25309375298245, - 69.21125949874141, - 69.20726323550102, - 68.78019883289588, - 69.24667107728621, - 69.1153426259508, - 69.56206231608063, - 69.72141422867662, - 69.541238907092, - 69.81884141217625, - 69.53432369593423, - 69.43315031151812, - 69.01688148574168, - 68.90923934889648, - 69.13664462290991, - 69.31984528071725, - 69.14875943039056, - 69.48885652654923, - 69.88297168977773, - 69.42462273878934, - 69.12679413148601, - 68.98123233159377, - 68.7762758442149, - 68.48846507574687, - 68.02689832504595, - 68.02852643078998, - 67.555096330903, - 67.4639788904284, - 67.61277291577984, - 67.70121565906206, - 67.66817331556194, - 67.84767253849441, - 68.18538578924706, - 68.29860737971661, - 68.53693780239855, - 68.59722904625475, - 68.72061222893264, - 68.6709989466837, - 69.09400533816238, - 69.20295511428635, - 69.04258759148102, - 68.77139467473914, - 68.57756213054044, - 68.67449080482191, - 68.60860533532343, - 69.01676017621124, - 69.3052161196497, - 68.89017381442457, - 68.87423335356772, - 68.94718162265079, - 69.07199142609447, - 68.79769510366016, - 68.65106890757201, - 68.77703094552813, - 68.28258034480257, - 68.39479364216955, - 68.34220719427985, - 68.64253416645396, - 68.87725555362057, - 68.5131252571485, - 68.89127035251008, - 68.67886068136877, - 68.4447624537287, - 68.00181105736998, - 68.16998112143412, - 68.43591872875314, - 68.02705208136817, - 68.45211203302853, - 68.53289570629535, - 68.58200283313724, - 68.25718933019785, - 68.36370956465593, - 68.05020228727913, - 68.50658655636543, - 68.66449948753682, - 68.2241732330651, - 68.09791466418139, - 67.88940531760399, - 68.36978817923638, - 67.96433264274425, - 68.36349840881765, - 68.48435193949715, - 68.79844380614031, - 69.02017361165895, - 68.52624119834393, - 68.74005315812674, - 68.76067653657759, - 68.27918960695276, - 68.65714329915559, - 68.42872809873309, - 67.98192094490678, - 68.02723949195821, - 68.36423058076824, - 68.71132274325691, - 68.6730162618873, - 68.2039400216969, - 67.86554691576616, - 67.49988053949725, - 67.16307215146469, - 67.0353669125758, - 67.25486895820083, - 66.95629780399439, - 67.11477592840751, - 66.64323746050167, - 66.20269172026232, - 66.48026858749327, - 66.4824015740555, - 66.09931551662274, - 66.52915019033718, - 66.45576884782787, - 66.24667785942938, - 65.81418399593981, - 65.5611498094969, - 65.3398959293035, - 65.77646026507297, - 65.39346792956597, - 65.41692492067247, - 65.80888038895401, - 66.01134945900266, - 65.80681809031556, - 65.32295296805074, - 65.37373854104783, - 64.93533382859144, - 64.7705026812803, - 65.17813748381224, - 65.361732144628, - 64.9021692008158, - 64.7544901225187, - 64.89471070898715, - 64.74868721773261, - 65.00087272748908, - 65.13124433830268, - 64.86532668113782, - 64.51108629312537, - 64.48208116580882, - 64.86340417937541, - 64.5927354669956, - 64.1183990008181, - 63.66603997870095, - 63.670535114339415, - 63.179312479687646, - 62.71414451358941, - 62.349677869382184, - 62.73321111245177, - 62.63668992149067, - 62.246656820357686, - 62.12151749467506, - 62.09114940207692, - 62.13652644719604, - 62.59170540130276, - 62.28435878005047, - 62.62555470862962, - 62.73559453227453, - 62.63492310358647, - 62.99493118502586, - 63.2621260239913, - 62.99279716454684, - 62.8629723908099, - 63.01324605242161, - 63.27456767760901, - 63.11585082867133, - 63.04279509050621, - 63.10999097814922, - 63.544265738869036, - 63.11822935137409, - 63.01523903936018, - 63.20403674621687, - 62.83896086980938, - 62.41843196460615, - 62.11985404869429, - 62.07986319614809, - 61.99277704632526, - 61.668764434861785, - 61.24484474074755, - 61.461440830656386, - 61.276838934561326, - 61.190724244624434, - 61.55613660124493, - 61.12078454699415, - 61.3276958600818, - 61.6042219184118, - 61.25513892816126, - 61.31664892177688, - 61.688070650858535, - 62.01190639528168, - 62.08869564629636, - 61.97211569824653, - 62.06419901170042, - 62.32586483758532, - 62.23902878995992, - 62.10813808603461, - 61.85578175807045, - 62.23028871528028, - 62.632050281179744, - 62.94816419819628, - 62.73043921369783, - 62.23627146727455, - 62.584832680453275, - 62.62993353336442, - 62.8749075179418, - 62.48040775408503, - 62.21373335340891, - 61.79955494265226, - 61.833015907179636, - 61.39273179502193, - 61.269508387088344, - 61.72530078527864, - 62.09495330426252, - 62.151597131318645, - 62.03375578347783, - 62.417839543433374, - 62.857582366978384, - 62.57434410206618, - 63.025461247334185, - 62.891637883802545, - 62.74129737438404, - 62.686344200077194, - 62.74668907124072, - 62.8988624768576, - 62.60573732388666, - 63.025949401766745, - 62.67167444177004, - 62.90064380635685, - 62.864966632927896, - 62.75573606469665, - 62.64819512833622, - 62.568258206957815, - 62.60577268655998, - 62.15762551315059, - 62.567239861872935, - 62.2060758300364, - 62.31900525191699, - 62.28916506290531, - 62.44905922260444, - 62.461296429876256, - 62.500385909925505, - 62.650801268022704, - 62.56666212391569, - 62.40046878730333, - 62.094243157050244, - 62.53663695990193, - 62.42300679544488, - 62.36921559899188, - 62.24670139180489, - 62.569517596988945, - 62.66647211282815, - 62.665771463959715, - 62.876380887882625, - 62.45928337880216, - 62.909344895815984, - 62.792949925824054, - 62.83068709163355, - 62.69318202524612, - 62.87621607310353, - 63.31283919698538, - 63.25629003985129, - 63.705604438529726, - 63.273909526061956, - 63.5892070912608, - 63.25172069842234, - 63.29295380191922, - 63.37827406047424, - 63.40692971848919, - 62.91617622008834, - 62.78539371994352, - 62.67023463643756, - 62.778172553545886, - 62.47010093156481, - 62.73229570857713, - 62.59545419552364, - 63.021765325598885, - 63.12625341655425, - 62.78539970673421, - 62.48947067386955, - 62.50019409861797, - 62.27827076256643, - 62.32133231940964, - 62.28201148707485, - 62.75074499118775, - 62.2850034814543, - 62.11551149639342, - 62.19275216451308, - 61.99131816833137, - 61.53708598957499, - 61.935909883441674, - 61.982544659526965, - 62.47356745991423, - 62.54325753022373, - 62.146857201138765, - 62.189218538018835, - 62.06268691181029, - 62.33603183556959, - 62.82869197777662, - 63.18597742858942, - 63.032993740715966, - 63.5325845753775, - 63.562424373715885, - 63.50147245681481, - 63.9167851513779, - 64.41348447594058, - 64.47641931732102, - 64.00422787602398, - 63.84372934402268, - 63.57536630107787, - 64.06767133087304, - 63.857109831163605, - 63.594856285335126, - 64.01811161431772, - 64.07634398750827, - 64.53914449236566, - 64.0503925198368, - 63.65098131727389, - 63.68701372362301, - 63.69177696813634, - 63.37477814620089, - 62.9056011078514, - 62.51297543133976, - 62.59250225336332, - 62.80712544689635, - 62.841367040210486, - 63.01245999144349, - 63.05987075936997, - 62.7064932753452, - 62.53562962324097, - 62.31063278405174, - 62.266535846784436, - 62.302218124559445, - 62.342098988884466, - 61.85031656038063, - 62.236466943962625, - 62.38666354433638, - 62.50448443527158, - 62.2386149786552, - 62.43706094747305, - 62.48167927367151, - 62.53256313135768, - 62.78282604117919, - 62.610692060658806, - 62.60559562844521, - 62.522478905756024, - 62.11039441006909, - 62.455676051055406, - 62.12208142671207, - 62.08989132214651, - 61.60556028504288, - 61.72080384449528, - 61.67203415718332, - 61.300028102691506, - 61.2882234681282, - 61.67414171824772, - 61.663919195939215, - 61.82126261684866, - 62.14747753168045, - 61.90000454947883, - 61.550477655414085, - 61.823665895055534, - 62.2914692558774, - 61.97827489307881, - 62.373656454593686, - 62.77509964777066, - 63.03123026432718, - 62.71959998560016, - 62.798641799535915, - 62.36309802737797, - 62.187803490902276, - 61.86629603436246, - 61.51332614924758, - 61.670529134596514, - 62.01614193494398, - 62.42759829956865, - 62.04049015814663, - 62.4879050225676, - 62.534578908118796, - 62.53729183335963, - 62.507213724278294, - 62.91741156445245, - 62.80078558969012, - 62.89530940332275, - 62.82952275179085, - 62.931001539540134, - 62.715893011718826, - 63.176668587903144, - 63.25804897932602, - 63.715274804489724, - 63.25110762353138, - 63.703759539930466, - 63.9121877763375, - 63.74483403967367, - 63.278090432146044, - 63.25689283100131, - 63.5587547259249, - 63.99611056226184, - 63.711033213960846, - 63.61430481648302, - 63.37762519043254, - 63.825084284030204, - 63.65971618383464, - 64.11513361026066, - 64.55773804769903, - 64.72114634405787, - 64.92113863156139, - 64.74299967907277, - 64.58315181550863, - 64.53895512079164, - 64.29203322638713, - 64.35539787981175, - 64.51347297698413, - 64.41240397641245, - 64.37002365296716, - 64.54885534394022, - 65.0387758477243, - 64.77700441309366, - 65.18362739291737, - 65.05949296204716, - 64.57684960686204, - 64.47443633413799, - 64.25660237904727, - 64.56848853603353, - 64.13857108098799, - 63.779464548765795, - 63.940686810035814, - 63.47280572727399, - 63.75027671584932, - 63.72842205520389, - 63.28631208752196, - 63.54806381048302, - 63.89145142689777, - 63.77801877620565, - 64.22035568724904, - 63.99613288560804, - 64.03027098363421, - 64.45100338093056, - 64.4954103610469, - 64.0379570128468, - 64.509809400983, - 64.24776908391132, - 64.18308085450447, - 64.02686567211323, - 64.00949969057655, - 64.08790624904579, - 64.44413148646105, - 64.436667344197, - 64.925560935662, - 64.4380208837763, - 64.63611397061874, - 64.53720467943039, - 64.89043109965093, - 65.02933526203901, - 65.38083597755491, - 65.63733460002958, - 66.04889884599933, - 66.15611674378638, - 66.58017724018646, - 66.13733327264003, - 65.69321107501534, - 65.92059175869956, - 65.73905913370584, - 65.39714875503125, - 65.31355908128221, - 65.75886616744013, - 66.05775873128395, - 65.93022978097021, - 66.3107650269844 - ] - ] - }, - "schema": { - "fields": [ - { - "config": { - "interval": 30000 - }, - "name": "time", - "type": "time", - "typeInfo": { - "frame": "time.Time", - "nullable": true - } - }, - { - "config": {}, - "labels": {}, - "name": "A-hehwzd", - "type": "number", - "typeInfo": { - "frame": "float64", - "nullable": true - } - } - ], - "meta": { - "custom": { - "customStat": 10 - }, - "typeVersion": [ - 0, - 0 - ] - }, - "refId": "A" - } - } - ] - } - ], - "title": "Canvas Enhanced Data Links", - "transformations": [ - { - "id": "calculateField", - "options": { - "alias": "Count (transformation)", - "mode": "reduceRow", - "reduce": { - "include": [ - "A-series" - ], - "reducer": "count" - } + "name": "time", + "type": "time", + "typeInfo": { + "frame": "time.Time", + "nullable": true } - } - ], - "type": "canvas" + }, + { + "config": {}, + "labels": {}, + "name": "A-hehwzd", + "type": "number", + "typeInfo": { + "frame": "float64", + "nullable": true + } + } + ], + "meta": { + "custom": { + "customStat": 10 + }, + "typeVersion": [0, 0] + }, + "refId": "A" + } + } + ] } - ], - "schemaVersion": 39, - "tags": [ - "gdev", - "panel-tests", - "canvas" - ], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timeRangeUpdatedDuringEditOrView": false, - "timepicker": {}, - "timezone": "browser", - "title": "Panel Tests - Canvas Datalinks", - "uid": "adf95uwu7w1s0e", - "version": 10, - "weekStart": "" -} \ No newline at end of file + ], + "title": "Canvas Enhanced Data Links", + "transformations": [ + { + "id": "calculateField", + "options": { + "alias": "Count (transformation)", + "mode": "reduceRow", + "reduce": { + "include": ["A-series"], + "reducer": "count" + } + } + } + ], + "type": "canvas" + } + ], + "schemaVersion": 39, + "tags": ["gdev", "panel-tests", "canvas"], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timeRangeUpdatedDuringEditOrView": false, + "timepicker": {}, + "timezone": "browser", + "title": "Panel Tests - Canvas Datalinks", + "uid": "adf95uwu7w1s0e", + "version": 10, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/panel-canvas/canvas-examples.json b/devenv/dev-dashboards/panel-canvas/canvas-examples.json index 7b025da055f..0d09602f4f6 100644 --- a/devenv/dev-dashboards/panel-canvas/canvas-examples.json +++ b/devenv/dev-dashboards/panel-canvas/canvas-examples.json @@ -50,7 +50,9 @@ }, "type": "canvas", "title": "Wind Energy", - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "pluginVersion": "9.4.0-pre", "fieldConfig": { "defaults": { @@ -1132,8 +1134,7 @@ { "csvContent": "w1_rpm, w1_energy_output, w1_status, w2_rpm, w2_energy_output, w2_status, w3_rpm, w3_energy_output, w3_status, w4_rpm, w4_energy_output, w4_status\n12, 1.2, operational, 22, 1.8, operational, 8, 0.6, operational, 0, 0, needs maintenance", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -1141,7 +1142,9 @@ ] }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 15, "w": 6, @@ -1176,7 +1179,9 @@ "type": "row" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -3310,8 +3315,7 @@ { "csvContent": "Status_12, Status_13, Status_14, Throughput_12, Throughput_13, Throughput_14, Color_12, Color_13, Color_14\nReady, Blocked, Ready, 205, 0, 205, red, Red, Green", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "Conveyor Controller", "scenarioId": "csv_content" @@ -3321,7 +3325,9 @@ "type": "canvas" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 18, "w": 6, @@ -3356,7 +3362,9 @@ "type": "row" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -3582,8 +3590,7 @@ { "csvContent": "house_draw, battery_charge, solar_output\n1.1, 2.2, 3.3", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -3593,7 +3600,9 @@ "type": "canvas" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 15, "w": 6, @@ -3615,7 +3624,9 @@ "type": "text" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -3792,8 +3803,7 @@ { "csvContent": "solar_output, battery_draw\n0.0, 2.2", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -3803,7 +3813,9 @@ "type": "canvas" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 15, "w": 6, @@ -3826,11 +3838,7 @@ } ], "schemaVersion": 37, - "tags": [ - "gdev", - "panel-tests", - "canvas" - ], + "tags": ["gdev", "panel-tests", "canvas"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-common/color_modes.json b/devenv/dev-dashboards/panel-common/color_modes.json index 2e5f6922d61..4e80e2a2216 100644 --- a/devenv/dev-dashboards/panel-common/color_modes.json +++ b/devenv/dev-dashboards/panel-common/color_modes.json @@ -18,7 +18,9 @@ "links": [], "panels": [ { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -217,7 +219,9 @@ "type": "stat" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { diff --git a/devenv/dev-dashboards/panel-common/lazy_loading.json b/devenv/dev-dashboards/panel-common/lazy_loading.json index 960c466124c..e6a1a91ad4f 100644 --- a/devenv/dev-dashboards/panel-common/lazy_loading.json +++ b/devenv/dev-dashboards/panel-common/lazy_loading.json @@ -18,7 +18,9 @@ "links": [], "panels": [ { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 7, "w": 24, @@ -143,7 +145,9 @@ "colorBackground": false, "colorValue": true, "colors": ["#299c46", "#73BF69", "#d44a3a"], - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": null, "format": "ms", "gauge": { @@ -222,7 +226,9 @@ "colorBackground": false, "colorValue": true, "colors": ["#299c46", "#73BF69", "#d44a3a"], - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": null, "format": "ms", "gauge": { @@ -301,7 +307,9 @@ "colorBackground": false, "colorValue": true, "colors": ["#299c46", "#73BF69", "#d44a3a"], - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": null, "format": "ms", "gauge": { @@ -380,7 +388,9 @@ "colorBackground": false, "colorValue": true, "colors": ["#299c46", "#73BF69", "#d44a3a"], - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": null, "format": "ms", "gauge": { @@ -464,7 +474,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 3, "fillGradient": 0, "gridPos": { @@ -561,7 +573,9 @@ } }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 4, "w": 24, @@ -617,7 +631,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 5, "gridPos": { @@ -706,7 +722,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 5, "gridPos": { @@ -795,7 +813,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 5, "gridPos": { @@ -884,7 +904,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 5, "gridPos": { @@ -976,7 +998,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 3, "fillGradient": 0, "gridPos": { @@ -1080,7 +1104,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 10, "gridPos": { @@ -1167,7 +1193,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 8, "gridPos": { @@ -1256,7 +1284,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 5, "gridPos": { @@ -1345,7 +1375,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 5, "gridPos": { @@ -1434,7 +1466,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 5, "gridPos": { @@ -1523,7 +1557,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 5, "gridPos": { @@ -1615,7 +1651,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 3, "fillGradient": 0, "gridPos": { @@ -1719,7 +1757,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 5, "gridPos": { @@ -1808,7 +1848,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 5, "gridPos": { @@ -1897,7 +1939,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 5, "gridPos": { @@ -1986,7 +2030,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "fillGradient": 5, "gridPos": { @@ -2069,7 +2115,9 @@ } }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 7, "w": 24, diff --git a/devenv/dev-dashboards/panel-common/linked-viz.json b/devenv/dev-dashboards/panel-common/linked-viz.json index 5b0201e8392..9be073d012c 100644 --- a/devenv/dev-dashboards/panel-common/linked-viz.json +++ b/devenv/dev-dashboards/panel-common/linked-viz.json @@ -63,9 +63,7 @@ "justifyMode": "auto", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -128,9 +126,7 @@ "justifyMode": "auto", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -199,9 +195,7 @@ "justifyMode": "auto", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -259,9 +253,7 @@ "justifyMode": "auto", "orientation": "auto", "reduceOptions": { - "calcs": [ - "first" - ], + "calcs": ["first"], "fields": "", "limit": 2, "values": true @@ -325,9 +317,7 @@ "justifyMode": "auto", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "limit": 2, "values": true @@ -397,9 +387,7 @@ "justifyMode": "auto", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "limit": 2, "values": true @@ -455,9 +443,7 @@ "options": { "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -518,9 +504,7 @@ "options": { "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -586,9 +570,7 @@ "options": { "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -644,9 +626,7 @@ "options": { "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "limit": 2, "values": true @@ -708,9 +688,7 @@ "options": { "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "limit": 2, "values": true @@ -777,9 +755,7 @@ "options": { "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "limit": 2, "values": true @@ -837,9 +813,7 @@ "displayMode": "gradient", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -900,9 +874,7 @@ "displayMode": "gradient", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -968,9 +940,7 @@ "displayMode": "gradient", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -1026,9 +996,7 @@ "displayMode": "gradient", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "limit": 2, "values": true @@ -1090,9 +1058,7 @@ "displayMode": "gradient", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "limit": 2, "values": true @@ -1159,9 +1125,7 @@ "displayMode": "gradient", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "limit": 2, "values": true diff --git a/devenv/dev-dashboards/panel-common/shared_queries.json b/devenv/dev-dashboards/panel-common/shared_queries.json index 2117b83a399..e2d8528c10f 100644 --- a/devenv/dev-dashboards/panel-common/shared_queries.json +++ b/devenv/dev-dashboards/panel-common/shared_queries.json @@ -22,7 +22,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -99,8 +101,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -108,8 +109,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_metric_values", @@ -117,8 +117,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "csv_metric_values", @@ -166,9 +165,7 @@ "options": { "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -227,9 +224,7 @@ "options": { "orientation": "auto", "reduceOptions": { - "calcs": [ - "min" - ], + "calcs": ["min"], "fields": "", "values": false }, @@ -295,9 +290,7 @@ "minVizWidth": 0, "orientation": "vertical", "reduceOptions": { - "calcs": [ - "max" - ], + "calcs": ["max"], "fields": "", "values": false }, @@ -386,9 +379,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true, @@ -419,10 +410,7 @@ ], "refresh": "", "schemaVersion": 38, - "tags": [ - "gdev", - "datasource-test" - ], + "tags": ["gdev", "datasource-test"], "templating": { "list": [] }, @@ -431,18 +419,7 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "", "title": "Datasource tests - Shared Queries", diff --git a/devenv/dev-dashboards/panel-dashlist/dashlist.json b/devenv/dev-dashboards/panel-dashlist/dashlist.json index 8db5b616acd..9ba4f9ce5a2 100644 --- a/devenv/dev-dashboards/panel-dashlist/dashlist.json +++ b/devenv/dev-dashboards/panel-dashlist/dashlist.json @@ -24,8 +24,7 @@ "panels": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "gridPos": { "h": 12, diff --git a/devenv/dev-dashboards/panel-datagrid/datagrid_metric_values.json b/devenv/dev-dashboards/panel-datagrid/datagrid_metric_values.json index 00a65a9f1aa..b4180bb04ea 100644 --- a/devenv/dev-dashboards/panel-datagrid/datagrid_metric_values.json +++ b/devenv/dev-dashboards/panel-datagrid/datagrid_metric_values.json @@ -22,7 +22,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 8, "w": 12, @@ -36,8 +38,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -45,8 +46,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_metric_values", @@ -73,4 +73,4 @@ "version": 0, "uid": "c01bf42b-b783-4447-a304-8554cee1843b", "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-flamegraph/panel_tests_flame_graph.json b/devenv/dev-dashboards/panel-flamegraph/panel_tests_flame_graph.json index efd4ecdb27c..d4716f38a93 100644 --- a/devenv/dev-dashboards/panel-flamegraph/panel_tests_flame_graph.json +++ b/devenv/dev-dashboards/panel-flamegraph/panel_tests_flame_graph.json @@ -28,7 +28,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 14, "w": 24, @@ -39,8 +41,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "flame_graph" @@ -53,10 +54,7 @@ "refresh": "", "revision": 1, "schemaVersion": 38, - "tags": [ - "gdev", - "panel-tests" - ], + "tags": ["gdev", "panel-tests"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-gauge/gauge-multi-series.json b/devenv/dev-dashboards/panel-gauge/gauge-multi-series.json index f7ff80edc12..e5c9daa44ea 100644 --- a/devenv/dev-dashboards/panel-gauge/gauge-multi-series.json +++ b/devenv/dev-dashboards/panel-gauge/gauge-multi-series.json @@ -18,7 +18,9 @@ "links": [], "panels": [ { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 8, "w": 20, @@ -105,7 +107,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 28, "w": 4, @@ -177,7 +181,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 20, "w": 20, diff --git a/devenv/dev-dashboards/panel-gauge/gauge_tests.json b/devenv/dev-dashboards/panel-gauge/gauge_tests.json index 309a255fcc7..0c8e2651e67 100644 --- a/devenv/dev-dashboards/panel-gauge/gauge_tests.json +++ b/devenv/dev-dashboards/panel-gauge/gauge_tests.json @@ -33,7 +33,9 @@ "type": "row" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -102,7 +104,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -171,7 +175,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -240,7 +246,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -309,7 +317,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -378,7 +388,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -447,7 +459,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -604,7 +618,9 @@ "type": "row" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -683,7 +699,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "should read N/A", "fieldConfig": { "defaults": { @@ -763,7 +781,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "should read N/A", "fieldConfig": { "defaults": { @@ -843,7 +863,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "should read N/A", "fieldConfig": { "defaults": { @@ -946,7 +968,9 @@ "type": "row" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1024,7 +1048,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1103,7 +1129,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1182,7 +1210,9 @@ "type": "gauge" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { diff --git a/devenv/dev-dashboards/panel-geomap/geomap-color-field.json b/devenv/dev-dashboards/panel-geomap/geomap-color-field.json index 38ea1d23b39..e12a4a7210d 100644 --- a/devenv/dev-dashboards/panel-geomap/geomap-color-field.json +++ b/devenv/dev-dashboards/panel-geomap/geomap-color-field.json @@ -28,7 +28,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -135,8 +137,7 @@ { "csvFileName": "flight_info_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -306,9 +307,7 @@ "justifyMode": "auto", "orientation": "auto", "reduceOptions": { - "calcs": [ - "min" - ], + "calcs": ["min"], "fields": "", "values": false }, @@ -367,9 +366,7 @@ "justifyMode": "auto", "orientation": "auto", "reduceOptions": { - "calcs": [ - "max" - ], + "calcs": ["max"], "fields": "", "values": false }, @@ -455,9 +452,7 @@ "options": { "footer": { "fields": "", - "reducer": [ - "max" - ], + "reducer": ["max"], "show": true }, "showHeader": true @@ -478,11 +473,7 @@ } ], "schemaVersion": 37, - "tags": [ - "gdev", - "panel-tests", - "geomap" - ], + "tags": ["gdev", "panel-tests", "geomap"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-geomap/geomap-photo-layer.json b/devenv/dev-dashboards/panel-geomap/geomap-photo-layer.json index af192c66d59..1722a91c739 100644 --- a/devenv/dev-dashboards/panel-geomap/geomap-photo-layer.json +++ b/devenv/dev-dashboards/panel-geomap/geomap-photo-layer.json @@ -29,7 +29,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -117,8 +119,7 @@ { "csvContent": "state,src\nAL,https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Flag_of_Alabama.svg/320px-Flag_of_Alabama.svg.png\nAK,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Flag_of_Alaska.svg/320px-Flag_of_Alaska.svg.png\nAZ,https://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/Flag_of_Arizona.svg/320px-Flag_of_Arizona.svg.png\nAR,https://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/Flag_of_Arkansas.svg/320px-Flag_of_Arkansas.svg.png\nCA,https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Flag_of_California.svg/320px-Flag_of_California.svg.png\nCO,https://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Flag_of_Colorado.svg/320px-Flag_of_Colorado.svg.png\nCT,https://upload.wikimedia.org/wikipedia/commons/thumb/9/96/Flag_of_Connecticut.svg/304px-Flag_of_Connecticut.svg.png\nDE,https://upload.wikimedia.org/wikipedia/commons/thumb/c/c6/Flag_of_Delaware.svg/320px-Flag_of_Delaware.svg.png\nFL,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Flag_of_Florida.svg/320px-Flag_of_Florida.svg.png\nGA,https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/Flag_of_Georgia_%28U.S._state%29.svg/320px-Flag_of_Georgia_%28U.S._state%29.svg.png\nHI,https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Flag_of_Hawaii.svg/320px-Flag_of_Hawaii.svg.png\nID,https://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Flag_of_Idaho.svg/305px-Flag_of_Idaho.svg.png\nIL,https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Flag_of_Illinois.svg/320px-Flag_of_Illinois.svg.png\nIN,https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/Flag_of_Indiana.svg/320px-Flag_of_Indiana.svg.png\nIA,https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Flag_of_Iowa.svg/320px-Flag_of_Iowa.svg.png\nKS,https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Flag_of_Kansas.svg/320px-Flag_of_Kansas.svg.png\nKY,https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Flag_of_Kentucky.svg/320px-Flag_of_Kentucky.svg.png\nLA,https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Flag_of_Louisiana.svg/320px-Flag_of_Louisiana.svg.png\nME,https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/Flag_of_the_State_of_Maine.svg/305px-Flag_of_the_State_of_Maine.svg.png\nMD,https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Flag_of_Maryland.svg/320px-Flag_of_Maryland.svg.png\nMA,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f2/Flag_of_Massachusetts.svg/320px-Flag_of_Massachusetts.svg.png\nMI,https://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/Flag_of_Michigan.svg/320px-Flag_of_Michigan.svg.png\nMN,https://upload.wikimedia.org/wikipedia/commons/thumb/b/b9/Flag_of_Minnesota.svg/320px-Flag_of_Minnesota.svg.png\nMS,https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/Flag_of_Mississippi.svg/320px-Flag_of_Mississippi.svg.png\nMO,https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Flag_of_Missouri.svg/320px-Flag_of_Missouri.svg.png\nMT,https://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/Flag_of_Montana.svg/320px-Flag_of_Montana.svg.png\nNE,https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Flag_of_Nebraska.svg/320px-Flag_of_Nebraska.svg.png\nNV,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f1/Flag_of_Nevada.svg/320px-Flag_of_Nevada.svg.png\nNH,https://upload.wikimedia.org/wikipedia/commons/thumb/2/28/Flag_of_New_Hampshire.svg/320px-Flag_of_New_Hampshire.svg.png\nNJ,https://upload.wikimedia.org/wikipedia/commons/thumb/9/92/Flag_of_New_Jersey.svg/320px-Flag_of_New_Jersey.svg.png\nNM,https://upload.wikimedia.org/wikipedia/commons/thumb/c/c3/Flag_of_New_Mexico.svg/320px-Flag_of_New_Mexico.svg.png\nNY,https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Flag_of_New_York.svg/320px-Flag_of_New_York.svg.png\nNC,https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Flag_of_North_Carolina.svg/320px-Flag_of_North_Carolina.svg.png\nND,https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/Flag_of_North_Dakota.svg/305px-Flag_of_North_Dakota.svg.png\nOH,https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Flag_of_Ohio.svg/320px-Flag_of_Ohio.svg.png\nOK,https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Flag_of_Oklahoma.svg/320px-Flag_of_Oklahoma.svg.png\nOR,https://upload.wikimedia.org/wikipedia/commons/thumb/b/b9/Flag_of_Oregon.svg/320px-Flag_of_Oregon.svg.png\nPA,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Flag_of_Pennsylvania.svg/320px-Flag_of_Pennsylvania.svg.png\nRI,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Flag_of_Rhode_Island.svg/273px-Flag_of_Rhode_Island.svg.png\nSC,https://upload.wikimedia.org/wikipedia/commons/thumb/6/69/Flag_of_South_Carolina.svg/320px-Flag_of_South_Carolina.svg.png\nSD,https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Flag_of_South_Dakota.svg/320px-Flag_of_South_Dakota.svg.png\nTN,https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Flag_of_Tennessee.svg/320px-Flag_of_Tennessee.svg.png\nTX,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Flag_of_Texas.svg/320px-Flag_of_Texas.svg.png\nUT,https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Flag_of_Utah.svg/320px-Flag_of_Utah.svg.png\nVT,https://upload.wikimedia.org/wikipedia/commons/thumb/4/49/Flag_of_Vermont.svg/320px-Flag_of_Vermont.svg.png\nVA,https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/Flag_of_Virginia.svg/320px-Flag_of_Virginia.svg.png\nWA,https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/Flag_of_Washington.svg/320px-Flag_of_Washington.svg.png\nWV,https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Flag_of_West_Virginia.svg/320px-Flag_of_West_Virginia.svg.png\nWI,https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Flag_of_Wisconsin.svg/320px-Flag_of_Wisconsin.svg.png\nWY,https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Flag_of_Wyoming.svg/320px-Flag_of_Wyoming.svg.png\n", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" diff --git a/devenv/dev-dashboards/panel-geomap/geomap-route-layer.json b/devenv/dev-dashboards/panel-geomap/geomap-route-layer.json index 169ca0163c5..8307558b992 100644 --- a/devenv/dev-dashboards/panel-geomap/geomap-route-layer.json +++ b/devenv/dev-dashboards/panel-geomap/geomap-route-layer.json @@ -76,8 +76,7 @@ { "csvContent": "lat,lon,val\n-5,2,0\n1,5,25\n6,10,50\n9,15,75\n10,20,100", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -86,13 +85,14 @@ "scenarioId": "csv_content", "refId": "B", "datasource": { - "uid": "PD8C576611E62080A", "type": "grafana-testdata-datasource" }, "csvContent": "lat,lon,alt\n45,0,0\n40,5,5\n35,10,10\n30,15, 15\n25,20,20" } ], - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "options": { "view": { "allLayers": true, diff --git a/devenv/dev-dashboards/panel-geomap/geomap-spatial-operations-transformer.json b/devenv/dev-dashboards/panel-geomap/geomap-spatial-operations-transformer.json index 0bd5732b577..64fd0589c45 100644 --- a/devenv/dev-dashboards/panel-geomap/geomap-spatial-operations-transformer.json +++ b/devenv/dev-dashboards/panel-geomap/geomap-spatial-operations-transformer.json @@ -28,7 +28,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -88,8 +90,7 @@ { "csvFileName": "flight_info_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -100,11 +101,7 @@ } ], "schemaVersion": 37, - "tags": [ - "gdev", - "panel-tests", - "geomap" - ], + "tags": ["gdev", "panel-tests", "geomap"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-geomap/geomap-v91.json b/devenv/dev-dashboards/panel-geomap/geomap-v91.json index d9a928ceba1..1bec4865743 100644 --- a/devenv/dev-dashboards/panel-geomap/geomap-v91.json +++ b/devenv/dev-dashboards/panel-geomap/geomap-v91.json @@ -28,7 +28,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -106,8 +108,7 @@ { "csvFileName": "flight_info_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -115,8 +116,7 @@ { "csvFileName": "population_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_file" @@ -126,7 +126,9 @@ "type": "geomap" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -209,7 +211,9 @@ "type": "geomap" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -311,8 +315,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "simulation", @@ -329,11 +332,7 @@ } ], "schemaVersion": 37, - "tags": [ - "gdev", - "panel-tests", - "geomap" - ], + "tags": ["gdev", "panel-tests", "geomap"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-geomap/geomap_multi-layers.json b/devenv/dev-dashboards/panel-geomap/geomap_multi-layers.json index 8cecfcab846..e7be37b67a2 100644 --- a/devenv/dev-dashboards/panel-geomap/geomap_multi-layers.json +++ b/devenv/dev-dashboards/panel-geomap/geomap_multi-layers.json @@ -29,7 +29,7 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -319,7 +319,7 @@ "type": "geomap" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -431,11 +431,7 @@ } ], "schemaVersion": 36, - "tags": [ - "gdev", - "panel-tests", - "geomap" - ], + "tags": ["gdev", "panel-tests", "geomap"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-geomap/panel-geomap.json b/devenv/dev-dashboards/panel-geomap/panel-geomap.json index 70f1595204f..bda6377ffff 100644 --- a/devenv/dev-dashboards/panel-geomap/panel-geomap.json +++ b/devenv/dev-dashboards/panel-geomap/panel-geomap.json @@ -28,7 +28,7 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -127,7 +127,7 @@ "type": "geomap" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -230,7 +230,7 @@ "type": "geomap" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -325,7 +325,7 @@ "type": "geomap" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -427,11 +427,7 @@ ], "refresh": "", "schemaVersion": 37, - "tags": [ - "gdev", - "panel-tests", - "geomap" - ], + "tags": ["gdev", "panel-tests", "geomap"], "templating": { "list": [] }, @@ -440,17 +436,7 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "", "title": "Panel Tests - Geomap", diff --git a/devenv/dev-dashboards/panel-graph/graph-shared-tooltips.json b/devenv/dev-dashboards/panel-graph/graph-shared-tooltips.json index 187d61b443f..6c06ee04db5 100644 --- a/devenv/dev-dashboards/panel-graph/graph-shared-tooltips.json +++ b/devenv/dev-dashboards/panel-graph/graph-shared-tooltips.json @@ -759,11 +759,7 @@ ], "refresh": false, "schemaVersion": 28, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-graph/graph-time-regions.json b/devenv/dev-dashboards/panel-graph/graph-time-regions.json index a4e03148536..c9661011d36 100644 --- a/devenv/dev-dashboards/panel-graph/graph-time-regions.json +++ b/devenv/dev-dashboards/panel-graph/graph-time-regions.json @@ -22,7 +22,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 2, "gridPos": { "h": 8, @@ -118,7 +120,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 2, "gridPos": { "h": 8, @@ -219,7 +223,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 2, "gridPos": { "h": 8, @@ -375,7 +381,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 2, "gridPos": { "h": 8, @@ -469,7 +477,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 8, diff --git a/devenv/dev-dashboards/panel-graph/graph_tests.json b/devenv/dev-dashboards/panel-graph/graph_tests.json index bd1fc95d3d6..fa214400e77 100644 --- a/devenv/dev-dashboards/panel-graph/graph_tests.json +++ b/devenv/dev-dashboards/panel-graph/graph_tests.json @@ -22,7 +22,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fill": 1, @@ -108,7 +110,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fill": 1, @@ -194,7 +198,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fill": 1, @@ -280,7 +286,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fill": 1, @@ -382,7 +390,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fill": 1, @@ -495,7 +505,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fill": 1, @@ -581,7 +593,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fill": 1, @@ -683,7 +697,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fill": 1, @@ -807,7 +823,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fill": 1, @@ -932,7 +950,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fill": 0, @@ -1049,7 +1069,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": 3, "fill": 1, "gridPos": { @@ -1134,7 +1156,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": 3, "fill": 1, "gridPos": { @@ -1237,7 +1261,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": 3, "fill": 1, "gridPos": { @@ -1376,7 +1402,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": 3, "fill": 1, "gridPos": { @@ -1480,7 +1508,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": 3, "fill": 1, "gridPos": { diff --git a/devenv/dev-dashboards/panel-heatmap/heatmap-calculate-log.json b/devenv/dev-dashboards/panel-heatmap/heatmap-calculate-log.json index f48358f7a02..26764802b06 100644 --- a/devenv/dev-dashboards/panel-heatmap/heatmap-calculate-log.json +++ b/devenv/dev-dashboards/panel-heatmap/heatmap-calculate-log.json @@ -28,7 +28,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -101,8 +103,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "max": 500000, "min": 0.01, @@ -807,11 +808,7 @@ } ], "schemaVersion": 36, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-heatmap/heatmap-legacy.json b/devenv/dev-dashboards/panel-heatmap/heatmap-legacy.json index d42005d2a59..03a4c72a0e9 100644 --- a/devenv/dev-dashboards/panel-heatmap/heatmap-legacy.json +++ b/devenv/dev-dashboards/panel-heatmap/heatmap-legacy.json @@ -40,7 +40,9 @@ "mode": "opacity" }, "dataFormat": "tsbuckets", - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 11, "w": 7, @@ -58,8 +60,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "exponential_heatmap_bucket_data" @@ -93,7 +94,9 @@ "mode": "spectrum" }, "dataFormat": "timeseries", - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 11, "w": 9, @@ -111,8 +114,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "max": 70, "min": 10, @@ -151,7 +153,9 @@ "mode": "spectrum" }, "dataFormat": "timeseries", - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 11, "w": 8, @@ -169,8 +173,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "exponential_heatmap_bucket_data" @@ -204,7 +207,9 @@ "mode": "opacity" }, "dataFormat": "tsbuckets", - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 11, "w": 7, @@ -222,8 +227,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "exponential_heatmap_bucket_data" @@ -315,7 +319,9 @@ "mode": "spectrum" }, "dataFormat": "timeseries", - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 11, "w": 8, @@ -333,8 +339,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "exponential_heatmap_bucket_data" @@ -360,11 +365,7 @@ } ], "schemaVersion": 36, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-heatmap/heatmap-x.json b/devenv/dev-dashboards/panel-heatmap/heatmap-x.json index ab4a499b23c..a43e78ddb69 100644 --- a/devenv/dev-dashboards/panel-heatmap/heatmap-x.json +++ b/devenv/dev-dashboards/panel-heatmap/heatmap-x.json @@ -1,324 +1,315 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 116, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 10, - "x": 0, - "y": 0 - }, - "id": 2, - "options": { - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "9.4.0-pre", - "targets": [ - { - "csvContent": "x,y1,y2\n1,8,12\n2,6,13\n3,7,9\n5,9,7\n6,5,9", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "Raw heatmap rows", - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 14, - "x": 10, - "y": 0 - }, - "id": 4, - "options": { - "calculate": false, - "cellGap": 1, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Oranges", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false - } - }, - "pluginVersion": "9.4.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A" - } - ], - "title": "Row heatmap", - "type": "heatmap" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 10, - "x": 0, - "y": 9 - }, - "id": 5, - "options": { - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "9.4.0-pre", - "targets": [ - { - "csvContent": "x,y,count\n1,4,10\n1,6,11\n2,5,30\n2,4,22\n3,6,17", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "Raw heatmap cells", - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 14, - "x": 10, - "y": 9 - }, - "id": 6, - "options": { - "calculate": false, - "cellGap": 1, - "color": { - "exponent": 0.5, - "fill": "dark-orange", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Oranges", - "steps": 64 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": true - }, - "rowsFrame": { - "layout": "auto" - }, - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false - } - }, - "pluginVersion": "9.4.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 5, - "refId": "A" - } - ], - "title": "Cells heatmap", - "type": "heatmap" + "type": "dashboard" } - ], - "schemaVersion": 37, - "tags": [], - "templating": { - "list": [] + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 116, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 10, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.4.0-pre", + "targets": [ + { + "csvContent": "x,y1,y2\n1,8,12\n2,6,13\n3,7,9\n5,9,7\n6,5,9", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Raw heatmap rows", + "type": "table" }, - "time": { - "from": "now-6h", - "to": "now" + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 14, + "x": 10, + "y": 0 + }, + "id": 4, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Oranges", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false + } + }, + "pluginVersion": "9.4.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "title": "Row heatmap", + "type": "heatmap" }, - "timepicker": {}, - "timezone": "", - "title": "Heatmap X axis", - "uid": "5Y0jv6pVz", - "version": 3, - "weekStart": "" - } - + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 10, + "x": 0, + "y": 9 + }, + "id": 5, + "options": { + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.4.0-pre", + "targets": [ + { + "csvContent": "x,y,count\n1,4,10\n1,6,11\n2,5,30\n2,4,22\n3,6,17", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Raw heatmap cells", + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 14, + "x": 10, + "y": 9 + }, + "id": 6, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Oranges", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false + } + }, + "pluginVersion": "9.4.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 5, + "refId": "A" + } + ], + "title": "Cells heatmap", + "type": "heatmap" + } + ], + "schemaVersion": 37, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Heatmap X axis", + "uid": "5Y0jv6pVz", + "version": 3, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/panel-histogram/histogram_tests.json b/devenv/dev-dashboards/panel-histogram/histogram_tests.json index eb5d6374971..af6127cb447 100644 --- a/devenv/dev-dashboards/panel-histogram/histogram_tests.json +++ b/devenv/dev-dashboards/panel-histogram/histogram_tests.json @@ -28,7 +28,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -72,9 +74,7 @@ "bucketOffset": 0, "combine": false, "legend": { - "calcs": [ - "sum" - ], + "calcs": ["sum"], "displayMode": "list", "placement": "bottom", "showLegend": true @@ -83,8 +83,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -143,9 +142,7 @@ "bucketSize": 3, "combine": false, "legend": { - "calcs": [ - "sum" - ], + "calcs": ["sum"], "displayMode": "list", "placement": "bottom", "showLegend": true @@ -165,7 +162,9 @@ "type": "histogram" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -210,9 +209,7 @@ "bucketSize": 1, "combine": false, "legend": { - "calcs": [ - "sum" - ], + "calcs": ["sum"], "displayMode": "list", "placement": "bottom", "showLegend": true @@ -222,8 +219,7 @@ { "csvFileName": "weight_height.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -235,9 +231,7 @@ "id": "filterFieldsByName", "options": { "include": { - "names": [ - "Height" - ] + "names": ["Height"] } } } @@ -245,7 +239,9 @@ "type": "histogram" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -290,9 +286,7 @@ "bucketSize": 5, "combine": false, "legend": { - "calcs": [ - "sum" - ], + "calcs": ["sum"], "displayMode": "list", "placement": "bottom", "showLegend": true @@ -302,8 +296,7 @@ { "csvFileName": "weight_height.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -315,9 +308,7 @@ "id": "filterFieldsByName", "options": { "include": { - "names": [ - "Weight" - ] + "names": ["Weight"] } } } @@ -325,7 +316,9 @@ "type": "histogram" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -367,9 +360,7 @@ "footer": { "countRows": false, "fields": [], - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true, @@ -385,8 +376,7 @@ { "csvFileName": "weight_height.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -399,9 +389,7 @@ "id": "filterFieldsByName", "options": { "include": { - "names": [ - "Height" - ] + "names": ["Height"] } } }, @@ -417,7 +405,9 @@ "type": "table" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -459,9 +449,7 @@ "footer": { "countRows": false, "fields": [], - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -471,8 +459,7 @@ { "csvFileName": "weight_height.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -484,9 +471,7 @@ "id": "filterFieldsByName", "options": { "include": { - "names": [ - "Weight" - ] + "names": ["Weight"] } } }, @@ -501,7 +486,9 @@ "type": "table" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -560,9 +547,7 @@ "options": { "bucketOffset": 0, "legend": { - "calcs": [ - "sum" - ], + "calcs": ["sum"], "displayMode": "list", "placement": "bottom", "showLegend": true @@ -572,8 +557,7 @@ { "csvContent": "xMin,xMax,count1,abcd\n1,2,10,123\n2,3,20,265\n3,4,30,73\n4,5,10,24", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -583,7 +567,9 @@ "type": "histogram" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -642,9 +628,7 @@ "options": { "bucketOffset": 0, "legend": { - "calcs": [ - "sum" - ], + "calcs": ["sum"], "displayMode": "list", "placement": "bottom", "showLegend": true @@ -654,8 +638,7 @@ { "csvContent": "xMin,count1,abcd\n1,10,123\n2,20,265\n3,30,73\n4,10,24", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -665,7 +648,9 @@ "type": "histogram" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -724,9 +709,7 @@ "options": { "bucketOffset": 0, "legend": { - "calcs": [ - "sum" - ], + "calcs": ["sum"], "displayMode": "list", "placement": "bottom", "showLegend": true @@ -736,8 +719,7 @@ { "csvContent": "xMax,count1,abcd\n1,10,123\n2,20,265\n3,30,73\n4,10,24", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -748,8 +730,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -802,8 +783,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"meta\": {\n \"custom\": {\n \"resultType\": \"matrix\"\n },\n \"type\": \"heatmap-rows\",\n \"typeVersion\": [\n 0,\n 1\n ]\n },\n \"name\": \"0.005\",\n \"fields\": [\n {\n \"config\": {\n \"interval\": 1200000\n },\n \"name\": \"Time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"0.005\"\n },\n \"labels\": {\n \"le\": \"0.005\"\n },\n \"name\": \"0.005\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"0.01\"\n },\n \"labels\": {\n \"le\": \"0.01\"\n },\n \"name\": \"0.01\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"0.025\"\n },\n \"labels\": {\n \"le\": \"0.025\"\n },\n \"name\": \"0.025\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"0.05\"\n },\n \"labels\": {\n \"le\": \"0.05\"\n },\n \"name\": \"0.05\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"0.1\"\n },\n \"labels\": {\n \"le\": \"0.1\"\n },\n \"name\": \"0.1\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"0.25\"\n },\n \"labels\": {\n \"le\": \"0.25\"\n },\n \"name\": \"0.25\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"0.5\"\n },\n \"labels\": {\n \"le\": \"0.5\"\n },\n \"name\": \"0.5\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"1.0\"\n },\n \"labels\": {\n \"le\": \"1.0\"\n },\n \"name\": \"1.0\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"2.5\"\n },\n \"labels\": {\n \"le\": \"2.5\"\n },\n \"name\": \"2.5\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"5.0\"\n },\n \"labels\": {\n \"le\": \"5.0\"\n },\n \"name\": \"5.0\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"10.0\"\n },\n \"labels\": {\n \"le\": \"10.0\"\n },\n \"name\": \"10.0\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"25.0\"\n },\n \"labels\": {\n \"le\": \"25.0\"\n },\n \"name\": \"25.0\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"50.0\"\n },\n \"labels\": {\n \"le\": \"50.0\"\n },\n \"name\": \"50.0\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"100.0\"\n },\n \"labels\": {\n \"le\": \"100.0\"\n },\n \"name\": \"100.0\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n },\n {\n \"config\": {\n \"displayNameFromDS\": \"+Inf\"\n },\n \"labels\": {\n \"le\": \"+Inf\"\n },\n \"name\": \"+Inf\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1706456400000,\n 1706457600000,\n 1706458800000,\n 1706460000000,\n 1706461200000,\n 1706462400000,\n 1706463600000,\n 1706464800000,\n 1706466000000,\n 1706467200000,\n 1706468400000,\n 1706469600000,\n 1706470800000,\n 1706472000000,\n 1706473200000,\n 1706474400000,\n 1706475600000,\n 1706476800000,\n 1706478000000\n ],\n [\n 0.19357429718875502,\n 0.18072289156626506,\n 0.18313253012048192,\n 0.18955823293172688,\n 0.18634538152610441,\n 0.19518072289156624,\n 0.20080321285140562,\n 0.18313253012048192,\n 0.19678714859437751,\n 0.18795180722891563,\n 0.18473895582329317,\n 0.19357429718875502,\n 0.19116465863453813,\n 0.19196787148594374,\n 0.19437751004016063,\n 0.19759036144578312,\n 0.19839357429718874,\n 0.19357429718875502,\n 0.18634538152610441\n ],\n [\n 0.22248995983935738,\n 0.229718875502008,\n 0.22248995983935738,\n 0.22168674698795174,\n 0.2305220883534136,\n 0.21285140562248994,\n 0.2128514056224899,\n 0.22891566265060237,\n 0.22570281124497987,\n 0.22088353413654616,\n 0.22088353413654618,\n 0.21927710843373488,\n 0.21686746987951805,\n 0.22248995983935738,\n 0.21847389558232927,\n 0.21124497991967867,\n 0.216867469879518,\n 0.2200803212851405,\n 0.22329317269076304\n ],\n [\n 0.017670682730923704,\n 0.02329317269076303,\n 0.027309236947791138,\n 0.02168674698795181,\n 0.016867469879518093,\n 0.025702811244979917,\n 0.02008032128514059,\n 0.018473895582329314,\n 0.01124497991967871,\n 0.024899598393574307,\n 0.025702811244979862,\n 0.0208835341365462,\n 0.02409638554216864,\n 0.01927710843373498,\n 0.0208835341365462,\n 0.02248995983935742,\n 0.016867469879518093,\n 0.02008032128514059,\n 0.02329317269076303\n ],\n [\n 0,\n 0,\n 0.0008032128514056658,\n 0.0008032128514056658,\n 0,\n 0,\n 0,\n 0.0032128514056224966,\n 0,\n 0,\n 0.0024096385542168863,\n 0,\n 0.001606425702811276,\n 0,\n 0,\n 0.0024096385542168863,\n 0.001606425702811276,\n 0,\n 0.0008032128514056103\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665,\n 0.06666666666666665\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ]\n ]\n }\n }\n]", "refId": "A", @@ -815,8 +795,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -882,8 +861,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"meta\": {\n \"type\": \"heatmap-cells\",\n \"typeVersion\": [\n 0,\n 0\n ],\n \"executedQueryString\": \"Expr: sum(rate(cortex_request_duration_seconds{container=~\\\"compactor\\\", route=~\\\"(debug_pprof|metrics|ready)\\\"}[4m0s]))\\nStep: 1m0s\",\n \"preferredVisualisationType\": \"graph\"\n },\n \"fields\": [\n {\n \"name\": \"xMax\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\"\n },\n \"config\": {\n \"interval\": 60000\n }\n },\n {\n \"name\": \"yMin\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n },\n \"labels\": {},\n \"config\": {\n \"displayNameFromDS\": \"sum(rate(cortex_request_duration_seconds{container=~\\\"compactor\\\", route=~\\\"(debug_pprof|metrics|ready)\\\"}[4m0s]))\"\n }\n },\n {\n \"name\": \"yMax\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n },\n \"config\": {}\n },\n {\n \"name\": \"count\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\"\n },\n \"config\": {}\n },\n {\n \"name\": \"yLayout\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"int8\"\n },\n \"config\": {}\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483460000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483520000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483580000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483640000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483700000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000,\n 1706483760000\n ],\n [\n 0.000012831061023768835,\n 0.000013992371264719713,\n 0.000016639827463764308,\n 0.0000181458605194507,\n 0.000019788201212326197,\n 0.000021579186437577742,\n 0.00002566212204753767,\n 0.000039576402424652394,\n 0.00020529697638030136,\n 0.0002238779402355154,\n 0.00026623723942022893,\n 0.0002903337683112112,\n 0.00031661121939721915,\n 0.00048828125,\n 0.002532889755177753,\n 0.002762135864009951,\n 0.00390625,\n 0.004259795830723663,\n 0.004645340292979379,\n 0.005065779510355506,\n 0.005524271728019902,\n 0.0060242610367497685,\n 0.006569503244169644,\n 0.007164094087536493,\n 0.0078125,\n 0.009290680585958758,\n 0.010131559020711013,\n 0.012048522073499537,\n 0.014328188175072986,\n 0.01703918332289465,\n 0.018581361171917516,\n 0.020263118041422026,\n 13.45434264405943,\n 0.000012831061023768835,\n 0.000013992371264719713,\n 0.000016639827463764308,\n 0.0000181458605194507,\n 0.000019788201212326197,\n 0.000021579186437577742,\n 0.00002566212204753767,\n 0.000039576402424652394,\n 0.0002238779402355154,\n 0.000244140625,\n 0.00026623723942022893,\n 0.0002903337683112112,\n 0.00048828125,\n 0.0021298979153618314,\n 0.002532889755177753,\n 0.002762135864009951,\n 0.00390625,\n 0.004259795830723663,\n 0.004645340292979379,\n 0.005065779510355506,\n 0.005524271728019902,\n 0.0060242610367497685,\n 0.006569503244169644,\n 0.007164094087536493,\n 0.0078125,\n 0.009290680585958758,\n 0.010131559020711013,\n 0.011048543456039804,\n 0.012048522073499537,\n 0.014328188175072986,\n 0.01703918332289465,\n 13.45434264405943,\n 0.000012831061023768835,\n 0.000013992371264719713,\n 0.000016639827463764308,\n 0.0000181458605194507,\n 0.000019788201212326197,\n 0.000021579186437577742,\n 0.00002566212204753767,\n 0.000244140625,\n 0.00026623723942022893,\n 0.0002903337683112112,\n 0.0021298979153618314,\n 0.002532889755177753,\n 0.002762135864009951,\n 0.00390625,\n 0.004259795830723663,\n 0.004645340292979379,\n 0.005065779510355506,\n 0.005524271728019902,\n 0.0060242610367497685,\n 0.006569503244169644,\n 0.007164094087536493,\n 0.0078125,\n 0.009290680585958758,\n 0.010131559020711013,\n 0.011048543456039804,\n 0.012048522073499537,\n 0.014328188175072986,\n 0.01703918332289465,\n 13.45434264405943,\n 0.000012831061023768835,\n 0.000013992371264719713,\n 0.0000152587890625,\n 0.000016639827463764308,\n 0.0000181458605194507,\n 0.000019788201212326197,\n 0.000021579186437577742,\n 0.00002566212204753767,\n 0.000244140625,\n 0.00026623723942022893,\n 0.0002903337683112112,\n 0.0021298979153618314,\n 0.002762135864009951,\n 0.00390625,\n 0.004259795830723663,\n 0.004645340292979379,\n 0.005065779510355506,\n 0.005524271728019902,\n 0.0060242610367497685,\n 0.006569503244169644,\n 0.007164094087536493,\n 0.0078125,\n 0.008519591661447326,\n 0.009290680585958758,\n 0.010131559020711013,\n 0.011048543456039804,\n 0.012048522073499537,\n 0.014328188175072986,\n 0.01703918332289465,\n 13.45434264405943,\n 0.000012831061023768835,\n 0.000013992371264719713,\n 0.0000152587890625,\n 0.000016639827463764308,\n 0.0000181458605194507,\n 0.000019788201212326197,\n 0.000021579186437577742,\n 0.00002566212204753767,\n 0.000244140625,\n 0.00026623723942022893,\n 0.0002903337683112112,\n 0.0005806675366224224,\n 0.0021298979153618314,\n 0.002762135864009951,\n 0.00390625,\n 0.004259795830723663,\n 0.004645340292979379,\n 0.005065779510355506,\n 0.005524271728019902,\n 0.0060242610367497685,\n 0.006569503244169644,\n 0.007164094087536493,\n 0.0078125,\n 0.008519591661447326,\n 0.009290680585958758,\n 0.010131559020711013,\n 0.011048543456039804,\n 0.015625,\n 13.45434264405943,\n 0.000012831061023768835,\n 0.000013992371264719713,\n 0.0000152587890625,\n 0.000016639827463764308,\n 0.0000181458605194507,\n 0.000019788201212326197,\n 0.000021579186437577742,\n 0.00002566212204753767,\n 0.000244140625,\n 0.00026623723942022893,\n 0.0002903337683112112,\n 0.00031661121939721915,\n 0.0003452669830012439,\n 0.0005806675366224224,\n 0.0021298979153618314,\n 0.002762135864009951,\n 0.00390625,\n 0.004259795830723663,\n 0.004645340292979379,\n 0.005065779510355506,\n 0.005524271728019902,\n 0.0060242610367497685,\n 0.006569503244169644,\n 0.007164094087536493,\n 0.0078125,\n 0.008519591661447326,\n 0.009290680585958758,\n 0.010131559020711013,\n 0.011048543456039804,\n 0.015625,\n 13.45434264405943\n ],\n [\n 0.000013992371264719713,\n 0.0000152587890625,\n 0.0000181458605194507,\n 0.000019788201212326197,\n 0.000021579186437577742,\n 0.000023532269674803783,\n 0.000027984742529439426,\n 0.000043158372875155485,\n 0.0002238779402355154,\n 0.000244140625,\n 0.0002903337683112112,\n 0.00031661121939721915,\n 0.0003452669830012439,\n 0.0005324744788404579,\n 0.002762135864009951,\n 0.0030121305183748843,\n 0.004259795830723663,\n 0.004645340292979379,\n 0.005065779510355506,\n 0.005524271728019902,\n 0.0060242610367497685,\n 0.006569503244169644,\n 0.007164094087536493,\n 0.0078125,\n 0.008519591661447326,\n 0.010131559020711013,\n 0.011048543456039804,\n 0.013139006488339287,\n 0.015625,\n 0.018581361171917516,\n 0.020263118041422026,\n 0.022097086912079608,\n 14.672064691274738,\n 0.000013992371264719713,\n 0.0000152587890625,\n 0.0000181458605194507,\n 0.000019788201212326197,\n 0.000021579186437577742,\n 0.000023532269674803783,\n 0.000027984742529439426,\n 0.000043158372875155485,\n 0.000244140625,\n 0.00026623723942022893,\n 0.0002903337683112112,\n 0.00031661121939721915,\n 0.0005324744788404579,\n 0.0023226701464896895,\n 0.002762135864009951,\n 0.0030121305183748843,\n 0.004259795830723663,\n 0.004645340292979379,\n 0.005065779510355506,\n 0.005524271728019902,\n 0.0060242610367497685,\n 0.006569503244169644,\n 0.007164094087536493,\n 0.0078125,\n 0.008519591661447326,\n 0.010131559020711013,\n 0.011048543456039804,\n 0.012048522073499537,\n 0.013139006488339287,\n 0.015625,\n 0.018581361171917516,\n 14.672064691274738,\n 0.000013992371264719713,\n 0.0000152587890625,\n 0.0000181458605194507,\n 0.000019788201212326197,\n 0.000021579186437577742,\n 0.000023532269674803783,\n 0.000027984742529439426,\n 0.00026623723942022893,\n 0.0002903337683112112,\n 0.00031661121939721915,\n 0.0023226701464896895,\n 0.002762135864009951,\n 0.0030121305183748843,\n 0.004259795830723663,\n 0.004645340292979379,\n 0.005065779510355506,\n 0.005524271728019902,\n 0.0060242610367497685,\n 0.006569503244169644,\n 0.007164094087536493,\n 0.0078125,\n 0.008519591661447326,\n 0.010131559020711013,\n 0.011048543456039804,\n 0.012048522073499537,\n 0.013139006488339287,\n 0.015625,\n 0.018581361171917516,\n 14.672064691274738,\n 0.000013992371264719713,\n 0.0000152587890625,\n 0.000016639827463764308,\n 0.0000181458605194507,\n 0.000019788201212326197,\n 0.000021579186437577742,\n 0.000023532269674803783,\n 0.000027984742529439426,\n 0.00026623723942022893,\n 0.0002903337683112112,\n 0.00031661121939721915,\n 0.0023226701464896895,\n 0.0030121305183748843,\n 0.004259795830723663,\n 0.004645340292979379,\n 0.005065779510355506,\n 0.005524271728019902,\n 0.0060242610367497685,\n 0.006569503244169644,\n 0.007164094087536493,\n 0.0078125,\n 0.008519591661447326,\n 0.009290680585958758,\n 0.010131559020711013,\n 0.011048543456039804,\n 0.012048522073499537,\n 0.013139006488339287,\n 0.015625,\n 0.018581361171917516,\n 14.672064691274738,\n 0.000013992371264719713,\n 0.0000152587890625,\n 0.000016639827463764308,\n 0.0000181458605194507,\n 0.000019788201212326197,\n 0.000021579186437577742,\n 0.000023532269674803783,\n 0.000027984742529439426,\n 0.00026623723942022893,\n 0.0002903337683112112,\n 0.00031661121939721915,\n 0.0006332224387944383,\n 0.0023226701464896895,\n 0.0030121305183748843,\n 0.004259795830723663,\n 0.004645340292979379,\n 0.005065779510355506,\n 0.005524271728019902,\n 0.0060242610367497685,\n 0.006569503244169644,\n 0.007164094087536493,\n 0.0078125,\n 0.008519591661447326,\n 0.009290680585958758,\n 0.010131559020711013,\n 0.011048543456039804,\n 0.012048522073499537,\n 0.01703918332289465,\n 14.672064691274738,\n 0.000013992371264719713,\n 0.0000152587890625,\n 0.000016639827463764308,\n 0.0000181458605194507,\n 0.000019788201212326197,\n 0.000021579186437577742,\n 0.000023532269674803783,\n 0.000027984742529439426,\n 0.00026623723942022893,\n 0.0002903337683112112,\n 0.00031661121939721915,\n 0.0003452669830012439,\n 0.00037651631479686053,\n 0.0006332224387944383,\n 0.0023226701464896895,\n 0.0030121305183748843,\n 0.004259795830723663,\n 0.004645340292979379,\n 0.005065779510355506,\n 0.005524271728019902,\n 0.0060242610367497685,\n 0.006569503244169644,\n 0.007164094087536493,\n 0.0078125,\n 0.008519591661447326,\n 0.009290680585958758,\n 0.010131559020711013,\n 0.011048543456039804,\n 0.012048522073499537,\n 0.01703918332289465,\n 14.672064691274738\n ],\n [\n 0.0044444444444444444,\n 0.017777777777777778,\n 0.0044444444444444444,\n 0.035555555555555556,\n 0.017777777777777778,\n 0.013333333333333332,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.017777777777777778,\n 0.03111111111111111,\n 0.013333333333333332,\n 0.05333333333333334,\n 0.035555555555555556,\n 0.022222222222222223,\n 0.022222222222222223,\n 0.022222222222222223,\n 0.017777777777777778,\n 0.013333333333333332,\n 0.013333333333333332,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.06666666666666667,\n 0.008888888888888889,\n 0.017777777777777778,\n 0.008888888888888889,\n 0.04,\n 0.0044444444444444444,\n 0.013333333333333332,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.013333333333333332,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.026666666666666665,\n 0.035555555555555556,\n 0.008888888888888889,\n 0.044444444444444446,\n 0.035555555555555556,\n 0.026666666666666665,\n 0.022222222222222223,\n 0.022222222222222223,\n 0.013333333333333332,\n 0.008888888888888889,\n 0.017777777777777778,\n 0.0044444444444444444,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.06666666666666667,\n 0.008888888888888889,\n 0.017777777777777778,\n 0.017777777777777778,\n 0.04,\n 0.0044444444444444444,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.008888888888888889,\n 0.017777777777777778,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.008888888888888889,\n 0.022222222222222223,\n 0.03111111111111111,\n 0.008888888888888889,\n 0.044444444444444446,\n 0.035555555555555556,\n 0.026666666666666665,\n 0.026666666666666665,\n 0.022222222222222223,\n 0.017777777777777778,\n 0.008888888888888889,\n 0.017777777777777778,\n 0.0044444444444444444,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.06666666666666667,\n 0.008888888888888889,\n 0.017777777777777778,\n 0.0044444444444444444,\n 0.017777777777777778,\n 0.03111111111111111,\n 0.008888888888888889,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.008888888888888889,\n 0.013333333333333332,\n 0.008888888888888889,\n 0.008888888888888889,\n 0.008888888888888889,\n 0.022222222222222223,\n 0.013333333333333332,\n 0.008888888888888889,\n 0.044444444444444446,\n 0.04,\n 0.022222222222222223,\n 0.022222222222222223,\n 0.022222222222222223,\n 0.03111111111111111,\n 0.0044444444444444444,\n 0.013333333333333332,\n 0.017777777777777778,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.06666666666666667,\n 0.008888888888888889,\n 0.026666666666666665,\n 0.0044444444444444444,\n 0.013333333333333332,\n 0.022222222222222223,\n 0.008888888888888889,\n 0.013333333333333332,\n 0.0044444444444444444,\n 0.008888888888888889,\n 0.008888888888888889,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.008888888888888889,\n 0.008888888888888889,\n 0.026666666666666665,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.035555555555555556,\n 0.057777777777777775,\n 0.026666666666666665,\n 0.03111111111111111,\n 0.03111111111111111,\n 0.022222222222222223,\n 0.0044444444444444444,\n 0.013333333333333332,\n 0.013333333333333332,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.06666666666666667,\n 0.0044444444444444444,\n 0.026666666666666665,\n 0.0044444444444444444,\n 0.022222222222222223,\n 0.022222222222222223,\n 0.0044444444444444444,\n 0.013333333333333332,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.013333333333333332,\n 0.017777777777777778,\n 0.013333333333333332,\n 0.008888888888888889,\n 0.035555555555555556,\n 0.05333333333333333,\n 0.022222222222222223,\n 0.026666666666666665,\n 0.035555555555555556,\n 0.022222222222222223,\n 0.008888888888888889,\n 0.02222222222222222,\n 0.008888888888888889,\n 0.0044444444444444444,\n 0.0044444444444444444,\n 0.06666666666666667\n ],\n [\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0,\n 0\n ]\n ]\n }\n }\n]", "refId": "A", @@ -896,11 +874,7 @@ ], "refresh": "", "schemaVersion": 39, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-piechart/panel_test_piechart.json b/devenv/dev-dashboards/panel-piechart/panel_test_piechart.json index e076384f273..4333993ea8e 100644 --- a/devenv/dev-dashboards/panel-piechart/panel_test_piechart.json +++ b/devenv/dev-dashboards/panel-piechart/panel_test_piechart.json @@ -53,9 +53,7 @@ }, "id": 2, "options": { - "displayLabels": [ - "name" - ], + "displayLabels": ["name"], "legend": { "values": [], "displayMode": "list", @@ -63,9 +61,7 @@ }, "pieType": "donut", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -122,22 +118,15 @@ }, "id": 11, "options": { - "displayLabels": [ - "name", - "percent" - ], + "displayLabels": ["name", "percent"], "legend": { - "values": [ - "percent" - ], + "values": ["percent"], "displayMode": "list", "placement": "right" }, "pieType": "pie", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -192,9 +181,7 @@ }, "id": 8, "options": { - "displayLabels": [ - "name" - ], + "displayLabels": ["name"], "legend": { "values": [], "displayMode": "hidden", @@ -202,9 +189,7 @@ }, "pieType": "pie", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -259,21 +244,15 @@ }, "id": 3, "options": { - "displayLabels": [ - "percent" - ], + "displayLabels": ["percent"], "legend": { - "values": [ - "percent" - ], + "values": ["percent"], "displayMode": "table", "placement": "bottom" }, "pieType": "pie", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -328,21 +307,15 @@ }, "id": 9, "options": { - "displayLabels": [ - "value" - ], + "displayLabels": ["value"], "legend": { - "values": [ - "value" - ], + "values": ["value"], "displayMode": "table", "placement": "bottom" }, "pieType": "pie", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -397,9 +370,7 @@ }, "id": 6, "options": { - "displayLabels": [ - "name" - ], + "displayLabels": ["name"], "legend": { "values": [], "displayMode": "list", @@ -407,9 +378,7 @@ }, "pieType": "pie", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -472,9 +441,7 @@ }, "pieType": "pie", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -498,10 +465,7 @@ } ], "schemaVersion": 27, - "tags": [ - "gdev", - "panel-tests" - ], + "tags": ["gdev", "panel-tests"], "templating": { "list": [] }, @@ -514,4 +478,4 @@ "title": "Panel Tests - Pie chart", "uid": "lVE-2YFMz", "version": 9 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-polystat/polystat_test.json b/devenv/dev-dashboards/panel-polystat/polystat_test.json index faa84463019..1473fc1e7da 100644 --- a/devenv/dev-dashboards/panel-polystat/polystat_test.json +++ b/devenv/dev-dashboards/panel-polystat/polystat_test.json @@ -30,7 +30,9 @@ ], "colors": ["#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a"], "d3DivId": "d3_svg_4", - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": 2, "displayModes": [ { @@ -43,48 +45,8 @@ } ], "fontSizes": [ - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 22, - 24, - 26, - 28, - 30, - 32, - 34, - 36, - 38, - 40, - 42, - 44, - 46, - 48, - 50, - 52, - 54, - 56, - 58, - 60, - 62, - 64, - 66, - 68, - 70 + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, + 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70 ], "fontTypes": [ "Open Sans", @@ -449,7 +411,7 @@ "text": "Malaysian Ringgit (RM)", "value": "currencyMYR" }, - { + { "text": "CFP franc (XPF)", "value": "currencyXPF" }, @@ -1188,7 +1150,9 @@ ], "colors": ["#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a"], "d3DivId": "d3_svg_5", - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": 2, "displayModes": [ { @@ -1201,48 +1165,8 @@ } ], "fontSizes": [ - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 22, - 24, - 26, - 28, - 30, - 32, - 34, - 36, - 38, - 40, - 42, - 44, - 46, - 48, - 50, - 52, - 54, - 56, - 58, - 60, - 62, - 64, - 66, - 68, - 70 + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, + 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70 ], "fontTypes": [ "Open Sans", @@ -2307,7 +2231,9 @@ ], "colors": ["#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a"], "d3DivId": "d3_svg_2", - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": 2, "displayModes": [ { @@ -2320,48 +2246,8 @@ } ], "fontSizes": [ - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 22, - 24, - 26, - 28, - 30, - 32, - 34, - 36, - 38, - 40, - 42, - 44, - 46, - 48, - 50, - 52, - 54, - 56, - 58, - 60, - 62, - 64, - 66, - 68, - 70 + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, + 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70 ], "fontTypes": [ "Open Sans", diff --git a/devenv/dev-dashboards/panel-stat/panel-stat-tests.json b/devenv/dev-dashboards/panel-stat/panel-stat-tests.json index 0cbecd3b690..6799fff4bc5 100644 --- a/devenv/dev-dashboards/panel-stat/panel-stat-tests.json +++ b/devenv/dev-dashboards/panel-stat/panel-stat-tests.json @@ -36,8 +36,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -89,9 +88,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -107,8 +104,7 @@ { "alias": "__house_locations", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "labels": "", "min": 0, @@ -123,8 +119,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -176,9 +171,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -194,8 +187,7 @@ { "alias": "__house_locations", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "min": 0, "noise": 10, @@ -210,8 +202,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -263,9 +254,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -281,8 +270,7 @@ { "alias": "__house_locations", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "min": 0, "noise": 10, @@ -297,8 +285,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -350,9 +337,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -368,8 +353,7 @@ { "alias": "__server_names", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "min": 0, "refId": "A", @@ -383,8 +367,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -436,9 +419,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -453,56 +434,49 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "E", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "G", "scenarioId": "random_walk" @@ -513,8 +487,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -566,9 +539,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -583,56 +554,49 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "E", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "G", "scenarioId": "random_walk" @@ -643,8 +607,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -698,9 +661,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -716,8 +677,7 @@ { "alias": "__server_names", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "max": 200, "min": 0, @@ -734,8 +694,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -789,9 +748,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -807,8 +764,7 @@ { "alias": "__server_names", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "max": 200, "min": 0, @@ -825,8 +781,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -880,9 +835,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -898,8 +851,7 @@ { "alias": "__server_names", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "max": 200, "min": 0, @@ -929,8 +881,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -982,9 +933,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -1000,8 +949,7 @@ { "alias": "__house_locations", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "labels": "", "min": 0, @@ -1016,8 +964,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1069,9 +1016,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -1087,8 +1032,7 @@ { "alias": "__house_locations", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "min": 0, "noise": 10, @@ -1103,8 +1047,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1156,9 +1099,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -1174,8 +1115,7 @@ { "alias": "__house_locations", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "min": 0, "noise": 10, @@ -1190,8 +1130,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1243,9 +1182,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -1261,8 +1198,7 @@ { "alias": "__server_names", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "min": 0, "refId": "A", @@ -1276,8 +1212,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1329,9 +1264,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -1346,56 +1279,49 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "E", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "G", "scenarioId": "random_walk" @@ -1406,8 +1332,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1459,9 +1384,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -1476,56 +1399,49 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "E", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "random_walk" }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "G", "scenarioId": "random_walk" @@ -1536,8 +1452,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1591,9 +1506,7 @@ "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -1609,8 +1522,7 @@ { "alias": "__server_names", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "max": 200, "min": 0, @@ -1627,8 +1539,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1682,9 +1593,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -1700,8 +1609,7 @@ { "alias": "__server_names", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "max": 200, "min": 0, @@ -1718,8 +1626,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1773,9 +1680,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "mean" - ], + "calcs": ["mean"], "fields": "", "values": false }, @@ -1791,8 +1696,7 @@ { "alias": "__server_names", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "max": 200, "min": 0, @@ -1809,8 +1713,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1848,9 +1751,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -1863,8 +1764,7 @@ { "csvContent": "time, value\n2023-12-13T00:00:00Z, 0\n2023-12-13T00:00:00Z, 100", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -1875,9 +1775,7 @@ }, { "datasource": { - "default": true, - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1915,9 +1813,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -1930,8 +1826,7 @@ { "csvContent": "time, value\n2023-12-13T00:00:00Z, 50\n2023-12-13T00:00:00Z, 100\n2023-12-13T00:00:00Z, 50", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -1942,8 +1837,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1981,9 +1875,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -1996,8 +1888,7 @@ { "csvContent": "time, value\n2023-12-13T00:00:00Z, 0\n2023-12-13T00:00:00Z, 0", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -2008,8 +1899,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2047,9 +1937,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": true }, @@ -2062,8 +1950,7 @@ { "csvContent": "Name, value\nName1, 10\nName2, 20", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -2075,11 +1962,7 @@ ], "refresh": "", "schemaVersion": 39, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, @@ -2088,22 +1971,11 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "", "title": "Panel Tests - Stat", "uid": "EJ8_d9jZk", "version": 15, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-table/table_kitchen_sink.json b/devenv/dev-dashboards/panel-table/table_kitchen_sink.json index c92924966ce..9c05634b066 100644 --- a/devenv/dev-dashboards/panel-table/table_kitchen_sink.json +++ b/devenv/dev-dashboards/panel-table/table_kitchen_sink.json @@ -23,8 +23,7 @@ "panels": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -355,13 +354,8 @@ "footer": { "countRows": false, "enablePagination": false, - "fields": [ - "Min", - "Max" - ], - "reducer": [ - "max" - ], + "fields": ["Min", "Max"], + "reducer": ["max"], "show": true }, "frameIndex": 0, @@ -372,8 +366,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk_table" @@ -381,8 +374,7 @@ { "csvContent": "Info,Image,Pills,Data Link,Long Text\ndown,https://placecats.com/millie/200/400,hello,https://grafana.com,\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse tempus et augue et lacinia. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec eu pretium tortor. Cras venenatis sapien sed mauris gravida, ut scelerisque est fringilla. Cras lorem diam, facilisis nec malesuada in, vulputate vel enim. Etiam fringilla nisi quis felis blandit tincidunt. Cras id lacus ornare, ullamcorper nisl eget, bibendum odio. Pellentesque imperdiet, leo a imperdiet venenatis, ligula risus venenatis quam, vel euismod magna nisi sit amet leo.\"\nup,https://placecats.com/neo/200/400,\"[1,2,3,\"\"foo\"\",\"\"bar\"\"]\",https://grafana.com/solutions/kubernetes/,\"Sed imperdiet eget diam sit amet fringilla. Curabitur quis lacus blandit, mollis diam non, accumsan tortor. Aliquam ac tellus eget dui facilisis tempor eu id nulla. Maecenas ultrices turpis eu elementum imperdiet. Fusce eget rhoncus mi, et egestas lectus. Mauris facilisis auctor enim sed malesuada. Maecenas placerat ultricies metus vitae viverra. In hac habitasse platea dictumst. Mauris ipsum nisl, dictum eu aliquam eleifend, rutrum id orci. Nullam eget dui et odio eleifend porttitor.\"\nup fast,https://placecats.com/bella/200/400,\"foo,1,4,beep\",https://k6.io/,\"Proin ac libero vulputate ex vulputate pharetra ut vel lacus. Phasellus quis dolor sed leo finibus scelerisque. Ut vel finibus leo, sed viverra ipsum. Suspendisse vitae rutrum arcu. Donec sed tellus vel lectus bibendum vestibulum. Sed eu felis non velit dictum pulvinar eu et leo. Aenean et dignissim arcu. Nam luctus at neque quis efficitur. Fusce tempus at nibh a imperdiet. Nullam malesuada ac magna at facilisis. Duis pretium aliquam eros. Donec pharetra dignissim dolor non bibendum. Ut gravida mi id urna tempus, at ullamcorper felis vulputate. Duis congue augue ex, sed finibus leo ornare ut. Mauris non quam sodales, dignissim lorem eget, tincidunt mauris. Aliquam ut velit auctor, vestibulum metus sed, mollis massa.\"\ndown fast,https://placecats.com/neo_2/200/400,\"foo,bar,baz,a longer one,bim\",https://grafana.com/products/cloud/,\"Nullam in pulvinar justo. Nunc dictum arcu ac pellentesque bibendum. Sed in erat turpis. Vestibulum eu orci ac ligula lobortis tempus. Fusce consectetur feugiat magna, eu tempor nibh vestibulum ac. Aliquam erat volutpat. Vivamus sit amet viverra enim. Quisque mollis odio nulla, nec vulputate sem placerat in. Etiam dolor sapien, pulvinar in accumsan at, consequat eget nisi. Nunc condimentum neque magna, congue consectetur dui efficitur interdum. Nam lobortis fringilla maximus. Vestibulum eu dui a velit condimentum eleifend consequat nec lectus.\"", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_content" @@ -482,7 +474,6 @@ } ], "datasource": { - "uid": "PD8C576611E62080A", "type": "grafana-testdata-datasource" }, "options": { @@ -490,9 +481,7 @@ "cellHeight": "sm", "footer": { "show": false, - "reducer": [ - "sum" - ], + "reducer": ["sum"], "countRows": false, "fields": "" } @@ -507,8 +496,7 @@ { "baseFilters": [], "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "filters": [], "name": "Filters", diff --git a/devenv/dev-dashboards/panel-table/table_markdown.json b/devenv/dev-dashboards/panel-table/table_markdown.json index b6aa28ca3b0..863edd09fed 100644 --- a/devenv/dev-dashboards/panel-table/table_markdown.json +++ b/devenv/dev-dashboards/panel-table/table_markdown.json @@ -85,9 +85,7 @@ "enablePagination": true, "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true diff --git a/devenv/dev-dashboards/panel-table/table_pagination.json b/devenv/dev-dashboards/panel-table/table_pagination.json index 48f5df03f1f..cafa00c36d5 100644 --- a/devenv/dev-dashboards/panel-table/table_pagination.json +++ b/devenv/dev-dashboards/panel-table/table_pagination.json @@ -1,2683 +1,2661 @@ { - "annotations": { - "list": [ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1110, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [ { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" + "options": { + "rent": { + "color": "yellow", + "index": 0 + } + }, + "type": "value" } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "property_type" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "store": { + "color": "blue", + "index": 0 + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "title" + }, + "properties": [ + { + "id": "custom.width", + "value": 205 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Number of rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 66 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Description" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URL" + }, + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Show details", + "url": "${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Surface" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "orange", + "value": 100 + }, + { + "color": "yellow", + "value": 200 + }, + { + "color": "green", + "value": 300 + }, + { + "color": "#EAB839", + "value": 500 + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "#EF843C", + "value": 2000 + } + ] + } + }, + { + "id": "unit", + "value": "areaM2" + }, + { + "id": "custom.width", + "value": 93 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Type" + }, + "properties": [ + { + "id": "custom.width", + "value": 94 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "City" + }, + "properties": [ + { + "id": "custom.width", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Price" + }, + "properties": [ + { + "id": "unit", + "value": "currencyUSD" + } + ] + } ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 1110, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [ - { - "options": { - "rent": { - "color": "yellow", - "index": 0 - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "property_type" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, - { - "id": "mappings", - "value": [ - { - "options": { - "store": { - "color": "blue", - "index": 0 - } - }, - "type": "value" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "title" - }, - "properties": [ - { - "id": "custom.width", - "value": 205 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Number of rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Description" - }, - "properties": [ - { - "id": "custom.inspect", - "value": true - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "URL" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "Show details", - "url": "${__value.raw}" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Surface" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background-solid" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "dark-red", - "value": null - }, - { - "color": "orange", - "value": 100 - }, - { - "color": "yellow", - "value": 200 - }, - { - "color": "green", - "value": 300 - }, - { - "color": "#EAB839", - "value": 500 - }, - { - "color": "#6ED0E0", - "value": 1000 - }, - { - "color": "#EF843C", - "value": 2000 - } - ] - } - }, - { - "id": "unit", - "value": "areaM2" - }, - { - "id": "custom.width", - "value": 93 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Type" - }, - "properties": [ - { - "id": "custom.width", - "value": 94 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "City" - }, - "properties": [ - { - "id": "custom.width", - "value": 120 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 77 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Price" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 0 - }, - "id": 2, - "options": { - "footer": { - "enablePagination": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Surface" - } - ] - }, - "pluginVersion": "9.0.0-pre", - "targets": [ - { - "csvContent": "\"id\",\"created_on\",\"operation\",\"property_type\",\"place_name\",\"place_with_parent_names\",\"country_name\",\"state_name\",\"geonames_id\",\"lat_lon\",\"lat\",\"lon\",\"price\",\"currency\",\"price_aprox_local_currency\",\"price_aprox_usd\",\"surface_total_in_m2\",\"surface_covered_in_m2\",\"price_usd_per_m2\",\"price_per_m2\",\"floor\",\"rooms\",\"expenses\",\"properati_url\",\"description\",\"title\",\"image_thumbnail\"\nf73c373e0588bf568164a057dd94203ac87d47b1,2014-08-07,rent,store,Catu,|Brasil|Bahia|Catu|,Brasil,Bahia,,,,,0,,0,0,,,,,,,,http://www.properati.com.br/mfye_alugar_outros_catu,\"Otimo Imovel com o melhor valor da regiao, confira as fotos - \",Exclusividade! - Loja Em Catu,https://thumbs4.properati.com/3/jA8isZw8Xju7z3-V2I-ED8x5D2o=/trim/198x0/smart/filters:strip_icc()/galeriadefotos.net.br/backup/upload/15989/1598966287bc7/zd533ba5e829b0543093a45e1d8398bd7.jpg\nd6d377927ab49671acdd38aa6f661a460601a88b,2015-01-20,rent,apartment,Pernambuco,|Brasil|Pernambuco|,Brasil,Pernambuco,,\"-8.126271,-34.903793\",-8.126271,-34.903793,1200,BRL,1184.32,383.55,,63,6.088095238095239,19.047619047619047,1,2,,http://www.properati.com.br/w71k_alugar_apartamentos_pernambuco,\"CONTATOS: Claro: 81./ Tim: 81./ Oi: 81./ Vivo: 81.Apartamento de 2 quartos mais Dependência completa de empregada, 1.º andar de edifício localizado na Rua Dr. Gaspar Regueira da Costa, 99, Boa Viagem.Este apartamento é constituído por: 1 Sala, 2 Quartos, 2 Banheiros, Cozinha, Área de serviço, Dependência completa de empregada e 1 lugar de estacionamento.O Valor do aluguer já inclui taxas.Agende já a sua visita.Nota: O Edifício irá ser pintado exteriormente, em breve.ISI-120-T2 #ref:ISI-120-T2 - ISI-120-T2 - idalécio Soares\",\"Apartamento de 2 quartos, DCE, 1.º Andar, 63 m2, Boa Viagem - Recife\",https://thumbs4.properati.com/0/B9BCwP1HK7NvZIYINGkFNnNfOZ4=/trim/198x0/smart/filters:strip_icc()/feedmedia.egorealestate.com/Zfeed/S5/C4123/P2270979/Tphoto/ID03a72200-0000-0500-0000-00000141a7a5.JPG\nc6826a9508436920fd59b46a202354f3e4823d22,2014-10-29,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.1546253,-45.7906242\",-23.1546253,-45.7906242,0,BRL,0,0,,3800,,,,,,http://www.properati.com.br/s41f_alugar_comercial_cacapava,\"Condomínio com 22 Módulos de Galpões; 3.800m2 a 12.600m2; 12m pé-direito médio; Piso 6 TON/m2; Ã�rea total de Terreno : 324.000 m2; Ã�rea Total construída: 133.200 m2; 293 vagas para automóveis; 103 vagas para caminhões; Refeitório para 256 pessoas por turno;Benefícios Fiscais no município de Caçapava conforme Lei Lei 5055/211; Isenção de Taxas;Isenção de IPTU; Redução de ISS; Reversão de ICMS.Valores locação = R$ 15,00 o m2Tx Cond. = R$ 1,50 o m2Valores poderão ser alterados sem prévio aviso.A Heron Imóveis oferece este(a) Comercial em Caçapava, no bairro Caçapava. Gostou desse(a) Comercial em Caçapava? Então veja mais informações! Acesse o nosso site clicando no botão Contate o anunciante ou ligue - ou ainda entre em contato conosco pelo email contato@ Obrigado!\",\"Comercial em Caçapava, no bairro Caçapava\",https://thumbs4.properati.com/1/J2n8nXVlvduy6EJjyLwPneEoc28=/trim/198x0/smart/filters:strip_icc()/www.heronimoveis.com.br/fotos/F00/35/23500-DSC06177.JPG\nba957ad3cb2d12d55d1f0466eeffe788a35a6f4f,2014-08-04,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7780086,-49.3450562\",-20.7780086,-49.3450562,950,BRL,751.1,243.25,,,,,,1,,http://www.properati.com.br/lxp9_alugar_casas_sao-jose-do-rio-preto,\"Ref.: CA95876 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Garden Village II..:Casa Condomnio Garden Village II, Casa Condominio, Dormitrios: 03, Tipo Apto.: 01, Wc. Social: 01, Sala de Visita: 01, Copa: 01, Cozinha: 01, Cozinha Planejada, Despensa, rea de Servio, Ar Condicionado, Alarme, Acabamento Em Gesso, Sanca, Campainha, Cerca Eletrica, Forro de Laje, Piso Dormitrios: Frio, Piso Salas: Frio, M2/ Terreno: 145, M2 rea Construida: 70, Garagem Descoberta: 01, Salo de Festa, Detalhes: R$ 950,00 + Iptu + Condomnio\", Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Garden Village II,https://thumbs4.properati.com/9/xcrfHjSnXdhGcOK1m1wg1jHJlsw=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/803/8860a8e8-6d62-49e6-a992-54ab8f360f35.jpg\n0999b33908c71af3b8be282ab35ab61b38a46353,2014-07-16,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,4300,BRL,4078.98,1321,,319,4.141065830721003,13.47962382445141,,4,,http://www.properati.com.br/ifuj_alugar_apartamentos_vila-olimpia,\"Apartamento na Vila Olí­mpia, com 4 quartos, sendo 2 suí­tes,Ampla sala com terraí§o, piso de madeira corrida, 1 dos quartos pode ser revertido para sala de tv ou escritório.Quartos com carpete de madeira, as suí­tes com armí¡rios embutidos, uma delas com ar condicionado.Armí¡rio corredor.Cozinha com armí¡rio, Piso de granito, na cozinha e lavanderia.  Referíªncia: AP34\",\"Apartamento no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/8/nxrbzTDipvKnqdx1wDABEyIbSes=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/34/c789b808-bf30-460d-9376-16299ce5abbb.jpg\n011d5618639ce229b012022a32b22eff9abd213e,2014-11-19,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.9648026,-46.3855723\",-23.9648026,-46.3855723,1300,BRL,1323.12,428.5,,60,7.141666666666667,21.666666666666668,4,1,,http://www.properati.com.br/tl4s_alugar_apartamentos_sao-paulo,\"PACOTE R$ 1.300,00 OTIMO APARTAMENTO MOBILIADO COM TERRAÇO PROXIMO SHOPPING , PRAIA E COMERCIOS ACEITA FIADOR / SEG. FIANÇA A 3 Milenio oferece este(a) Apartamento em Sao Vicente, no bairro Gonzaguinha - 1 dormitórios. Gostou desse(a) Apartamento em Sao Vicente? Então veja mais informações! Acesse o nosso site clicando no botão Contate o anunciante ou ligue - ou ainda entre em contato conosco pelo email vendas@ Obrigado!\",\"Apartamento em Sao Vicente, no bairro Gonzaguinha - 1 dormitórios\",https://thumbs4.properati.com/4/x8BqTbd304ntTBY5pTf5Yi_nNMw=/trim/198x0/smart/filters:strip_icc()/www.imobiliariasdesantos.com.br/fotos/F00/74/757400-FOTOS%20HELANE%20001.jpg\n6f274a2d23ffa89cb0301f3277585beda7723ce8,2014-09-01,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8343086,-49.3805559\",-20.8343086,-49.3805559,5000,BRL,3953.34,1280.31,,,,,,,,http://www.properati.com.br/o23s_alugar_comercial_sao-jose-do-rio-preto_rua-nuno-alvares-pereira,\"Ref.: SA95668Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Pq. EstorilM2 rea Construida: 170, Detalhes: Salo de 170 M, Com Mezanino. J Com Acessibilidade. Tem Uma Linda Fachada e Estacionamento Para Clientes.\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Pq. Estoril,https://thumbs4.properati.com/8/7VqZVGV6Hl3paOrhYXv_ksowyEw=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1875/TG5yXGj9EJPaa5o0dWgL.jpg\ndb6f890847bcacc6ec3e78a0e6613132174e4c70,2014-12-05,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178411,-49.387605\",-20.8178411,-49.387605,10000,BRL,7906.68,2560.62,,,,,,1,,http://www.properati.com.br/ue07_alugar_casas_sao-jose-do-rio-preto_rua-cila,\"Ref.: CO95026Tipo: Casa Comercial, Predio ComercialCidade: So Jos do Rio Preto - SPBairro: RedentoraSobrado, Dormitrios: 4, Tipo Apto.: 4, C/ A/e: 4, A/e C/ Interior: 4, Wc. Social: 1, Copa/cozinha: 1, Cozinha C/ A/e: 1, Despensa, Salas : 1, Sala P/ Ambientes : 4, M2 rea Construida: 330, Entrada Lateral: 1, Piso Dormitrios: Frio\",\"Ref.: CO95026 Tipo: Casa Comercial, Predio Comercial Cidade: So Jos do Rio Preto - SP Bairro: Redentora\",https://thumbs4.properati.com/2/DNREjVLgpGPzTlv8aIvhpd7KZkI=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2461/02ea33d3-3ebd-4139-a380-b60eb84c87d1.jpg\nf7d3243419c85cf439189481819f13cb22ab0498,2014-10-01,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8126181,-49.3404534\",-20.8126181,-49.3404534,3800,BRL,3004.52,973.03,,,,,,,,http://www.properati.com.br/qz8t_alugar_casas_sao-jose-do-rio-preto_avenida-miguel-damha,\"Ref.: CA95902Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Damha III..: Casa Condomnio Damha III, Casa Condominio, Dormitrios: 03, Suite: 01, Closet , Tipo Apto.: 02, C/ A/e: 02, Home, Copa/cozinha: 01, Cozinha Planejada, Piscina, Varanda, rea de Servio, Wc. de Empregada/servio, Forro de Laje, M2/ Terreno: 450, M2 rea Construida: 240, rea de Lazer, Garagem Descoberta: 02, Garagem Coberta: 02, Churrasqueira, Valor Condominio R$-: 420,00\",Ref.: CA95902 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Damha III,https://thumbs4.properati.com/8/cqu5q3tBJOddQ526fWf2puVwINI=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2060/6064cf7e-f8ed-44f3-8a80-b6576de27d62.jpg\ncbfc4c495b3578c995363825a85a821217fab4ec,2014-10-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,14000,BRL,11069.36,3584.87,,,,,,,,http://www.properati.com.br/ri3p_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95918Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Mini Dist. Industrial Adail Vetorasso..: Salo Comercial No Mini Distrito Industrial Adail Vetorasso, Salo Comercial, Wcs.: 02, Cozinha: 01, Escritrio, M2/ Terreno: 2.100, M2 rea Construida: 1.350, Detalhes: Cobertura Metlica.p Direito Com 7 Metros.corredor Lateral.\",Ref.: SA95918 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Mini Dist. Industrial Adail Vetorasso,https://thumbs4.properati.com/9/INPTa4YGuWfsekPfC8ez-rqd3PI=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2285/Mhd9hMU2ZwU9YXAC9Hzi.jpg\nb4dab15f9d4411d0847d1871e0a62e107b492fdc,2014-08-02,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.8773135,-46.7592613\",-23.8773135,-46.7592613,28000,BRL,22138.72,7169.74,,,,,,,,http://www.properati.com.br/lud3_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95869Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Eng. Schimidt..: Salo Comercial Em Engenheiro Schimidt, Salo Comercial, Obs: Salo Ideal Para Transportadora Com Frente Para 03 Marginal, Esquina Com Rua Projetada 01 e Rodovia W. Luiz, M2/ Terreno: 5.500, M2 rea Construida: 2.200\",Ref.: SA95869 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Eng. Schimidt,https://thumbs4.properati.com/3/oJm3M_UtBn2PVRsZ2O4n48IvhuA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/780/60d090bc-4a05-4929-88ae-aca5b9873a76.jpg\nd3769eb1b41c780c83f2d176adae8ad9a81b7ba3,2014-10-08,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.818728,-49.4212608\",-20.818728,-49.4212608,16000,BRL,12650.68,4096.99,,,,,,,,http://www.properati.com.br/r6d9_alugar_comercial_sao-jose-do-rio-preto_avenida-joao-batista-vetorasso,\"Ref.: SA95810Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Waldemar VerdiM2/ Terreno: 5.000, M2 rea Construida: 1.400, Detalhes: Com Recepo e 8 Salas. P Direito Com 7 M.\",Salo,https://thumbs4.properati.com/6/GFkI3LbwZQAhB8USv5fTltHxz0E=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2179/QEWBOD1T8GCOjBi0H6WI.jpg\nf51aebdb554e9b5dfa16c3538d3376040f5f2b5c,2014-08-20,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.1423284,-51.3750141\",-22.1423284,-51.3750141,16000,BRL,12650.68,4096.99,,,,,,,,http://www.properati.com.br/np97_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95723Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Moyss Miguel HaddadM2 rea Construida: 322, Obs: Salo Ideal Para Loja, 217m Terreo e 105m Mezanino. Estacionamento Na Frente.imvel Novo.\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Moyss Miguel Haddad,https://thumbs4.properati.com/2/viy2bV22HhxBkY_449PiH9sLQPw=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1548/9242514f-75f0-4bdc-a5b1-68a958cbda17.jpg\n7266f270625a52c84adaf69ac08a53b397617247,2014-09-01,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,6000,BRL,4744,1536.37,,,,,,,,http://www.properati.com.br/o20x_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95742Tipo: Salo IndustrialCidade: So Jos do Rio Preto - SPBairro: Quinta das PaineirasWcs.: 02, Cozinha: 01, M2/ Terreno: 720, M2 rea Construida: 458,90, Obs: Salo Industrial Grande Com 458m, Com Boa Acessibilidade e tima Localizao, 02 Quadras da Avenida Potirendaba, Fcil Acesso e Entrada Para Caminhes.\",Tipo: Salo Industrial Cidade: So Jos do Rio Preto - SP Bairro: Quinta das Paineiras,https://thumbs4.properati.com/3/0rnMsn1G6rWTjCQ9lnrLn6WR7JA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1771/KET9NdQ0WNrtQlhGEVEq.jpg\nc1e10a8afe111ba5caa5034df1ecb56b25b772f9,2014-08-19,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.1423284,-51.3750141\",-22.1423284,-51.3750141,12000,BRL,9488,3072.74,,,,,,,,http://www.properati.com.br/muvz_alugar_casas_sao-jose-do-rio-preto,\"Ref.: CA95766Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Moyss Miguel HaddadWc. Social: 04, M2/ Terreno: 980, M2 rea Construida: 500, Obs: Entrada Lateral Com Acesso Para Caminho, Com 04 Wcs. Sendo 02 Wc P/ Deficiente.\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Moyss Miguel Haddad,https://thumbs4.properati.com/3/GvRImi73Q9koPTqVulTG5pg1J2s=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1519/T181YBWZd62P9tMfgs1F.jpg\nd156f7cc95141ef1fca4de81d6dc65b143c9988f,2014-08-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.1423284,-51.3750141\",-22.1423284,-51.3750141,12000,BRL,9488,3072.74,,,,,,,,http://www.properati.com.br/muwd_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95749Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Moyss Miguel HaddadM2 rea Construida: 280, Obs: Salo Ideal Para Loja, 217mterreo + 68m Mezanino.estacionamento Na Frente,\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Moyss Miguel Haddad,https://thumbs4.properati.com/5/A5TB5m6yLugDjIdQVsXy9br70YQ=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1533/eeec7b18-daa6-422b-aac1-82894f366e60.jpg\n90ed612641d0db18967ee9c07edc8b0647c97976,2014-08-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.1423284,-51.3750141\",-22.1423284,-51.3750141,12000,BRL,9488,3072.74,,,,,,,,http://www.properati.com.br/muwc_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95725Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Moyss Miguel HaddadM2 rea Construida: 280, Obs: Salo Ideal Para Loja, 217m Terreo, + 68m Mezanino.estacionamento Na Frente, Imvel Novo\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Moyss Miguel Haddad,https://thumbs4.properati.com/2/8rbyOC1iGXRWRZqh5Z6pcOsdsfQ=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1532/a142f7a0-ff97-4794-84d8-4144253429c3.jpg\nc69e1ca4e7cd3346bc510240893bf2c2c7437e8e,2014-08-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.1423284,-51.3750141\",-22.1423284,-51.3750141,12000,BRL,9488,3072.74,,,,,,,,http://www.properati.com.br/muvh_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95724Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Moyss Miguel HaddadM2/ Terreno: 280, Obs: Salo Ideal Para Loja, 217m Terreo e + 68m Mezanino.Estacionamento Na Frente,imvel Novo.\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Moyss Miguel Haddad,https://thumbs4.properati.com/1/3gyCoSFzrSme_NcQhKWIEnuoeaY=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1501/CeAfrlKKrQIRE9uzNxoa.jpg\n0c5e391bac4d007585efb02466681c760a758423,2014-09-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8379345,-49.3370139\",-20.8379345,-49.3370139,8000,BRL,6325.32,2048.49,,,,,,,,http://www.properati.com.br/q4jv_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95899Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Ch. Estancia Jockey Clube..: Salo Comercial , Salo Comercial, Wcs.: 04, Wcs. C/ A/e, Cozinha: 01, Obs: P Direito 9 Metros, M2 rea Construida: 1.000, Detalhes: Salo Novo, Sendo Os Wcs Piso Porcelanato, Cozinha Porcelanato e Piso Liso, Com Telhado Vulcanizado.\",Ref.: SA95899 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Ch. Estancia Jockey Clube,https://thumbs4.properati.com/8/OM-MkRbrVgdcQa163wlgXjWDHqU=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2007/8541c9f9-4477-448d-a193-d2b00dc5eed4.jpg\n01bdf823f7827d745574bb7a180a39e4db359463,2014-08-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,8000,BRL,6325.32,2048.49,,,,,,,,http://www.properati.com.br/muux_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95894Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Ch. Jockey Clube..: Salo Comercial Na Chcara Jockey Clube, Salo Comercial, M2/ Terreno: 5.000, M2 rea Construida: 1.150, Detalhes: Galpo Com Piso Cimento Polido, Estrutura Metlica, Entrada Lateral Para Caminho.p Direito Alto Com 6,/2 M. \",Ref.: SA95894 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Ch. Jockey Clube,https://thumbs4.properati.com/1/HZjM3Xdq2xWgpQ5gSrCVIASVnJA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1481/Tz9VYOVWXC1ZVU5fUHwL.jpg\n050a20b55332403b962575877b81d609a5988a15,2014-09-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8379345,-49.3370139\",-20.8379345,-49.3370139,8000,BRL,6325.32,2048.49,,,,,,,,http://www.properati.com.br/q4ju_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95900Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Ch. Estancia Jockey Clube..: Salo Comercial , Salo Comercial, Wcs.: 04, Wcs. C/ A/e, Cozinha: 01, Obs: P Direito 9 Metros, M2 rea Construida: 1.000, Detalhes: Salo Novo, Sendo Os Wcs Piso Porcelanato, Cozinha Porcelanato e Piso Liso, Com Telhado Vulcanizado.\",Ref.: SA95900 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Ch. Estancia Jockey Clube,https://thumbs4.properati.com/3/ZL10NlMLKOM5C49dt-MjpOTaaMo=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2006/9fbe5c67-00ba-4e7b-9904-08316f433dd4.jpg\nfeb178373d5eab7df3b6c546a5d1e6a192156c7f,2014-08-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8457948,-49.353464\",-20.8457948,-49.353464,8000,BRL,6325.32,2048.49,,,,,,,,http://www.properati.com.br/muuv_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95892Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Ch. Jockey Clube..: Salo Comercial Na Chcara Jockey Clube, Salo Comercial, M2/ Terreno: 5.000, M2 rea Construida: 1.150, Detalhes: Galpo Com Piso Cimento Polido, Estrutura Metlica, Entrada Lateral Para Caminho.p Direito Alto Com 6,/2 M.\",Ref.: SA95892 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Ch. Jockey Clube ,https://thumbs4.properati.com/5/xwV26hopilS3ZK6xLE-O3iy4rE4=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1479/vT0mPYs7U2dAsti8LWGQ.jpg\n882a8542b44e551782d3126a1d43d907cdba854b,2014-08-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8442587,-49.3291753\",-20.8442587,-49.3291753,7000,BRL,5534.66,1792.43,,,,,,,,http://www.properati.com.br/mt5y_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95817Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Marginal Eng. SchimidtWc. Social: 02, Cozinha, Mesanino, Escritrio, M2/ Terreno: 2.000, M2 rea Construida: 1.100, Pintura Nova, Piso Dormitrios: Cimentado;, Piso Salas: Polido;, Detalhes: Salo Novo, Com Estrutura Metlica e Banheiro C/ Acessibilidade.\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Marginal Eng. Schimidt,https://thumbs4.properati.com/4/FPT3HYl7BCrZMA5Okj6iNxUgPRA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1432/MaEwnQ1cL6HLcrscPFb8.jpg\n201e0ccc9fc63a78f68391bdd74ac5407e07da9b,2014-08-04,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,1000,BRL,790.66,256.06,,,,,,1,,http://www.properati.com.br/lxpd_alugar_casas_sao-jose-do-rio-preto,\"Ref.: CA95884Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Parque Liberdade III..:Casa Condomnio Parque da Liberdade III, Casa Condominio, Dormitrios: 03, C/ A/e: 02, Wc. Social: 01, Wcs. C/ A/e, Sala de Visita: 01, Cozinha: 01, Cozinha Planejada, Interfone, Acabamento Em Gesso, Sanca, Campainha, Forro de Laje, Obs: Imvel Semi Novo, Com Projeto da Arquiteta Kenia Miranda, o Imvel Tem Papel de Parede, Cortinas Nos Dormitrios e Sala, Luminrias Na Cozinha., M2/ Terreno: 143, Garagem Coberta: 02, Churrasqueira, Detalhes: R$ 1.000,00 + Iptu + Condominio\",Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Parque Liberdade III,https://thumbs4.properati.com/2/v319TrEqOc-5Hy9xmTQXh1KL2UE=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/807/7331be4a-3945-41cd-b761-4322696192f5.jpg\n05cf0728d4ba6016469b6b4a864542a1824dc25c,2014-08-15,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.7688712,-46.7100661\",-23.7688712,-46.7100661,2000,BRL,1581.32,512.12,,,,,,,,http://www.properati.com.br/mqtt_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95463Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Jardim So MarcosWc. Social: 2, Cozinha: 1, Mesanino, Recepo, M2/ Terreno: 406, M2 rea Construida: 110, Pintura Nova, Piso Salas: Piso Frio\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Jardim So Marcos,https://thumbs4.properati.com/9/EMUy3dbQiGwd8LmfHH92qsmCQ7Q=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1375/srbDQgpudCyI2lewxvjS.jpg\nf5942694fe76bfe705275acfe74148c588367f86,2014-09-01,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.7688712,-46.7100661\",-23.7688712,-46.7100661,4000,BRL,3162.64,1024.24,,,,,,8,,http://www.properati.com.br/o215_alugar_casas_sao-jose-do-rio-preto_rua-antonio-dias,\"Ref.: CO95681Tipo: Casa ComercialCidade: So Jos do Rio Preto - SPBairro: Jardim So MarcosWc. Social: 04, Sala(s): 08, M2/ Terreno: 280, Garagem Coberta: 02, Forro de Laje, Piso Salas: Frio, Iptu Valor: 58,00, Detalhes: timo Local Para Clincas.\",Tipo: Casa Comercial Cidade: So Jos do Rio Preto - SP Bairro: Jardim So Marcos,https://thumbs4.properati.com/4/F58YgAYlsu22NFL9RPPH5RURZJ8=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1779/sr0aS0NcXQGZ7HsOtyan.jpg\n1b093694ca05135b213162c0bd499e9adb708309,2014-12-10,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.6302071,-46.5818983\",-23.6302071,-46.5818983,4000,BRL,3162.64,1024.24,,,,,,,,http://www.properati.com.br/ufsq_alugar_comercial_sao-jose-do-rio-preto_avenida-marginal,\"Ref.: SA95942Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Pq. Res. Manor Daud..: Salo Comercial No Parque Residencial Manor Daud, Salo Comercial, Detalhes: Salo Com 340m, Entrada Para Caminho.frente Para Br153\",Ref.: SA95942 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Pq. Res. Manor Daud,https://thumbs4.properati.com/4/4e8bVPqS0g1ezrFKP9fcdzvSn0I=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2493/rJ3aboE1bZnwuqJHy4Lr.jpg\n50bd70c45a9a9b087c404cac6b67c491f64c211e,2014-10-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2500,BRL,1976.65,640.15,,,,,,,,http://www.properati.com.br/ri3l_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95916Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Res. Caetano..: Salo Comercial No Residencial Caetano, Salo Comercial, Wcs.: 02, Cozinha: 01, M2 rea Construida: 350, Detalhes: Cozinha2 Wc Com Acessibilidade;1 Porta Na Frente1 Porta Na Lateral;barraco Novo.cobertura Com Estrutura Metlica. P Direito de 6 Metros.\",\"Ref.: SA95916 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Res. Caetano ..: Salo Comercial No Residencial Caetano, Salo Comercial, Wcs.: 02, Cozinha: 01, M2 rea Construida: 350, Detalhes: Cozinha 2 Wc Com Acessibilidade\",https://thumbs4.properati.com/9/l325GXwN3fD9xS0dglH5hmaB83A=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2281/FjKJBqBJFxhvJ4atJVuO.jpg\n50a4a96d3ec01b7b1032e5eec4a3496b38f35c4f,2014-10-09,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7780086,-49.3450562\",-20.7780086,-49.3450562,2500,BRL,1976.65,640.15,,,,,,,,http://www.properati.com.br/r9j7_alugar_casas_sao-jose-do-rio-preto_avenida-belvedere,\"Ref.: CA95904Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Village Damha Rio Preto I..: Casa Em Condomnio Village Damha Rio Preto I, Casa Condominio, Dormitrios: 03, Tipo Apto.: 01, C/ A/e: 03, Cozinha: 01, Cozinha Planejada, Varanda, rea de Servio, Wc. de Empregada/servio, Garagem Coberta: 02, Churrasqueira\",Ref.: CA95904 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Village Damha Rio Preto I,https://thumbs4.properati.com/1/CVM0xMvGlg_DX1BluR3vWpRkhMU=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2206/7f2a5d99-2465-48fb-859c-a52311ba0c18.jpg\nf5be311dcee4a66dcb26f463f76c49b6084de8ab,2014-11-11,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,1600,BRL,1411.74,457.2,,,,,2,1,,http://www.properati.com.br/t8nu_alugar_apartamentos_tatuape_rua-serra-de-braganca,\"APTO DE 40M/2 COM 01 DORMITRIO, SALA AMPLA COM SACADA, COZINHA PLANEJADA, WC SOCIAL, REA DE SERVIO, 01 VAGA DE GARAGEM LIVRE, LAZER COMPLETO COM PISCINA, PLAYGROUD, SALO DE FESTA, CHURRASQUEIRA, SAUNA, SALA DE FITINESS, SALA DE LEITURA, SALO DE JOGOS, EXCELENTE LOCALIZAO. O APTO ESTA COM FOGO, GELADEIRA, MICROONDAS, SUGGAR, BALCO ESTILO COZINHA AMERICANA, 02 BANQUETAS, 02 MESINHAS DE CANTO, 01 HOME-OFFICER, CAMA BOX COM COLCHO, VENTILADOR DE TETO, ARMRIO NO DORMITRIO.\",TOLEDO CONSULTORIA JURIDICA E IMOBILIARIA,https://thumbs4.properati.com/6/-9lTZIOGIGHwHaddpPoJu6s92hY=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/2/6c5e21eb-1c7b-41d6-9257-b6e7994ea93c.jpg\na031b9b0ccce57678aab134025713cdb4ad7ed19,2014-10-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7630911,-49.3810839\",-20.7630911,-49.3810839,1500,BRL,1185.99,384.09,,,,,,,,http://www.properati.com.br/ri3h_alugar_comercial_sao-jose-do-rio-preto_rua-gumercindo-tomas-de-aquino,\"Ref.: SA95914Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Centenrio da Emancipao..: Salo Comercial No Distrito Industrial Centenrio da Emancipao, Salo Comercial, Wcs.: 02, Cozinha: 01, M2/ Terreno: 200, M2 rea Construida: 100, Detalhes: Salo Em Construo, Com 2 Wc Com Acessibilidade e Cozinha.porta Frente e Lateral.estrutura Metlica, P Direito 5 Metros.\",Ref.: SA95914 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Dist. Industrial Centenrio da Emancipao,https://thumbs4.properati.com/5/cuTILpWk120n1EtpTTP7CuHqFTI=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2277/xOFbBdd0MAPLxuFIMMMc.jpg\n8198126233f30e45a7ec723640ecd09fc933f35f,2014-10-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7630911,-49.3810839\",-20.7630911,-49.3810839,1500,BRL,1185.99,384.09,,,,,,,,http://www.properati.com.br/ri3j_alugar_comercial_sao-jose-do-rio-preto_rua-gumercindo-tomas-de-aquino,\"Ref.: SA95915Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Centenrio da Emancipao..: Salo Comercial No Distrito Industrial Centenrio da Emancipao, Salo Comercial, Wcs.: 02, Cozinha: 01, M2/ Terreno: 200, M2 rea Construida: 100, Detalhes: Salo Em Construo, Com 2 Wc Com Acessibilidade e Cozinha.porta Frente e Lateral.estrutura Metlica, P Direito 5 Metros.\",Ref.: SA95915 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Dist. Industrial Centenrio da Emancipao,https://thumbs4.properati.com/0/LWklCEKjfuTI94hwh7U-tpkiQxw=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2279/YBRlngu70KNBBuf3pXju.jpg\ncfe8aedbfe7496306c9ee598fdb0799d1a4d43a7,2014-08-14,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178411,-49.387605\",-20.8178411,-49.387605,3000,BRL,2371.98,768.18,,,,,,,,http://www.properati.com.br/mpsw_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95860Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: RedentoraSalo Comercial, Terrea, Acabamento Em Gesso, Forro de Laje, Piso Salas: Frio, M2 rea Construida: 160\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Redentora,https://thumbs4.properati.com/1/w-odT7rMEUYcr3TVS4fo2ausAAI=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1278/Kp7YsojHwZdQDjK4JvMz.jpg\n9002dc7d32f4f097a4f9c789ad93b7f5304396cf,2014-08-14,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178411,-49.387605\",-20.8178411,-49.387605,3000,BRL,2371.98,768.18,,,,,,,,http://www.properati.com.br/mpsz_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95862Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: RedentoraM2 rea Construida: 190, Garagem Descoberta: 02, Forro de Laje, Piso Salas: Frio\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Redentora,https://thumbs4.properati.com/7/xW33i6TXrwRgMFrpyW_syKKKlPs=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1281/UKC5P4P7lZPyQSY9l8xC.jpg\n2128d47314a494ddecda6b6e981c46afbd3fae51,2014-10-30,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,3000,BRL,2371.98,768.18,,,,,,,,http://www.properati.com.br/s9we_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95921Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Redentora..: Salo Comercial Na Redentora, Salo Comercial, M2/ Terreno: 150, Detalhes: tima Localizao!\",Ref.: SA95921 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Redentora,https://thumbs4.properati.com/6/HVrSVpwKgIJpnnFxGcMzyHIeUx4=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2347/abTB8PxHKedvADO9yyhF.jpg\n0329fa7a5536c99eee743612010897cafed7f340,2014-10-15,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8030634,-49.4324803\",-20.8030634,-49.4324803,3000,BRL,2371.98,768.18,,,,,,,,http://www.properati.com.br/re15_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95910Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Res. Palestra..: Salo Comercial No Residencial Palestra, Salo Comercial, Wc. Social: 02, Forro de Laje, Obs: timo Salo, Novo., M2/ Terreno: 250, M2 rea Construida: 200\",Ref.: SA95910 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Res. Palestra,https://thumbs4.properati.com/8/MBuRdEvx5x-V-zpeycnxFNg-n70=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2238/NOqLX7BtA7KEH0SUs5rV.jpg\nc822a8819d8874916877cc6b3c91194cbf5968ca,2014-10-09,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7780086,-49.3450562\",-20.7780086,-49.3450562,3000,BRL,2371.98,768.18,,,,,,,,http://www.properati.com.br/r9j6_alugar_casas_sao-jose-do-rio-preto_avenida-belvedere,\"Ref.: CA95903Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Village Damha Rio Preto I..: Casa Condomnio Village Damha Rio Preto I, Casa Condominio, Dormitrios: 03, Tipo Apto.: 03, C/ A/e: 03, Cozinha: 01, Cozinha Planejada, Fogo, Lavabo, Salas : 01, Sala P/ Ambientes : 02, Piscina, Ducha Externa, Varanda, rea de Servio, Wc. de Empregada/servio, Garagem Coberta: 02, Churrasqueira\",Ref.: CA95903 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Village Damha Rio Preto I,https://thumbs4.properati.com/2/595nD1yJ6OYSKSxIr0D1iMhNilQ=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2205/060de194-4e66-4f1e-b0cc-dd05e276539f.jpg\n2568b8aa05b9d3cb3e9e8ef74c4461c34d2d57b5,2014-10-05,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8350772,-49.369111\",-20.8350772,-49.369111,3000,BRL,2371.98,768.18,,,,,,,,http://www.properati.com.br/r1q8_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95905Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Quinta das Paineiras..: Salo Comercial No Quinta das Paineiras, Salo Comercial, Terrea, Cozinha: 01, Escritrio, M2 rea Construida: 225\",Ref.: SA95905 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Quinta das Paineiras,https://thumbs4.properati.com/6/2tu7W_u475v3n8Ubll7avmjLXPI=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2130/0y7ijJHaZqFbrC0LSLFy.jpg\n0dff14f277324eb9f04d59b6c26758ccdb744e27,2014-12-05,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8126181,-49.3404534\",-20.8126181,-49.3404534,3700,BRL,2925.47,947.43,,,,,,,,http://www.properati.com.br/udzy_alugar_casas_sao-jose-do-rio-preto_avenida-miguel-damha,\"Ref.: CA95938Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Damha III..: Linda Casa Tipo Sobrado No Condomnio Damha Iii, Casa Condominio, Sobrado, Dormitrios: 03, Suite Master: 01, C/ Hidro, Tipo Apto.: 02, C/ A/e, Ducha Dupla, Lavatrio Duplo, Cozinha: 01, Cozinha Planejada, Despensa, Escritrio, Lavabo, Salas : 01, Sala P/ Ambientes : 02, Varanda, rea de Servio, Lavanderia, Quarto de Empregada, Wc. de Empregada/servio, Forro de Laje, Garagem Descoberta: 02, Garagem Coberta: 02, Churrasqueira\",Ref.: CA95938 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Damha III,https://thumbs4.properati.com/0/FGZdTzG9TG6qqioIMRxZ7WLDQWY=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2452/bVU2c6naoVF7KCpphJqL.jpg\n6b3bff7cc70a79dfed41fc0ae514a7ad16a328b8,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,7000,BRL,6640.22,2150.47,,88,24.437159090909088,79.54545454545455,,,,http://www.properati.com.br/ifvc_alugar_comercial_vila-olimpia,\"\tEdifício comercial de excelente padrão, localizado em ponto nobre da Vila Olímpia, próximo da Av. dos Bandeirantes e Shopping Vila Olímpia.\t Prédio conta com 3 elevadores de alta velocidade, sistema de proteção contra incêndio, ar condicionado central, próximo a bancos. Referíªncia: CO65\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",\nc26e111d703af6f65be91df94c274bbd41585a40,2014-08-21,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.6357809,-46.5324419\",-23.6357809,-46.5324419,50000,BRL,39533.44,12803.11,,,,,,,,http://www.properati.com.br/nqbl_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95307Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Rodovia Assis ChateaubriandWcs.: 4, Escritrio, M2/ Terreno: 4.000, Detalhes: Barraco Com 4.000 M\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Rodovia Assis Chateaubriand,https://thumbs4.properati.com/0/lJ2ffPr7gtS2vlQuGTg_zDX6844=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1592/WQmB3JTS7Y2N72aUI5Ud.jpg\n2e8ffab1b55b5245e917b3597009338cb92b6586,2014-10-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7807632,-49.3985157\",-20.7807632,-49.3985157,50000,BRL,39533.44,12803.11,,,,,,,,http://www.properati.com.br/rgyw_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95804Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Waldemar VerdiM2/ Terreno: 6.000, M2 rea Construida: 3.200\",Salo,https://thumbs4.properati.com/3/X38EXdJIkvCXPQCdWURfrgMMMWQ=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2270/OTptGk75zRPMzZ1pL1on.jpg\nc522d5f57ea8e14d18fa3ba746cb581cd379330a,2014-08-20,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,100000,BRL,79066.88,25606.22,,,,,,,,http://www.properati.com.br/np98_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95721Tipo: Salo IndustrialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial IWcs.: Vrios, M2/ Terreno: 13.000, M2 rea Construida: 8.500, Detalhes: tima Localizao\",Tipo: Salo Industrial Cidade: So Jos do Rio Preto - SP Bairro: Dist. Industrial I,https://thumbs4.properati.com/6/jARKWDWV0rGe-HzGUtUeE0X3knw=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1549/ZaCxToSHCaeCL7GxZ08g.jpg\n07383fafc72a9aa9f0286b841b782ca718485de8,2014-09-01,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178198,-49.3468294\",-20.8178198,-49.3468294,3500,BRL,2767.31,896.21,,,,,,1,,http://www.properati.com.br/o246_alugar_casas_sao-jose-do-rio-preto_avenida-nadima-damha,\"Ref.: CA95827Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Damha II (Res. Jardins)Dormitrios: 03, Suite: 03, C/ A/e: 03, Sacada, Sala de Visita, Copa, Cozinha, Cozinha Planejada, Despensa, Piscina, rea de Servio, Lavanderia, Wc. de Empregada/servio, Garagem Descoberta: 02, Garagem Coberta: 02, Churrasqueira, Acabamento Em Gesso, Sanca, Forro de Laje, Piso Salas: Frio;, Documentao: Em Dia.\",Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Damha II (Res. Jardins),https://thumbs4.properati.com/6/Bq9TbjreWNnjd2VrvJ5oieGegeQ=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1889/db5caa0b-ec86-44f4-9c0f-ab26a6816b62.jpg\n179f70a47a9ce50e161ea483ffee741a8e1c7fb2,2014-08-14,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178411,-49.387605\",-20.8178411,-49.387605,3500,BRL,2767.31,896.21,,,,,,,,http://www.properati.com.br/mpsx_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95861Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Redentora TerreaM2 rea Construida: 190, Acabamento Em Gesso, Forro de Laje, Pintura Nova, Piso Salas: Frio\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Redentora Terrea,https://thumbs4.properati.com/1/VQPzYdCL1X2L1IkzU17WHDuej9s=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1279/nGCLTL2QhwMJSHGtxR7y.jpg\ne48c41f6ad3dba93e0ac6038a5aa5cda39d651d0,2014-09-01,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.1423284,-51.3750141\",-22.1423284,-51.3750141,3500,BRL,2767.31,896.21,,,,,,,,http://www.properati.com.br/o2m6_alugar_casas_sao-jose-do-rio-preto,\"Ref.: CA95898Tipo: Casa Comercial, Casa ResidencialCidade: So Jos do Rio Preto - SPBairro: Moyss Miguel Haddad..: Casa Residencial No Moyss Miguel Haddad, Casa Residencial, Dormitrios: 03, Suite: 03, C/ Hidro: 01, C/ A/e: 03, Sacada, Wc. Social: 01, Wcs. C/ A/e, Sala de Visita: 01, Copa: 01, Cozinha: 01, Cozinha Planejada, Despensa, Escritrio, Salas : 01, Sala P/ Ambientes : 03, Piscina, Varanda, rea de Servio, Lavanderia, Quarto de Empregada, Wc. de Empregada/servio, Ar Split, Ventilador, Interfone, Acabamento Em Gesso, Sanca, Tv Cabo, Campainha, Quintal, Grade, Murado, Forro de Laje, Piso Salas: Frio, Obs: Imvel Prximo Ao Shopping Iguatemi, M2 rea Construida: 450, Garagem Descoberta: 04, Garagem Coberta: 02, Churrasqueira, Jardim de Inverno, Jardim Interno, Iptu Valor: 199,00\",\"Ref.: CA95898 Tipo: Casa Comercial, Casa Residencial Cidade: So Jos do Rio Preto - SP Bairro: Moyss Miguel Haddad\",https://thumbs4.properati.com/5/fZwdpPACH02ObP9aj7-UFvVm0lE=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1937/a7WmbhKqWo7JqFgAHcOD.jpg\n9ea36b0e269fbf2581eef1510f0148594919b330,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,3150,BRL,2988.09,967.71,,45,21.50466666666667,70,,,,http://www.properati.com.br/ifxf_alugar_comercial_chacara-santo-antonio,\"\tNovAmérica Inside Park, o novo marco imobiliário de São Paulo. É um novo espaço, um novo bairro, uma nova opção de vida. É a expansão urbana mais consciente e mais urbana. Um mundo para morar, trabalhar e viver em plena harmonia. Uma região onde a vida social e a vida familiar se equilibram. Um lugar que concretiza o prazer de viver em uma grande metrópole. 1 torre comercial, escritórios de vila e lojas, 5 condomínios residenciais independentes e 2 parques em mais de 70.000 m² de terreno.\t\tNovAmérica Office Park é um conceito totalmente novo de local de trabalho, que valoriza eficiência e a qualidade de vida de seus ocupantes. EDSA em parceria com Neusa Nakata tiveram a missão de conceber um produto inusitado, diferenciado e particular. O resultado é um cenário privilegiado para que você e seus clientes tenham bem-estar em horário comercial.\t\tA região do NovAmérica reúne as principais empresas nacionais e multinacionais, que chegaram por aqui atraídas pela infraestrutura e pelas importantes e fáceis vias de acesso. O que confirma que a região é o novo pólo econômico de São Paulo.\t\tConheça os diferenciais do NovAmérica Office Park:\t\tÚnico na Nações Unidas a integrar um complexo formado por 1 torre comercial, escritórios de vila, lojas e 5 condomínios residenciais independentes.\tConceito consagrado de bem-estar em horário comercial.\tAcesso ao parque com mais de 10 mil m² destinado à cidade.\tPotencial de clientes vindos dos 5 condomínios residenciais.\tA oportunidade de morar e trabalhar de forma integrada e independente.\tServiços by Facilities Office.\tArquitetura e decoração inspirados nas ultimas tendências mundiais.\tProjeto paisagístico assinado por um dos mais conceituados escritórios do mundo, a EDSA. Referíªncia: CO150\",\"Comercio no(a) Chácara Santo Antônio , São Paulo - SP\",https://thumbs4.properati.com/2/2S3OsO4umzIVXFHbHKTrb7dk-x8=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/150/c0d9b8fc-3da8-4a27-ac1f-4e1684d35312.jpg\na5c14fe842664d12fe4bdfad313d5af251121d89,2014-10-01,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5882535,-46.6167776\",-23.5882535,-46.6167776,1400,BRL,1106.91,358.48,,,,,,,,http://www.properati.com.br/qz98_alugar_comercial_sao-jose-do-rio-preto_rua-da-imprensa,Ref.: SA95836Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Vila DinizDetalhes: Salo Comercial Com Aproximadamente 50 M e 02 Banheiros Com Acessibilidade.,Ref.: SA95836 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Vila Diniz,https://thumbs4.properati.com/9/CRgjdJjcRp1Lz-pPZChI7eL8ZIY=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2075/fOuQlJsX61PBHGGwhPSh.jpg\nb64a9bd212d9e91821e5e892eeff464bbc0202cd,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,9600,BRL,9106.57,2949.21,,120,24.57675,80,,,,http://www.properati.com.br/ifwi_alugar_comercial_vila-olimpia,\"\tConjunto Comercial com 120m² de área útil, 3 vagas, 3 banheiros, 1 copa. Referíªncia: CO112\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/0/3pwYR5bzXi_fuQfUVbzkPbFkst4=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/112/93f2b4dc-86f7-4544-803f-62dfec9dc967.jpg\n59a2898d29cb6860a70355c1b2028b9ab38d89d9,2015-01-13,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5456177,-46.563645\",-23.5456177,-46.563645,1801,BRL,1459.35,472.62,,,,,,2,,http://www.properati.com.br/vyso_alugar_apartamentos_tatuape,\"APTO DE 75M/2, COM 03 DORMITRIOS, SALA AMPLA COM SACADA, COZINHA PLANEJADA, WC SOCIAL, REA DE SERVIO COM WC, REPLETOS DE ARMRIOS, 01 VAGA DE GARAGEM FIXA, EXCELENTE ESTRUTURA DE LAZER COM PISCINA, PLAYGROUD, SALO DE FESTA, CHURRASQUEIRA, SALA DE GINASTICA, EXCELENTE LOCALIZAO, A 100 METROS DO METR.\",LOCAO TATUAPE CONDOMINIO ILHAS GREGAS,https://thumbs4.properati.com/6/-xzzzVWk3lxFITvW285d3YmP00c=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/13/e7c88a20-dcac-49b2-ae42-e782447d3f07.jpg\n1925426e5575ecd98f1e63422a187081754e0f5c,2015-01-13,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5444872,-46.5657875\",-23.5444872,-46.5657875,1499,BRL,1214.64,393.37,,,,,2,1,,http://www.properati.com.br/vysp_alugar_apartamentos_tatuape_rua-serra-de-braganca,\"APTO DE 40M/2, COM 01 DORMITRIO, SALA AMPLA COM SACADA, COZINHA, WC SOCIAL, SEMI-MOBILIADO COM FOGO, SUGGAR, GELADEIRA, MICRO-ONDAS, ARMRIOS PLANEJADOS NA COZINHA, CAMA BOX, GUARDA ROUPA, VENTILADOR DE TETO, RACK DE TV, 02 BANQUETAS, 02 MESINHAS DE CANTO, EXCELENTE ESTRUTURA DE LAZER COM PISCINA, PLAYGROUD, SALO DE FESTA, CHURRASQUEIRA, SAUNA, SALA DE FITINESS, BRINQUEDOTECA, SALO DE JOGOS, SALA DE LEITURA. EXCELENTE LOCALIZAO, PRXIMO DO SUPERMERCADO PO DE ACAR, FCIL ACESSO PARA O METR.\",NEW CONCEPT 22 A,https://thumbs4.properati.com/5/SXF7T5Zfxal6lcQifCYOufBKjYA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/14/0522b83e-c37e-4736-ac81-ca8540d2d806.jpg\nfda45d95b6fe8daf9215dcc80ad057531879eda4,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,4575,BRL,4339.84,1405.48,,120,11.712333333333333,38.125,,,,http://www.properati.com.br/ifxz_alugar_comercial_vila-olimpia,\"\tConjunto Comercial na Vila Olimpia, com 61m², podendo aumentar a área para 117m². Referíªncia: CO179\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/5/cZY_8L_8bfKOV9ay-F-6DsnRZ-c=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/179/0df8ffa9-49a9-49c0-9968-37c13719d904.jpg\n7eb9fb8ad21ff1da490b75fd04643939fd72edf1,2015-01-13,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5508578,-46.5679013\",-23.5508578,-46.5679013,1550,BRL,1255.99,406.76,,,,,11,1,,http://www.properati.com.br/vysn_alugar_apartamentos_tatuape,\"APTO DE 57M/2, COM 02 DORMITRIOS, SALA AMPLA COM SACADA, WC SOCIAL, COZINHA PLANEJADA, AMPLA REA DE SERVIO COM WC, 01 VAGA DE GARAGEM, SALO DE FESTA, CHURRASQUEIRA, PLAYGROUD, QUADRA DE FUTEBOL, EXCELENTE LOCALIZAO, PRXIMO AO SHOPP/METR BOULEVAR TATUAP.\",Apartamento,https://thumbs4.properati.com/4/mwisK4iz0H0viKmBVOGr8B40c1o=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/12/612ab301-0ac4-4c4c-9691-7278200c2b62.jpg\n59a2934bc5a4c3530613fae471a210ae63498d80,2014-09-02,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.826094,-49.376396\",-20.826094,-49.376396,1200,BRL,960.76,311.15,,,,,,1,,http://www.properati.com.br/ob16_alugar_apartamentos_sao-jose-do-rio-preto,\"Apartamento mobiliado, pronto para morar e com excelente localizao, na zona sul.2 dormitrios sendo 1 tipo apto todos com armrio, ventilador de teto e ar-condicionadosala com sacada para 2 ambientes com sofa e estantecozinha planejada com mesa com 4 cadeiras e fogo2 banheiros com box blindex, gabinete e chuveirorea de servio com armrio, varal e mquina de lavar1 vaga de garagem pilotisCondomnio: Porto eletrnico, portaria 24h, elevador, churrasqueira e piscina.\",Apartamento com 2 dormitrios em Rio Preto,https://thumbs4.properati.com/5/VXcYDJRN6VtNxvgVw-mxJOlL_sA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/premier/photos/111/91c65753-86b6-40fd-8673-7f8f107a8459.jpg\nd08581768058f5286ca4f209222d59a3f10af84d,2015-01-13,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.8877586,-47.081265\",-22.8877586,-47.081265,2401,BRL,1945.56,630.08,,,,,19,2,,http://www.properati.com.br/vysm_alugar_apartamentos_tatuape,\"APTO DE 93M/2, COM 03 DORMITRIOS, SENDO UMA SUTE, SALA AMPLA COM SACADA E DOIS AMBIENTES, WC SOCIAL, COZINHA, AMPLA REA DE SERVIO, REPLETO DE ARMRIOS, 02 VAGAS DE GARAGEM, LAZER COMPLETO COM PISCINA, PLAYGROUD, SALO DE FESTA, SALO DE JOGOS, SAUNA, CHURRASQUEIRA, EXCELENTE LOCALIZAO, PRXIMO DA PRAA SILVIO ROMERO.\",APTO LOCAO TATUAP,https://thumbs4.properati.com/3/d45ivnQIryA-xDQvwZrOc1pBPlE=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/11/85e5aee8-90fa-4295-bcb5-dce1ed7e789c.jpg\n7739326a3915df1654866f5c27d42e40f0038365,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2200,BRL,2086.92,675.86,,102,6.626078431372549,21.568627450980394,,,,http://www.properati.com.br/ifwp_alugar_comercial_vila-olimpia,\"\tConjunto Comercial com 46m², 2 banheiros, 3 salas, 1 vaga. Referíªncia: CO122\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/6/QhZrO4ITAg_PJagrwPKR0ywe4GI=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/122/80e20053-aaba-4f3b-a8f7-9dc2cdcb44a7.jpg\n4d949c2fcb78e76cf0cb2376ae3a3acc3b27994a,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2200,BRL,2086.92,675.86,,46,14.692608695652174,47.82608695652174,,,,http://www.properati.com.br/ifut_alugar_comercial_vila-olimpia,\"Conjunto Comercial na Rua Helena, com 46m², 1 vaga. Referíªncia: CO44\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/7/rah-1WLiSRF_nrLl-U2mEY27Gus=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/44/3d3a55f5-dd0c-4969-bb57-19f9a554c1f2.jpg\nc98dc531eb6cb68bcec0e60d7dc042bd663caa4d,2014-08-02,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.815191,-49.389435\",-20.815191,-49.389435,5000,BRL,4003.24,1296.47,,,,,,,,http://www.properati.com.br/ludd_alugar_casas_sao-jose-do-rio-preto,\"Imvel com excelente localizao, com recepo, 1 sala com banheiro privativo, 3 salas amplas + 1 interna, todos os ambientes com ar condicionado, cozinha, despensa, garagem interna para vrios veculos. IMVEL SER ENTREGUE REFORMADO E COM AS ACESSIBILIDADES EXIGIDAS!\",Casa Comercial,https://thumbs4.properati.com/8/3TeTIOIgyjtraKZz08buZLIU8W8=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/premier/photos/80/6a0fcb3e-3e78-434f-9624-a5621798b2b2.jpg\ne85c67a2bc55f4834be8d4cf1fd96340ef4ce129,2014-08-04,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8379877,-49.385659\",-20.8379877,-49.385659,800,BRL,632.5,204.84,,,,,,1,,http://www.properati.com.br/lxpc_alugar_casas_higienopolis,\"Ref.: AP95874 Tipo: ApartamentoCidade: So Jos do Rio Preto - SPBairro: Higienpolis..: Apartamento Novo No Jardim Higienopolis, Apartamento, rea Util M2: 50, Dormitrios: 01, C/ A/e, Sacada, Wc. Social: 01, Cozinha C/ A/e, Lavanderia, Elevador, Piso Dormitrios: Porcelanato, Piso Salas: Porcelanato, Obs: Prdio Novo.apto Nunca Habitado., rea de Lazer, Garagem Coberta: 01, Churrasqueira, Espao Gourmet\",Tipo: Apartamento Cidade: So Jos do Rio Preto - SP Bairro: Higienpolis,https://thumbs4.properati.com/6/8tmxgf5PTdg11vI4rVdPwXy39gw=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/806/2077f853-c360-4cd7-b5c8-a33f76415c40.jpg\n33b22b30a043e5a868df61862bb97698b453df89,2014-12-05,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7910821,-49.3781115\",-20.7910821,-49.3781115,800,BRL,632.5,204.84,,,,,,1,,http://www.properati.com.br/ue05_alugar_apartamentos_sao-jose-do-rio-preto_rua-pedro-mulati,\"Ref.: AP95816Tipo: ApartamentoCidade: So Jos do Rio Preto - SPBairro: Jardim ConceioDormitrios: 02, C/ A/e, Wc. Social, Box Wcs., Sala de Estar, Cozinha, Piscina, rea de Servio, Garagem Coberta: 01, rea Util M2: 60, Condominio C/ rea de Lazer, Piscina Adulto, Playground, Valor Condominio R$-: 190,00\",Ref.: AP95816 Tipo: Apartamento Cidade: So Jos do Rio Preto - SP Bairro: Jardim Conceio,https://thumbs4.properati.com/2/4RA-EyT8LswOeQ6lcBbkzLlKjII=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2459/jWyxMNGlETMMxgj2uW9o.jpg\ne2235d97414fcc1a31865b1abe71c1cf85ae01fa,2014-11-17,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7780086,-49.3450562\",-20.7780086,-49.3450562,2700,BRL,2134.78,691.36,,,,,,,,http://www.properati.com.br/tdi5_alugar_casas_sao-jose-do-rio-preto_avenida-belvedere,\"Ref.: CA95926Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Village Damha Rio Preto I..: Casa Condomnio Village Damha Rio Preto, Casa Condominio, Terrea, Dormitrios: 3, Suite: 1, Tipo Apto.: 2, C/ A/e, Lavatrio Duplo: 1, Cozinha C/ A/e: 1, Cozinha Planejada, Escritrio, Lavabo, Salas : 1, Sala P/ Ambientes : 2, Varanda, rea de Servio, Wc. de Empregada/servio, Obs: Espao Para Colocar Piscina, M2 rea Construida: 180, Garagem Descoberta: 2, Garagem Coberta: 2, Churrasqueira, Detalhes: Com Armrios .\",Ref.: CA95926 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Village Damha Rio Preto I ,https://thumbs4.properati.com/3/ZZ3MVCiFvwDaZxqgfl5oQJ1Vp6c=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2390/5d2ae653-6549-4772-b486-cd9360af6ebd.jpg\n1334a26f10895f5a21b6db0adf96e2ff1dc83799,2014-09-16,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7780086,-49.3450562\",-20.7780086,-49.3450562,1250,BRL,988.31,320.07,,,,,,,,http://www.properati.com.br/q4jz_alugar_casas_sao-jose-do-rio-preto_avenida-belvedere,\"Ref.: CA95901Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Maria Stella..: Casa Condomnio Maria Stella, Casa Condominio, Terrea, Dormitrios: 3, Tipo Apto.: 1, Wc. Social: 1, Cozinha: 1, Cozinha Planejada, Salas : 01, Sala P/ Ambientes : 02, Varanda, rea de Servio, Lavanderia, Garagem Coberta: 02, Salo de Festa, Playground, Piscina Adulto, Quadras Poliesportivas: 1, Campo de Futebol: 1, Valor Condominio R$-: 260,00\",Ref.: CA95901 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Maria Stella,https://thumbs4.properati.com/3/nKZAghWN-90yQywuniXpPPLO9sk=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2011/e55aad60-d657-4c71-b732-96032067b76f.jpg\n40c34e74b932ff6e10ff49774a8f7fb6e982c1c2,2014-11-30,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8081017,-49.3505771\",-20.8081017,-49.3505771,4500,BRL,3558.01,1152.28,,,,,,,,http://www.properati.com.br/tz24_alugar_comercial_sao-jose-do-rio-preto_rua-valdomiro-nadotti,\"Ref.: SA95928Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Tres Maria..: Salo Comercial No Bairro Trs Maria, Salo Comercial, Detalhes: 160 Metros Mais 40 Metros de Mesanino.\",Ref.: SA95928 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Tres Maria,https://thumbs4.properati.com/3/Yg9eVpfZKwd2s12w6w1yQ4YYVhY=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2402/MTVaVFERWIxvf0IcXQaQ.jpg\n716428a7c9f46f98fd78e36a72109b0c0ec43753,2014-11-30,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8081017,-49.3505771\",-20.8081017,-49.3505771,4500,BRL,3558.01,1152.28,,,,,,,,http://www.properati.com.br/tz25_alugar_comercial_sao-jose-do-rio-preto_rua-valdomiro-nadotti,\"Ref.: SA95929Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Tres Maria..: Salo Comercial No Bairro Trs Maria, Salo Comercial, M2/ Terreno: 200, Detalhes: 140 Metros Mais 40 Metros de Mesanino.\",Ref.: SA95929 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Tres Maria,https://thumbs4.properati.com/9/a_rVYKLimoBl774T612e8o5Icfo=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2403/fhkihJbLNgNCmHo7eBRG.jpg\n2102860e4c561ee2afec1c15fb71f7c6cfafc28d,2014-08-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,9000,BRL,7116.02,2304.56,,,,,,,,http://www.properati.com.br/muuy_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95893Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Ch. Jockey Clube..: Salo Comercial Na Chcara Jockey Clube, Salo Comercial, M2/ Terreno: 5.000, M2 rea Construida: 1.200, Detalhes: Galpo Com Piso Cimento Polido, Estrutura Metlica, Escritrio, Cozinha, 02 Wc, Entrada Pela Frente e Lateral Para Caminho.p Direito Alto Com 6,/2 M.\",Ref.: SA95893 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Ch. Jockey Clube,https://thumbs4.properati.com/3/H-b0Ol05_NX0A5soGXBvD_dA3wk=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1482/gCB4KEDxOoIlG9HlGbCW.jpg\ndb16c4572d4f19875153b041d1dcb6b82115e6a7,2014-11-03,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8174527,-49.4306981\",-20.8174527,-49.4306981,18000,BRL,14232.04,4609.12,,,,,,,,http://www.properati.com.br/sjyy_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95923Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Parque Industrial..: Salo Comercial No Parque Industrial, Salo Comercial, M2/ Terreno: 3.000, M2 rea Construida: 1.780, Detalhes: 1.000m de Patio.escritrio Com Elevado Vrias Salas, Cozinha, Wc, Vestirio Mas/fem;04 Salas de Descanso Para Motorista Com Vestirio, 02 Chuveiros e 04 Wc;cozinha Externa Com Quiosque + 02 Wc Mas/fem;parte Operacional Com P Direito de 7 Metros, e A Lateral Toda Com Embarque e Desembarque;ptio Com Espao Para Carretas, Caminhes e Carros;portaria Na Entrada do Ptio.\",Ref.: SA95923 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Parque Industrial,https://thumbs4.properati.com/0/wtHJ8Xcu4pqyV7YSP06g_N1yrfg=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2356/rO0uXvqSM9ilLshNDz0f.jpg\nc8c81389391a237255bade4a0608212fa62e13b1,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,4200,BRL,3984.12,1290.28,,107,12.058691588785047,39.25233644859813,,,,http://www.properati.com.br/ifxy_alugar_comercial_vila-olimpia,\"\tConjunto Comercial na Vila Olimpia, com 56m² de área útil, excelente localização.  Referíªncia: CO178\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/7/YjqSlFDSnOcayBrp2UtD_X2xaJM=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/178/fa4df6b6-bb36-40a4-a46b-7b1438c77d03.jpg\ne1f129a3f1296a7e7a3b60d5b96d61c49159900c,2014-11-19,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.9295411,-46.3418105\",-23.9295411,-46.3418105,1600,BRL,1628.47,527.39,,32,16.4809375,50,,1,,http://www.properati.com.br/tkvf_alugar_apartamentos_sao-paulo,\"A 3 Milenio oferece este(a) Apartamento em Sao Vicente, no bairro Morro dos Barbosas - 1 dormitórios. Gostou desse(a) Apartamento em Sao Vicente? Então veja mais informações! Acesse o nosso site clicando no botão Contate o anunciante ou ligue - ou ainda entre em contato conosco pelo email vendas@ Obrigado!\",\"Apartamento em Sao Vicente, no bairro Morro dos Barbosas - 1 dormitórios\",https://thumbs4.properati.com/5/FvlCdG4KWDtvmzsszDUttj3AuAY=/trim/198x0/smart/filters:strip_icc()/www.imobiliariasdesantos.com.br/fotos/F00/72/807200-DSC03573.JPG\na8821d1c24cccd45d37ef69cf2b29ef3be744fad,2014-11-17,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8456698,-49.4030718\",-20.8456698,-49.4030718,3200,BRL,2530.11,819.39,,,,,,1,,http://www.properati.com.br/tdi2_alugar_apartamentos_sao-jose-do-rio-preto_avenida-anisio-haddad,\"Ref.: AP95925Tipo: ApartamentoCidade: So Jos do Rio Preto - SPBairro: Cond. Green Fields..: Apartamento No Condomnio Green Fields, Apartamento, rea Util M2: 152, Dormitrios: 03, Suite Master: 01, Closet , Tipo Apto.: 02, C/ A/e: 02, Wc. Social: 02, Sala de Visita: 01, Cozinha Planejada, Garagem Coberta: 02\",Ref.: AP95925 Tipo: Apartamento Cidade: So Jos do Rio Preto - SP Bairro: Cond. Green Fields,https://thumbs4.properati.com/4/oRIx16Fpw4LPkRsB59wlBS_mxVo=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2387/ae2a6d87-5760-44ff-a47f-d237a5321c3c.jpg\n08918f4a93c54f4505b783a8e31ef11842c55e56,2014-10-01,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5882535,-46.6167776\",-23.5882535,-46.6167776,80000,BRL,63253.52,20484.98,,,,,,,,http://www.properati.com.br/qz9a_alugar_comercial_sao-jose-do-rio-preto_rua-da-imprensa,\"Ref.: SA95835Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Vila DinizM2/ Terreno: 12.000, Detalhes: - Salo Com 5.000 M e Bastante rea Para Estacionamento Aberto.Ideal Para Atacadista, Hipermercado e Distribuidora, Entre Outros.\",Ref.: SA95835 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Vila Diniz,https://thumbs4.properati.com/1/PkKXX6cNiwu9krqBtdWDinLG89A=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2077/vSsX8s9IzXdbNCXPId0W.jpg\n1ce358d0b5c35f146d70dff4089a8b3d287cb7b9,2014-10-08,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8085627,-49.3452813\",-20.8085627,-49.3452813,5500,BRL,4348.67,1408.34,,,,,,,,http://www.properati.com.br/r6de_alugar_comercial_sao-jose-do-rio-preto_avenida-sebastiao-tavares-da-silva,\"Ref.: SA95809Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Vista AlegreM2/ Terreno: 360, M2 rea Construida: 360, Detalhes: Salo Com Vrias Divisrias.\",Salo,https://thumbs4.properati.com/8/dhtnMWfIFZ8mMCFVDpxpvjoF0LA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2184/l63oynNjEecn8u1Dzf3W.jpg\nb6ed51b61bb57831cc00d904741b4f544cafc28f,2014-08-04,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178198,-49.3468294\",-20.8178198,-49.3468294,5500,BRL,4348.67,1408.34,,,,,,1,,http://www.properati.com.br/lxoz_alugar_casas_sao-jose-do-rio-preto,\"Ref.: CA95886Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Damha II(Res. Jardins)..: Casa Condomnio Damha II, Casa Condominio, Sobrado, Dormitrios: 03, Suite: 01, C/ Hidro, Tipo Apto.: 02, C/ A/e: 03, Roupeiro, Home, Cozinha: 01, Cozinha Planejada, Despensa, Escritrio, Lavabo, Salas : 01, Sala P/ Ambientes : 03, Piscina, Varanda, rea de Servio, Quarto de Empregada, Wc. de Empregada/servio, Aquecedor Solar, M2 rea Construida: 350, rea de Lazer, Garagem Descoberta: 03, Garagem Coberta: 03, Churrasqueira\", Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Damha II,https://thumbs4.properati.com/1/gEw1FIkmFLn2_zGBjqnuUzcifYU=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/793/e9d2d588-8d92-4070-b7d6-5b55e4484038.jpg\n1273c64fb8b9402dfad98d3984dec2998d8bdb68,2014-08-15,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8126181,-49.3404534\",-20.8126181,-49.3404534,5500,BRL,4348.67,1408.34,,,,,,1,,http://www.properati.com.br/mqtl_alugar_casas_sao-jose-do-rio-preto_avenida-miguel-damha,\"Ref.: CA95731Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Damha IVDormitrios: 03, Suite: 01, Closet : 01, C/ Hidro, Tipo Apto.: 02, C/ A/e: 02, Wcs.: 05, Wcs. C/ A/e: 04, Box Wcs.: 04, Copa: 01, Cozinha: 01, Cozinha C/ A/e, Despensa, Escritrio, Lavabo, Salas : 01, Sala P/ Ambientes : 02, Piscina, Varanda, rea de Servio, Wc. de Empregada/servio, M2/ Terreno: 420, M2 rea Construida: 380, rea de Lazer, Garagem Descoberta: 02, Garagem Coberta: 02, Churrasqueira, Piso Dormitrios: Porcelanatoq, Piso Salas: Porcelanato, Obs: Imvel Muito Bem Conservado, timo Acabamento., Valor Condominio R$-: 300,00, Detalhes: Toda Reformada.\",Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Damha IV,https://thumbs4.properati.com/6/H5vuIYMzk8pMuWJ-OjcdH4GItq8=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1367/9717e95d-fe6f-4cbc-bb5d-21c2fe92d294.jpg\n6aa6bf8a204f123441efb9f97699ee24cf8f9932,2014-08-15,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178198,-49.3468294\",-20.8178198,-49.3468294,5500,BRL,4348.67,1408.34,,,,,,1,,http://www.properati.com.br/mqtn_alugar_casas_sao-jose-do-rio-preto_avenida-nadima-damha,\"Ref.: CA95797Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Damha ISobrado, Dormitrios: 03, Suite: 01, Tipo Apto.: 02, Wcs.: 01, Cozinha Planejada, Escritrio, Lavabo, Salas : 01, Sala P/ Ambientes : 03, Piscina, rea de Servio, Wc. de Empregada/servio, rea de Lazer, Garagem Coberta: 03, Churrasqueira, Ar Condicionado, Ventilador, Interfone, Piso Dormitrios: Taco, Piso Salas: Frio\",Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Damha I,https://thumbs4.properati.com/0/NAjAu7cPHQwzwT2j3k1G4X7-A3U=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1369/7b6ca8dd-648a-4e18-b9f5-272073bfbf69.jpg\n8a977c0c4b9ef700024cb2ee3e59de53bcf599c8,2014-07-16,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2000,BRL,1897.2,614.42,,70,8.77742857142857,28.571428571428573,,2,,http://www.properati.com.br/ifzl_alugar_apartamentos_vila-olimpia,\"\tApartamento na Vila Olimpia, sala para 2 ambientes, 2 dormitórios com armários embutidos, cozinha, lavanderia, quarto na área de serviço, 2 banheiros, 1 vaga. Referíªncia: AP237\",\"Apartamento no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/9/waPGo7zWMk2XTzN-br6B0h4Nrgo=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/237/75daca8f-ee37-4813-97af-b4fa00920d4f.jpg\nb48b18eca01fc2732d6afe024904eb1e900cc52a,2014-07-16,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2000,BRL,1897.2,614.42,,54,11.378148148148147,37.03703703703704,,2,,http://www.properati.com.br/ifzn_alugar_apartamentos_saude,\"\tÓtimo apartamento proximo ao Metrê Praça da Arvore, sala para 2 ambientes, 2 dormitórios com armários embutidos, cozinha com armários, banheiro social e de serviço, 1 vaga na garagem, quadra, piscina e play.\tCom pintura nova, pronto para morar!! Referíªncia: AP239\",\"Apartamento no(a) Saúde , São Paulo - SP\",https://thumbs4.properati.com/0/Zof1-heqqvAgC3xdyYRYiQHIX2I=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/239/450071da-5288-4f26-bbb4-66bcacaef572.jpg\n636cbd951ef34773973cfdef37746b911d07a24c,2014-07-16,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,4000,BRL,3794.41,1228.84,,200,6.1442,20,,4,,http://www.properati.com.br/ifxa_alugar_casas_saude,\"\tAluga sobrado em zona mista, residencial e ou serviços, a uma quadra da Av. do Cursino e a 1000m, do Shopping Plaza Sul, 4 dormitórios, sendo uma suite, ampla sala, mais sala de jantar, cozinha, edicula com 3 quartos, mais lavanderia, garagem para 3 veiculos, casa de esquina, com portões automaticos.  Referíªncia: CA145\",\"Casa no(a) Saúde , São Paulo - SP\",https://thumbs4.properati.com/3/0sie3N08lMquoZ655zNy1CeDUbU=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/145/9fef5234-2fa4-4974-b24c-2b3cf6c4c542.jpg\n0812a419c00dcbaaaa926ad4e8de47da7959f9d9,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,5700,BRL,5407.01,1751.09,,127,13.788110236220472,44.881889763779526,,,,http://www.properati.com.br/ifzp_alugar_comercial_saude,\"\tConjunto Comercial proximo do Metrô São Judas, com 109m² de área útil, dividido em 5 salas, com possibilidade de vão livre, 3 banheiro, 1 copa, 3 vagas, prédio 24 horas.  Referíªncia: CO241\",\"Comercio no(a) Saúde , São Paulo - SP\",https://thumbs4.properati.com/1/0kl3BRCM4riJX3LhCObIu4wuBxQ=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/241/25ac4ee5-f867-4808-b226-837aefd7ba2c.jpg\n570fece17687d05345022d1567c79dd80bd1dcb0,2014-12-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8312527,-49.360102\",-20.8312527,-49.360102,15000,BRL,11860.02,3840.93,,,,,,,,http://www.properati.com.br/viin_alugar_comercial_sao-jose-do-rio-preto_avenida-marginal-lineu-alcantara-gil,\"Ref.: SA95950Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Campo Verde..: Salo Comercial No Distrito Industrial Campo Verde, Salo Comercial, M2/ Terreno: 5.000, M2 rea Construida: 3.000, Detalhes: tima Localizao Com Asfalto Para Rua, Estacionamento Para 60 Carros.barraco 5.000m2c/ Escritrio Isolado Ao Lado do Galpo C/ 6 Salas Grandes Von Livre Cond. Port.24h.\",Ref.: SA95950 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Dist. Industrial Campo Verde,https://thumbs4.properati.com/6/7lTVZ92lzm8ap5amDGM_eb1EHOU=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2528/yS1CaXFW8XYwJdPuhgGn.jpg\n2ee8e3818d61fdc4e01a5d89be181974d74e4380,2014-08-15,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8424141,-49.3549387\",-20.8424141,-49.3549387,15000,BRL,11860.02,3840.93,,,,,,,,http://www.properati.com.br/mqtc_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95109Tipo: Salo Comercial, Salo IndustrialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Tancredo Neves .Terrea M2/ Terreno: 2.100, M2 rea Construida: 936, Detalhes: Estacionamento Na Frente,entrada Lateral Para Carga e Descarga,prox. do Carrefour\",\"Tipo: Salo Comercial, Salo Industrial Cidade: So Jos do Rio Preto - SP Bairro: Dist. Industrial Tancredo Neves .\",https://thumbs4.properati.com/9/KVlFV9eR-3HhzpzA5EtDKJICEgY=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1358/k6zhNAyNgH9P1excuuTM.jpg\n0f0577616ba85404705aaead7f35ff6e8b4a91da,2014-08-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5733308,-46.544242\",-23.5733308,-46.544242,15000,BRL,11860.02,3840.93,,,,,,,,http://www.properati.com.br/mt62_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: CO95825 Tipo: Predio Comercial, Salo Comercial, Salo Industrial Cidade: So Jos do Rio Preto - SP Bairro: Pq. IndustrialWc. Social: 02, Salas : 06, M2/ Terreno: 1.113, Documentao: Em Dia., Detalhes: Banheiro Feminino e Masculino, 06 Salas Amplas, Sendo de 420 M a Maior.o Salo Possui Ambientes Para Reunies, Sala de Refeitrio de 93 M e Armrio Embutido, Alarme, Campainha, Interfone, Cerca Eltrica e Estacionamento de 258 M Com 25 Vagas Cobertas.\",\"Tipo: Predio Comercial, Salo Comercial, Salo Industrial Cidade: So Jos do Rio Preto - SP Bairro: Pq. Industrial\",https://thumbs4.properati.com/5/ug_ZifuqqZGKLp9_hQAm2sSvkgE=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1436/Q14vgp5W0wZIU71vOSui.jpg\n8d6a13266a268bd8dd46f19df78ef71e3509ee5a,2014-10-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7700326,-49.3956468\",-20.7700326,-49.3956468,6500,BRL,5139.33,1664.4,,,,,,,,http://www.properati.com.br/ri3n_alugar_comercial_sao-jose-do-rio-preto_avenida-ada-marzochi-polachini,\"Ref.: SA95917Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Mini Dist. Industrial Adail Vetorasso..: Salo Comercial No Mini Destrito Industrial Adail Vetorasso, Salo Comercial, Wcs.: 02, Cozinha: 01, Escritrio, M2/ Terreno: 1.050, M2 rea Construida: 680, Detalhes: Barraco Novo, Com Pilar No Centro;porta Na Frente e Lateral;cobertura Metlica;p Direito 6 Metros.\",Ref.: SA95917 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Mini Dist. Industrial Adail Vetorasso,https://thumbs4.properati.com/2/3gLCbr6emuqSINA3fAYUW1zaIUM=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2283/grmYrDDM8HnJtcT4RzOD.jpg\ndac06563fc851c6596496ceaff68cbf177bb6dde,2014-10-01,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7863702,-49.3690389\",-20.7863702,-49.3690389,6500,BRL,5139.33,1664.4,,,,,,,,http://www.properati.com.br/qz9p_alugar_comercial_sao-jose-do-rio-preto_avenida-solon-da-silva-varginha,\"Ref.: SA95834Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Vila NovaesWc. Social: 03, Mesanino, M2/ Terreno: 530, M2 rea Construida: 480, Detalhes: Salo Comercial Com P Direito de 6m e Mezanino de 55 M.possui Aparelhagem de Ar Condicionado, Som Ambiente, Cmeras de Segurana e Estacionamento Para 18 Carros.local Ideal Para Lojas, Mercados, Igreja, Depsito, Entre Outros.\",Ref.: SA95834 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Vila Novaes,https://thumbs4.properati.com/8/qD9kCsVbiYyB0WGFw5WesI2Ny6s=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2092/d62f4d68-2ea5-4f83-bde9-fdc53bb504f2.jpg\n1ccba6f23edef69215ca9cfe74214a5276597714,2014-10-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,6500,BRL,5139.33,1664.4,,,,,,,,http://www.properati.com.br/ri3q_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95919Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Centenrio da Emancipao..: Salo Comercial No Distrito Industrial Centenrio da Emancipao., Salo Comercial, Cozinha: 02, Mesanino, Escritrio, M2 rea Construida: 1.015, Detalhes: Escritrio, Cozinha, 02 Wc, Mezanino, 2 Salas, Entrada Lateral.salo 700 Metrosdiviso 315 Metros.\",Ref.: SA95919 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Dist. Industrial Centenrio da Emancipao,https://thumbs4.properati.com/0/FlEAiRaerT0pRZEeW7AhhCuJjJc=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2286/v22UnUeHl8YbhJaP8IaU.jpg\na9d04cd869b56cac7bcb3a54a27147996a973a3d,2015-01-20,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5418835,-46.5583192\",-23.5418835,-46.5583192,1900,BRL,1539.57,498.6,,,,,16,1,,http://www.properati.com.br/w730_alugar_apartamentos_tatuape,\"APTO DE 58M/2, COM 02 DORMITRIOS, SENDO UMA SUTE, SALA AMPLA COM SACADA, COZINHA, WC SOCIAL, REA DE SERVIO, COM ALGUMAS MOBILIAS, TUDO DE PRIMEIRA, 02 VAGAS DE GARAGEM, LAZER COMPLETE, EXCELENTE LOCALIZAO, A UMA QUADRA DO METR.\",MOBILIADO EXCLUSIVE,https://thumbs4.properati.com/2/KuQXATs4BGrSaZvfCzOSMN2pqWs=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/19/30ad0c15-c9ef-48f7-a06e-2a0201bb7433.jpg\n5de8d0e3c8872b0af03bdc517a4a12021c48da59,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,24700,BRL,23430.5,7588.09,,289,26.25636678200692,85.46712802768167,,,,http://www.properati.com.br/ifvd_alugar_comercial_vila-olimpia,\"EDIFí�CIO COMERCIAL DE ALTí�SSIMO PADRí�O,  LOCALIZADO NO PONTO MAIS NOBRE DA REGIí�O, EM FRENTE AOSHOPPING VILA OLí�MPIA, ENTRE AV. DOS BANDEIRANTES E JUSCELINO KUBITSCHEK. OPRí�DIO CONTA COM 6 ELEVADORES DE ALTA VELOCIDADE, SENDO 1 PANORí�MICO, ARCONDICIONADO CENTRAL, FACHADA EM CORTINA DE VIDRO. EDIFí�CIO INTELIGENTE COMSOFISTICADO SISTEMA DE CONTROLE DE INCí�NDIO, CONSUMO DE ENERGIA. Referíªncia: CO66\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",\n705fdcf676aca2c9f51fcc0a332fcff39ee1706c,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,19500,BRL,18497.74,5990.59,,260,23.04073076923077,75,,,,http://www.properati.com.br/ifyk_alugar_comercial_vila-olimpia,\"\tConjunto Comercial com 260m² de área útil, 6 vagas, Ar condicionado Central. Referíªncia: CO200\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/0/-wzyHwNVYSdVIvzDSj7dz-RtyfY=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/200/f2ef8797-b051-4b62-b4fe-e8fdb7523a26.jpg\n179ce00d44c6fafbac93e139f052ab4ce304100d,2014-08-04,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,4200,BRL,3320.8,1075.46,,,,,,,,http://www.properati.com.br/lxpa_alugar_casas_sao-jose-do-rio-preto,\"Ref.: CA95877 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Village La MontangneDormitrios: 3, Suite: 1, C/ Hidro: 1, Tipo Apto.: 2, C/ A/e: 3, Cozinha Planejada, Escritrio, Lavabo, Salas : 1, Sala P/ Ambientes : 3, Piscina, rea de Servio, M2/ Terreno: 360, M2 rea Construida: 250, Garagem Descoberta: 2, Garagem Coberta: 2\",Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Village La Montangne,https://thumbs4.properati.com/8/XTvYImGZcecKNC8xwzjnrrqWibg=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/804/ce485ed8-97e3-4af6-bc5e-3d347e06b31d.jpg\n868d3ff8ea898557e9819638705d2f823431d000,2015-01-13,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.521407,-46.5769202\",-23.521407,-46.5769202,1500,BRL,1215.45,393.63,,,,,13,1,,http://www.properati.com.br/vysr_alugar_apartamentos_tatuape,\"APTO DE 60M/2, COM 02 DORMITRIO, SALA AMPLA COM SACADA, WC SOCIAL, COZINHA, REA DE SERVIO, 01 VAGA DE GARAGEM, EXCELENTE ESTRUTURA DE LAZER COM PISCINA, PLAYGROUD, SALO DE FESTA, CHURRASQUEIRA, EXCELENTE LOCALIZAO, FCIL ACESSO AO SHOPPING METR/TATUAP.\",131 VITORIA,https://thumbs4.properati.com/0/yyioUci-ExAIuKlfIudXKNKaMAs=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/16/ff90ae98-dbde-47dc-9f04-32cdb2d2d0d3.jpg\nb9de26b4b13ad0f58469677b72b5171c2b04ae1f,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,13500,BRL,12806.12,4147.33,,183,22.663005464480875,73.77049180327869,,,,http://www.properati.com.br/ifv7_alugar_comercial_vila-olimpia,CONJUNTO COMERCIAL - RECEPCAO - HD - 4 SALAS - 2 WC - COPA  Referíªncia: CO60,\"Comercio no(a) Vila Olímpia , São Paulo - SP\",\n416be9056b69e83819532b65a04c6d1f7135f1ca,2014-12-11,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2400,BRL,1897.57,614.54,,,,,,,,http://www.properati.com.br/uict_alugar_comercial_jardim-maracana,\"Ref.: SA95945Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Jardim Maracan..: Salo Comercial No Jardim Maracan, Salo Comercial, Wc. Social: 02, Cozinha: 01, Forro de Laje, Piso Salas: Frio, M2/ Terreno: 225, M2 rea Construida: 130\",Ref.: SA95945 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Jardim Maracan,https://thumbs4.properati.com/5/3964ltfTag6YXQlyxEM19akYy1s=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2500/f25a8d90-6759-426c-a4ed-d8aefc6b19a4.jpg\nc1aff8edd38c3254c5775927802a8b8fae45a1d8,2014-08-05,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2400,BRL,1897.57,614.54,,,,,,1,,http://www.properati.com.br/mel5_alugar_casas_bosque-da-saude,\"Ref.: CA95883Tipo: Casa ResidencialCidade: So Jos do Rio Preto - SPBairro: Bosque Da Saude..: Casa Residencial No Bosque da Saude, Casa Residencial, Dormitrios: 03, Tipo Apto.: 01, C/ A/e: 03, Wc. Social: 01, Copa: 01, Cozinha: 01, Despensa, Salas : 02, Varanda, Garagem Descoberta: 02, Garagem Coberta: 02\",Tipo: Casa Residencial Cidade: So Jos do Rio Preto - SP Bairro: Bosque Da Saude,https://thumbs4.properati.com/0/aAdm951DKitDcqkiJ8p68O6xdNA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/848/083f9a71-b22a-4897-bf14-72fbe585dea5.jpg\ne4d569301fb8a21047d67f193929ecf360e9405e,2015-01-11,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,750,BRL,600.6,194.51,,,,,,1,,http://www.properati.com.br/vxnv_alugar_apartamentos_jardim-satelite,\"Excelente apartamento em frente ao condomnio Quinta das Flores totalmente reformado com 2 dormitrios, sala, cozinha planejada, rea de servio, lavabo com gabinete, wc com box blindex e 1 vaga de garagem.Ideal para casal sem filhos e sem animais\",Excelente apartamento no Jardim Satlite,https://thumbs4.properati.com/1/RhUtbG6YnK8FCa_yOduiEf3yyj0=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/tyrreno/photos/1074/71219c81-463f-4710-a46d-5e7e2fee9362.jpg\n6b59e27767f7570db49b2175077b1c059fa20b88,2014-10-01,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5715766,-46.6697673\",-23.5715766,-46.6697673,3100,BRL,2451.06,793.79,,,,,,,,http://www.properati.com.br/qz9r_alugar_comercial_sao-jose-do-rio-preto_avenida-brasil,\"Ref.: SA95828Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Jardim MugnaniWc. Social: 02, Cozinha, M2/ Terreno: 350, M2 rea Construida: 210, Detalhes: - Salo Novo!\", Ref.: SA95828 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Jardim Mugnani,https://thumbs4.properati.com/5/ShU0-2rvOmZQkWG3Ml57SSATz_s=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2094/VmmbZZ9w1FykW0ldwpGM.jpg\n3931096ab81c0a74496858654375447e859df8f2,2014-12-05,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7910821,-49.3781115\",-20.7910821,-49.3781115,880,BRL,695.77,225.33,,,,,,1,,http://www.properati.com.br/ue04_alugar_apartamentos_sao-jose-do-rio-preto_rua-pedro-mulati,\"Ref.: AP95815Tipo: ApartamentoCidade: So Jos do Rio Preto - SPBairro: Jardim ConceioCobertura, Dormitrios: 02, C/ A/e, Wc. Social, Box Wcs., Sala de Estar, Cozinha, Piscina, rea de Servio, rea de Lazer, Garagem Coberta: 01, rea Util M2: 65, Playground\",Ref.: AP95815 Tipo: Apartamento Cidade: So Jos do Rio Preto - SP Bairro: Jardim Conceio,https://thumbs4.properati.com/3/0zqbkQ73LUnQeQMp0yntvzoZrq8=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2458/Dv0976z6fjHNbJf7oAX0.jpg\nc15e079e557ec6ad9d86baede07324e678686764,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,3800,BRL,3604.66,1167.39,,88,13.265795454545456,43.18181818181818,,,,http://www.properati.com.br/ifzr_alugar_comercial_saude,\"\tConjunto Comercial proximo do Metrô São Judas, com 76m², 2 banheiros, 2 vagas, 1 copa, predio 24 horas. Referíªncia: CO243\",\"Comercio no(a) Saúde , São Paulo - SP\",https://thumbs4.properati.com/4/h5_FesPCfkGnmz5ac8c3DvXy_cE=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/243/68c5314b-39b1-4ebd-af49-694d915540b0.jpg\n62cbd166c6e120af08202b4db367db83240ed7e1,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,8500,BRL,8063.11,2611.28,,300,8.704266666666667,28.333333333333332,,,,http://www.properati.com.br/ifw2_alugar_comercial_vila-olimpia,\"\t\t\tLindo(a) Comercio de 300 metros quadrados no bairro Vila Olímpia na cidade de São Paulo - SP.\t\t\t, 2 banheiro(s), 6 vagas(s) de garagem.\t \t\tCondições de Pagamento: \t \t \t \t\tCaracteristicas: Referíªncia: CO93\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/1/gH6VwXVOHsfAy5JV8elaJg59lGA=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/93/4276fcba-994a-4296-9a35-65c580711457.jpg\n5a5bfb194fdbec1a633f5894a66c8bf45c8ae463,2015-01-06,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,1100,BRL,869.7,281.66,,,,,,,,http://www.properati.com.br/vv2s_alugar_apartamentos_sao-jose-do-rio-preto,\"Ref.: AP95935Tipo: ApartamentoCidade: So Jos do Rio Preto - SPBairro: Vila Itlia..: Apartamento Residencial Na Vila Itlia, Apartamento, rea Util M2: 63, Dormitrios: 02, Closet , Tipo Apto.: 01, Wc. Social: 01, Sala de Tv, Cozinha: 01, Cozinha C/ A/e, Garagem Coberta: 01, Detalhes: Prdio Novo.\",Ref.: AP95935 Tipo: Apartamento Cidade: So Jos do Rio Preto - SP Bairro: Vila Itlia,https://thumbs4.properati.com/5/XPnfndqmnEKY04smTHRwdeanGd8=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2535/atPPaTZcVegFbIYjH45d.jpg\n8f0adde258e0b9ad5897ba55288b52005ca749a8,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,3200,BRL,3035.52,983.07,,100,9.8307,32,,,,http://www.properati.com.br/ifxp_alugar_comercial_republica,\"\tLoja/Galpão com mezanino, pé direito duplo, localizada na Av. Amaral Guegel, proximo da Consolação, 2 banheiro e 2 vagas demarcadas. Referíªncia: CO169\",\"Comercio no(a) República , São Paulo - SP\",https://thumbs4.properati.com/6/XJyKobKfgKlfwiO0SB2Tt2i0Y9w=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/169/50b1ac29-6a0b-4488-aaa4-07bc131dd969.jpg\n480229dcb811d916f90a02ffd9c5b62e8a72ccbe,2014-10-15,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8168432,-49.3930989\",-20.8168432,-49.3930989,17000,BRL,13441.34,4353.05,,,,,,,,http://www.properati.com.br/re16_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: CO95289Tipo: Predio ComercialCidade: So Jos do Rio Preto - SPBairro: Vila dos BancariosM2 rea Construida: 800, Garagem Descoberta: 20, Detalhes: Predio Comercial Com 10m Salas de 80 M Cada, Fica Em Um Pavimento Com Elevador, 20 Vagas Para Estacionar .\",Loja,https://thumbs4.properati.com/4/Z-A_sLSPQOFzDbPb8MkkcY9IwMU=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2239/bsfsEYepcv9Cu4EHDvjU.jpg\n\n", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "No pagination, no footer", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "country_name": true, - "created_on": true, - "expenses": true, - "floor": true, - "geonames_id": true, - "id": true, - "image_thumbnail": true, - "lat": true, - "lat_lon": true, - "lon": true, - "operation": true, - "place_with_parent_names": true, - "price_aprox_local_currency": true, - "price_aprox_usd": true, - "state_name": true, - "surface_total_in_m2": true - }, - "indexByName": { - "country_name": 13, - "created_on": 9, - "currency": 19, - "description": 5, - "expenses": 24, - "floor": 7, - "geonames_id": 15, - "id": 0, - "image_thumbnail": 26, - "lat": 17, - "lat_lon": 16, - "lon": 18, - "operation": 8, - "place_name": 4, - "place_with_parent_names": 12, - "price": 11, - "price_aprox_local_currency": 20, - "price_aprox_usd": 21, - "price_per_m2": 23, - "price_usd_per_m2": 22, - "properati_url": 25, - "property_type": 2, - "rooms": 6, - "state_name": 14, - "surface_covered_in_m2": 3, - "surface_total_in_m2": 10, - "title": 1 - }, - "renameByName": { - "description": "Description", - "place_name": "City", - "price": "Price", - "properati_url": "URL", - "property_type": "Type", - "rooms": "Rooms", - "surface_covered_in_m2": "Surface", - "title": "Property name" - } - } - } - ], - "type": "table" + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "footer": { + "enablePagination": false, + "fields": "", + "reducer": ["sum"], + "show": false }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Surface" + } + ] + }, + "pluginVersion": "9.0.0-pre", + "targets": [ { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [ - { - "options": { - "rent": { - "color": "yellow", - "index": 0 - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "property_type" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, - { - "id": "mappings", - "value": [ - { - "options": { - "store": { - "color": "blue", - "index": 0 - } - }, - "type": "value" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "title" - }, - "properties": [ - { - "id": "custom.width", - "value": 205 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Number of rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Description" - }, - "properties": [ - { - "id": "custom.inspect", - "value": true - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "URL" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "Show details", - "url": "${__value.raw}" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Surface" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background-solid" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "dark-red", - "value": null - }, - { - "color": "orange", - "value": 100 - }, - { - "color": "yellow", - "value": 200 - }, - { - "color": "green", - "value": 300 - }, - { - "color": "#EAB839", - "value": 500 - }, - { - "color": "#6ED0E0", - "value": 1000 - }, - { - "color": "#EF843C", - "value": 2000 - } - ] - } - }, - { - "id": "unit", - "value": "areaM2" - }, - { - "id": "custom.width", - "value": 93 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Type" - }, - "properties": [ - { - "id": "custom.width", - "value": 94 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "City" - }, - "properties": [ - { - "id": "custom.width", - "value": 120 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 77 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Price" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 0 - }, - "id": 6, - "options": { - "footer": { - "enablePagination": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": true - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Surface" - } - ] - }, - "pluginVersion": "9.0.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A" - } - ], - "title": "No pagination, footer", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "country_name": true, - "created_on": true, - "expenses": true, - "floor": true, - "geonames_id": true, - "id": true, - "image_thumbnail": true, - "lat": true, - "lat_lon": true, - "lon": true, - "operation": true, - "place_with_parent_names": true, - "price_aprox_local_currency": true, - "price_aprox_usd": true, - "state_name": true, - "surface_total_in_m2": true - }, - "indexByName": { - "country_name": 13, - "created_on": 9, - "currency": 19, - "description": 5, - "expenses": 24, - "floor": 7, - "geonames_id": 15, - "id": 0, - "image_thumbnail": 26, - "lat": 17, - "lat_lon": 16, - "lon": 18, - "operation": 8, - "place_name": 4, - "place_with_parent_names": 12, - "price": 11, - "price_aprox_local_currency": 20, - "price_aprox_usd": 21, - "price_per_m2": 23, - "price_usd_per_m2": 22, - "properati_url": 25, - "property_type": 2, - "rooms": 6, - "state_name": 14, - "surface_covered_in_m2": 3, - "surface_total_in_m2": 10, - "title": 1 - }, - "renameByName": { - "description": "Description", - "place_name": "City", - "price": "Price", - "properati_url": "URL", - "property_type": "Type", - "rooms": "Rooms", - "surface_covered_in_m2": "Surface", - "title": "Property name" - } - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [ - { - "options": { - "rent": { - "color": "yellow", - "index": 0 - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "property_type" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, - { - "id": "mappings", - "value": [ - { - "options": { - "store": { - "color": "blue", - "index": 0 - } - }, - "type": "value" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "title" - }, - "properties": [ - { - "id": "custom.width", - "value": 205 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Number of rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Description" - }, - "properties": [ - { - "id": "custom.inspect", - "value": true - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "URL" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "Show details", - "url": "${__value.raw}" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Surface" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background-solid" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "dark-red", - "value": null - }, - { - "color": "orange", - "value": 100 - }, - { - "color": "yellow", - "value": 200 - }, - { - "color": "green", - "value": 300 - }, - { - "color": "#EAB839", - "value": 500 - }, - { - "color": "#6ED0E0", - "value": 1000 - }, - { - "color": "#EF843C", - "value": 2000 - } - ] - } - }, - { - "id": "unit", - "value": "areaM2" - }, - { - "id": "custom.width", - "value": 93 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Type" - }, - "properties": [ - { - "id": "custom.width", - "value": 94 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "City" - }, - "properties": [ - { - "id": "custom.width", - "value": 120 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 77 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Price" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 0 - }, - "id": 9, - "options": { - "footer": { - "enablePagination": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": false, - "sortBy": [ - { - "desc": true, - "displayName": "Surface" - } - ] - }, - "pluginVersion": "9.0.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A" - } - ], - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "country_name": true, - "created_on": true, - "expenses": true, - "floor": true, - "geonames_id": true, - "id": true, - "image_thumbnail": true, - "lat": true, - "lat_lon": true, - "lon": true, - "operation": true, - "place_with_parent_names": true, - "price_aprox_local_currency": true, - "price_aprox_usd": true, - "state_name": true, - "surface_total_in_m2": true - }, - "indexByName": { - "country_name": 13, - "created_on": 9, - "currency": 19, - "description": 5, - "expenses": 24, - "floor": 7, - "geonames_id": 15, - "id": 0, - "image_thumbnail": 26, - "lat": 17, - "lat_lon": 16, - "lon": 18, - "operation": 8, - "place_name": 4, - "place_with_parent_names": 12, - "price": 11, - "price_aprox_local_currency": 20, - "price_aprox_usd": 21, - "price_per_m2": 23, - "price_usd_per_m2": 22, - "properati_url": 25, - "property_type": 2, - "rooms": 6, - "state_name": 14, - "surface_covered_in_m2": 3, - "surface_total_in_m2": 10, - "title": 1 - }, - "renameByName": { - "description": "Description", - "place_name": "City", - "price": "Price", - "properati_url": "URL", - "property_type": "Type", - "rooms": "Rooms", - "surface_covered_in_m2": "Surface", - "title": "Property name" - } - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [ - { - "options": { - "rent": { - "color": "yellow", - "index": 0 - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "property_type" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, - { - "id": "mappings", - "value": [ - { - "options": { - "store": { - "color": "blue", - "index": 0 - } - }, - "type": "value" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "title" - }, - "properties": [ - { - "id": "custom.width", - "value": 205 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Number of rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Description" - }, - "properties": [ - { - "id": "custom.inspect", - "value": true - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "URL" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "Show details", - "url": "${__value.raw}" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Surface" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background-solid" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "dark-red", - "value": null - }, - { - "color": "orange", - "value": 100 - }, - { - "color": "yellow", - "value": 200 - }, - { - "color": "green", - "value": 300 - }, - { - "color": "#EAB839", - "value": 500 - }, - { - "color": "#6ED0E0", - "value": 1000 - }, - { - "color": "#EF843C", - "value": 2000 - } - ] - } - }, - { - "id": "unit", - "value": "areaM2" - }, - { - "id": "custom.width", - "value": 93 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Type" - }, - "properties": [ - { - "id": "custom.width", - "value": 94 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "City" - }, - "properties": [ - { - "id": "custom.width", - "value": 120 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 77 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Price" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 8 - }, - "id": 7, - "options": { - "footer": { - "enablePagination": true, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Surface" - } - ] - }, - "pluginVersion": "9.0.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A" - } - ], - "title": "Pagination, no footer", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "country_name": true, - "created_on": true, - "expenses": true, - "floor": true, - "geonames_id": true, - "id": true, - "image_thumbnail": true, - "lat": true, - "lat_lon": true, - "lon": true, - "operation": true, - "place_with_parent_names": true, - "price_aprox_local_currency": true, - "price_aprox_usd": true, - "state_name": true, - "surface_total_in_m2": true - }, - "indexByName": { - "country_name": 13, - "created_on": 9, - "currency": 19, - "description": 5, - "expenses": 24, - "floor": 7, - "geonames_id": 15, - "id": 0, - "image_thumbnail": 26, - "lat": 17, - "lat_lon": 16, - "lon": 18, - "operation": 8, - "place_name": 4, - "place_with_parent_names": 12, - "price": 11, - "price_aprox_local_currency": 20, - "price_aprox_usd": 21, - "price_per_m2": 23, - "price_usd_per_m2": 22, - "properati_url": 25, - "property_type": 2, - "rooms": 6, - "state_name": 14, - "surface_covered_in_m2": 3, - "surface_total_in_m2": 10, - "title": 1 - }, - "renameByName": { - "description": "Description", - "place_name": "City", - "price": "Price", - "properati_url": "URL", - "property_type": "Type", - "rooms": "Rooms", - "surface_covered_in_m2": "Surface", - "title": "Property name" - } - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [ - { - "options": { - "rent": { - "color": "yellow", - "index": 0 - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "property_type" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, - { - "id": "mappings", - "value": [ - { - "options": { - "store": { - "color": "blue", - "index": 0 - } - }, - "type": "value" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "title" - }, - "properties": [ - { - "id": "custom.width", - "value": 205 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Number of rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Description" - }, - "properties": [ - { - "id": "custom.inspect", - "value": true - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "URL" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "Show details", - "url": "${__value.raw}" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Surface" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background-solid" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "dark-red", - "value": null - }, - { - "color": "orange", - "value": 100 - }, - { - "color": "yellow", - "value": 200 - }, - { - "color": "green", - "value": 300 - }, - { - "color": "#EAB839", - "value": 500 - }, - { - "color": "#6ED0E0", - "value": 1000 - }, - { - "color": "#EF843C", - "value": 2000 - } - ] - } - }, - { - "id": "unit", - "value": "areaM2" - }, - { - "id": "custom.width", - "value": 93 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Type" - }, - "properties": [ - { - "id": "custom.width", - "value": 94 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "City" - }, - "properties": [ - { - "id": "custom.width", - "value": 120 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 77 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Price" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 8 - }, - "id": 8, - "options": { - "footer": { - "enablePagination": true, - "fields": "", - "reducer": [ - "sum" - ], - "show": true - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Surface" - } - ] - }, - "pluginVersion": "9.0.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A" - } - ], - "title": "Pagination and footer", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "country_name": true, - "created_on": true, - "expenses": true, - "floor": true, - "geonames_id": true, - "id": true, - "image_thumbnail": true, - "lat": true, - "lat_lon": true, - "lon": true, - "operation": true, - "place_with_parent_names": true, - "price_aprox_local_currency": true, - "price_aprox_usd": true, - "state_name": true, - "surface_total_in_m2": true - }, - "indexByName": { - "country_name": 13, - "created_on": 9, - "currency": 19, - "description": 5, - "expenses": 24, - "floor": 7, - "geonames_id": 15, - "id": 0, - "image_thumbnail": 26, - "lat": 17, - "lat_lon": 16, - "lon": 18, - "operation": 8, - "place_name": 4, - "place_with_parent_names": 12, - "price": 11, - "price_aprox_local_currency": 20, - "price_aprox_usd": 21, - "price_per_m2": 23, - "price_usd_per_m2": 22, - "properati_url": 25, - "property_type": 2, - "rooms": 6, - "state_name": 14, - "surface_covered_in_m2": 3, - "surface_total_in_m2": 10, - "title": 1 - }, - "renameByName": { - "description": "Description", - "place_name": "City", - "price": "Price", - "properati_url": "URL", - "property_type": "Type", - "rooms": "Rooms", - "surface_covered_in_m2": "Surface", - "title": "Property name" - } - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [ - { - "options": { - "rent": { - "color": "yellow", - "index": 0 - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "property_type" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, - { - "id": "mappings", - "value": [ - { - "options": { - "store": { - "color": "blue", - "index": 0 - } - }, - "type": "value" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "title" - }, - "properties": [ - { - "id": "custom.width", - "value": 205 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Number of rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Description" - }, - "properties": [ - { - "id": "custom.inspect", - "value": true - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "URL" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "Show details", - "url": "${__value.raw}" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Surface" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background-solid" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "dark-red", - "value": null - }, - { - "color": "orange", - "value": 100 - }, - { - "color": "yellow", - "value": 200 - }, - { - "color": "green", - "value": 300 - }, - { - "color": "#EAB839", - "value": 500 - }, - { - "color": "#6ED0E0", - "value": 1000 - }, - { - "color": "#EF843C", - "value": 2000 - } - ] - } - }, - { - "id": "unit", - "value": "areaM2" - }, - { - "id": "custom.width", - "value": 93 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Type" - }, - "properties": [ - { - "id": "custom.width", - "value": 94 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "City" - }, - "properties": [ - { - "id": "custom.width", - "value": 120 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 77 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Price" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 16 - }, - "id": 10, - "options": { - "footer": { - "enablePagination": true, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": false, - "sortBy": [ - { - "desc": true, - "displayName": "Surface" - } - ] - }, - "pluginVersion": "9.0.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A" - } - ], - "title": "Pagination, no footer, no header", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "country_name": true, - "created_on": true, - "expenses": true, - "floor": true, - "geonames_id": true, - "id": true, - "image_thumbnail": true, - "lat": true, - "lat_lon": true, - "lon": true, - "operation": true, - "place_with_parent_names": true, - "price_aprox_local_currency": true, - "price_aprox_usd": true, - "state_name": true, - "surface_total_in_m2": true - }, - "indexByName": { - "country_name": 13, - "created_on": 9, - "currency": 19, - "description": 5, - "expenses": 24, - "floor": 7, - "geonames_id": 15, - "id": 0, - "image_thumbnail": 26, - "lat": 17, - "lat_lon": 16, - "lon": 18, - "operation": 8, - "place_name": 4, - "place_with_parent_names": 12, - "price": 11, - "price_aprox_local_currency": 20, - "price_aprox_usd": 21, - "price_per_m2": 23, - "price_usd_per_m2": 22, - "properati_url": 25, - "property_type": 2, - "rooms": 6, - "state_name": 14, - "surface_covered_in_m2": 3, - "surface_total_in_m2": 10, - "title": 1 - }, - "renameByName": { - "description": "Description", - "place_name": "City", - "price": "Price", - "properati_url": "URL", - "property_type": "Type", - "rooms": "Rooms", - "surface_covered_in_m2": "Surface", - "title": "Property name" - } - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [ - { - "options": { - "rent": { - "color": "yellow", - "index": 0 - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "property_type" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, - { - "id": "mappings", - "value": [ - { - "options": { - "store": { - "color": "blue", - "index": 0 - } - }, - "type": "value" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "title" - }, - "properties": [ - { - "id": "custom.width", - "value": 205 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Number of rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Description" - }, - "properties": [ - { - "id": "custom.inspect", - "value": true - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "URL" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "Show details", - "url": "${__value.raw}" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Surface" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background-solid" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "dark-red", - "value": null - }, - { - "color": "orange", - "value": 100 - }, - { - "color": "yellow", - "value": 200 - }, - { - "color": "green", - "value": 300 - }, - { - "color": "#EAB839", - "value": 500 - }, - { - "color": "#6ED0E0", - "value": 1000 - }, - { - "color": "#EF843C", - "value": 2000 - } - ] - } - }, - { - "id": "unit", - "value": "areaM2" - }, - { - "id": "custom.width", - "value": 93 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Type" - }, - "properties": [ - { - "id": "custom.width", - "value": 94 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "City" - }, - "properties": [ - { - "id": "custom.width", - "value": 120 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 77 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Price" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 16 - }, - "id": 11, - "options": { - "footer": { - "enablePagination": true, - "fields": "", - "reducer": [ - "sum" - ], - "show": true - }, - "showHeader": false, - "sortBy": [ - { - "desc": true, - "displayName": "Surface" - } - ] - }, - "pluginVersion": "9.0.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A" - } - ], - "title": "Pagination, footer, no header", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "country_name": true, - "created_on": true, - "expenses": true, - "floor": true, - "geonames_id": true, - "id": true, - "image_thumbnail": true, - "lat": true, - "lat_lon": true, - "lon": true, - "operation": true, - "place_with_parent_names": true, - "price_aprox_local_currency": true, - "price_aprox_usd": true, - "state_name": true, - "surface_total_in_m2": true - }, - "indexByName": { - "country_name": 13, - "created_on": 9, - "currency": 19, - "description": 5, - "expenses": 24, - "floor": 7, - "geonames_id": 15, - "id": 0, - "image_thumbnail": 26, - "lat": 17, - "lat_lon": 16, - "lon": 18, - "operation": 8, - "place_name": 4, - "place_with_parent_names": 12, - "price": 11, - "price_aprox_local_currency": 20, - "price_aprox_usd": 21, - "price_per_m2": 23, - "price_usd_per_m2": 22, - "properati_url": 25, - "property_type": 2, - "rooms": 6, - "state_name": 14, - "surface_covered_in_m2": 3, - "surface_total_in_m2": 10, - "title": 1 - }, - "renameByName": { - "description": "Description", - "place_name": "City", - "price": "Price", - "properati_url": "URL", - "property_type": "Type", - "rooms": "Rooms", - "surface_covered_in_m2": "Surface", - "title": "Property name" - } - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [ - { - "options": { - "rent": { - "color": "yellow", - "index": 0 - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "property_type" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, - { - "id": "mappings", - "value": [ - { - "options": { - "store": { - "color": "blue", - "index": 0 - } - }, - "type": "value" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "title" - }, - "properties": [ - { - "id": "custom.width", - "value": 205 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Number of rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Description" - }, - "properties": [ - { - "id": "custom.inspect", - "value": true - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "URL" - }, - "properties": [ - { - "id": "links", - "value": [ - { - "targetBlank": true, - "title": "Show details", - "url": "${__value.raw}" - } - ] - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Surface" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background-solid" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "dark-red", - "value": null - }, - { - "color": "orange", - "value": 100 - }, - { - "color": "yellow", - "value": 200 - }, - { - "color": "green", - "value": 300 - }, - { - "color": "#EAB839", - "value": 500 - }, - { - "color": "#6ED0E0", - "value": 1000 - }, - { - "color": "#EF843C", - "value": 2000 - } - ] - } - }, - { - "id": "unit", - "value": "areaM2" - }, - { - "id": "custom.width", - "value": 93 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Type" - }, - "properties": [ - { - "id": "custom.width", - "value": 94 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "City" - }, - "properties": [ - { - "id": "custom.width", - "value": 120 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Rooms" - }, - "properties": [ - { - "id": "custom.width", - "value": 77 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Price" - }, - "properties": [ - { - "id": "unit", - "value": "currencyUSD" - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 16 - }, - "id": 12, - "options": { - "footer": { - "enablePagination": true, - "fields": "", - "reducer": [ - "sum" - ], - "show": true - }, - "showHeader": false, - "sortBy": [ - { - "desc": true, - "displayName": "Surface" - } - ] - }, - "pluginVersion": "9.0.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A" - } - ], - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "country_name": true, - "created_on": true, - "expenses": true, - "floor": true, - "geonames_id": true, - "id": true, - "image_thumbnail": true, - "lat": true, - "lat_lon": true, - "lon": true, - "operation": true, - "place_with_parent_names": true, - "price_aprox_local_currency": true, - "price_aprox_usd": true, - "state_name": true, - "surface_total_in_m2": true - }, - "indexByName": { - "country_name": 13, - "created_on": 9, - "currency": 19, - "description": 5, - "expenses": 24, - "floor": 7, - "geonames_id": 15, - "id": 0, - "image_thumbnail": 26, - "lat": 17, - "lat_lon": 16, - "lon": 18, - "operation": 8, - "place_name": 4, - "place_with_parent_names": 12, - "price": 11, - "price_aprox_local_currency": 20, - "price_aprox_usd": 21, - "price_per_m2": 23, - "price_usd_per_m2": 22, - "properati_url": 25, - "property_type": 2, - "rooms": 6, - "state_name": 14, - "surface_covered_in_m2": 3, - "surface_total_in_m2": 10, - "title": 1 - }, - "renameByName": { - "description": "Description", - "place_name": "City", - "price": "Price", - "properati_url": "URL", - "property_type": "Type", - "rooms": "Rooms", - "surface_covered_in_m2": "Surface", - "title": "Property name" - } - } - } - ], - "type": "table" + "csvContent": "\"id\",\"created_on\",\"operation\",\"property_type\",\"place_name\",\"place_with_parent_names\",\"country_name\",\"state_name\",\"geonames_id\",\"lat_lon\",\"lat\",\"lon\",\"price\",\"currency\",\"price_aprox_local_currency\",\"price_aprox_usd\",\"surface_total_in_m2\",\"surface_covered_in_m2\",\"price_usd_per_m2\",\"price_per_m2\",\"floor\",\"rooms\",\"expenses\",\"properati_url\",\"description\",\"title\",\"image_thumbnail\"\nf73c373e0588bf568164a057dd94203ac87d47b1,2014-08-07,rent,store,Catu,|Brasil|Bahia|Catu|,Brasil,Bahia,,,,,0,,0,0,,,,,,,,http://www.properati.com.br/mfye_alugar_outros_catu,\"Otimo Imovel com o melhor valor da regiao, confira as fotos - \",Exclusividade! - Loja Em Catu,https://thumbs4.properati.com/3/jA8isZw8Xju7z3-V2I-ED8x5D2o=/trim/198x0/smart/filters:strip_icc()/galeriadefotos.net.br/backup/upload/15989/1598966287bc7/zd533ba5e829b0543093a45e1d8398bd7.jpg\nd6d377927ab49671acdd38aa6f661a460601a88b,2015-01-20,rent,apartment,Pernambuco,|Brasil|Pernambuco|,Brasil,Pernambuco,,\"-8.126271,-34.903793\",-8.126271,-34.903793,1200,BRL,1184.32,383.55,,63,6.088095238095239,19.047619047619047,1,2,,http://www.properati.com.br/w71k_alugar_apartamentos_pernambuco,\"CONTATOS: Claro: 81./ Tim: 81./ Oi: 81./ Vivo: 81.Apartamento de 2 quartos mais Dependência completa de empregada, 1.º andar de edifício localizado na Rua Dr. Gaspar Regueira da Costa, 99, Boa Viagem.Este apartamento é constituído por: 1 Sala, 2 Quartos, 2 Banheiros, Cozinha, Área de serviço, Dependência completa de empregada e 1 lugar de estacionamento.O Valor do aluguer já inclui taxas.Agende já a sua visita.Nota: O Edifício irá ser pintado exteriormente, em breve.ISI-120-T2 #ref:ISI-120-T2 - ISI-120-T2 - idalécio Soares\",\"Apartamento de 2 quartos, DCE, 1.º Andar, 63 m2, Boa Viagem - Recife\",https://thumbs4.properati.com/0/B9BCwP1HK7NvZIYINGkFNnNfOZ4=/trim/198x0/smart/filters:strip_icc()/feedmedia.egorealestate.com/Zfeed/S5/C4123/P2270979/Tphoto/ID03a72200-0000-0500-0000-00000141a7a5.JPG\nc6826a9508436920fd59b46a202354f3e4823d22,2014-10-29,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.1546253,-45.7906242\",-23.1546253,-45.7906242,0,BRL,0,0,,3800,,,,,,http://www.properati.com.br/s41f_alugar_comercial_cacapava,\"Condomínio com 22 Módulos de Galpões; 3.800m2 a 12.600m2; 12m pé-direito médio; Piso 6 TON/m2; Ã�rea total de Terreno : 324.000 m2; Ã�rea Total construída: 133.200 m2; 293 vagas para automóveis; 103 vagas para caminhões; Refeitório para 256 pessoas por turno;Benefícios Fiscais no município de Caçapava conforme Lei Lei 5055/211; Isenção de Taxas;Isenção de IPTU; Redução de ISS; Reversão de ICMS.Valores locação = R$ 15,00 o m2Tx Cond. = R$ 1,50 o m2Valores poderão ser alterados sem prévio aviso.A Heron Imóveis oferece este(a) Comercial em Caçapava, no bairro Caçapava. Gostou desse(a) Comercial em Caçapava? Então veja mais informações! Acesse o nosso site clicando no botão Contate o anunciante ou ligue - ou ainda entre em contato conosco pelo email contato@ Obrigado!\",\"Comercial em Caçapava, no bairro Caçapava\",https://thumbs4.properati.com/1/J2n8nXVlvduy6EJjyLwPneEoc28=/trim/198x0/smart/filters:strip_icc()/www.heronimoveis.com.br/fotos/F00/35/23500-DSC06177.JPG\nba957ad3cb2d12d55d1f0466eeffe788a35a6f4f,2014-08-04,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7780086,-49.3450562\",-20.7780086,-49.3450562,950,BRL,751.1,243.25,,,,,,1,,http://www.properati.com.br/lxp9_alugar_casas_sao-jose-do-rio-preto,\"Ref.: CA95876 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Garden Village II..:Casa Condomnio Garden Village II, Casa Condominio, Dormitrios: 03, Tipo Apto.: 01, Wc. Social: 01, Sala de Visita: 01, Copa: 01, Cozinha: 01, Cozinha Planejada, Despensa, rea de Servio, Ar Condicionado, Alarme, Acabamento Em Gesso, Sanca, Campainha, Cerca Eletrica, Forro de Laje, Piso Dormitrios: Frio, Piso Salas: Frio, M2/ Terreno: 145, M2 rea Construida: 70, Garagem Descoberta: 01, Salo de Festa, Detalhes: R$ 950,00 + Iptu + Condomnio\", Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Garden Village II,https://thumbs4.properati.com/9/xcrfHjSnXdhGcOK1m1wg1jHJlsw=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/803/8860a8e8-6d62-49e6-a992-54ab8f360f35.jpg\n0999b33908c71af3b8be282ab35ab61b38a46353,2014-07-16,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,4300,BRL,4078.98,1321,,319,4.141065830721003,13.47962382445141,,4,,http://www.properati.com.br/ifuj_alugar_apartamentos_vila-olimpia,\"Apartamento na Vila Olí­mpia, com 4 quartos, sendo 2 suí­tes,Ampla sala com terraí§o, piso de madeira corrida, 1 dos quartos pode ser revertido para sala de tv ou escritório.Quartos com carpete de madeira, as suí­tes com armí¡rios embutidos, uma delas com ar condicionado.Armí¡rio corredor.Cozinha com armí¡rio, Piso de granito, na cozinha e lavanderia.  Referíªncia: AP34\",\"Apartamento no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/8/nxrbzTDipvKnqdx1wDABEyIbSes=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/34/c789b808-bf30-460d-9376-16299ce5abbb.jpg\n011d5618639ce229b012022a32b22eff9abd213e,2014-11-19,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.9648026,-46.3855723\",-23.9648026,-46.3855723,1300,BRL,1323.12,428.5,,60,7.141666666666667,21.666666666666668,4,1,,http://www.properati.com.br/tl4s_alugar_apartamentos_sao-paulo,\"PACOTE R$ 1.300,00 OTIMO APARTAMENTO MOBILIADO COM TERRAÇO PROXIMO SHOPPING , PRAIA E COMERCIOS ACEITA FIADOR / SEG. FIANÇA A 3 Milenio oferece este(a) Apartamento em Sao Vicente, no bairro Gonzaguinha - 1 dormitórios. Gostou desse(a) Apartamento em Sao Vicente? Então veja mais informações! Acesse o nosso site clicando no botão Contate o anunciante ou ligue - ou ainda entre em contato conosco pelo email vendas@ Obrigado!\",\"Apartamento em Sao Vicente, no bairro Gonzaguinha - 1 dormitórios\",https://thumbs4.properati.com/4/x8BqTbd304ntTBY5pTf5Yi_nNMw=/trim/198x0/smart/filters:strip_icc()/www.imobiliariasdesantos.com.br/fotos/F00/74/757400-FOTOS%20HELANE%20001.jpg\n6f274a2d23ffa89cb0301f3277585beda7723ce8,2014-09-01,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8343086,-49.3805559\",-20.8343086,-49.3805559,5000,BRL,3953.34,1280.31,,,,,,,,http://www.properati.com.br/o23s_alugar_comercial_sao-jose-do-rio-preto_rua-nuno-alvares-pereira,\"Ref.: SA95668Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Pq. EstorilM2 rea Construida: 170, Detalhes: Salo de 170 M, Com Mezanino. J Com Acessibilidade. Tem Uma Linda Fachada e Estacionamento Para Clientes.\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Pq. Estoril,https://thumbs4.properati.com/8/7VqZVGV6Hl3paOrhYXv_ksowyEw=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1875/TG5yXGj9EJPaa5o0dWgL.jpg\ndb6f890847bcacc6ec3e78a0e6613132174e4c70,2014-12-05,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178411,-49.387605\",-20.8178411,-49.387605,10000,BRL,7906.68,2560.62,,,,,,1,,http://www.properati.com.br/ue07_alugar_casas_sao-jose-do-rio-preto_rua-cila,\"Ref.: CO95026Tipo: Casa Comercial, Predio ComercialCidade: So Jos do Rio Preto - SPBairro: RedentoraSobrado, Dormitrios: 4, Tipo Apto.: 4, C/ A/e: 4, A/e C/ Interior: 4, Wc. Social: 1, Copa/cozinha: 1, Cozinha C/ A/e: 1, Despensa, Salas : 1, Sala P/ Ambientes : 4, M2 rea Construida: 330, Entrada Lateral: 1, Piso Dormitrios: Frio\",\"Ref.: CO95026 Tipo: Casa Comercial, Predio Comercial Cidade: So Jos do Rio Preto - SP Bairro: Redentora\",https://thumbs4.properati.com/2/DNREjVLgpGPzTlv8aIvhpd7KZkI=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2461/02ea33d3-3ebd-4139-a380-b60eb84c87d1.jpg\nf7d3243419c85cf439189481819f13cb22ab0498,2014-10-01,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8126181,-49.3404534\",-20.8126181,-49.3404534,3800,BRL,3004.52,973.03,,,,,,,,http://www.properati.com.br/qz8t_alugar_casas_sao-jose-do-rio-preto_avenida-miguel-damha,\"Ref.: CA95902Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Damha III..: Casa Condomnio Damha III, Casa Condominio, Dormitrios: 03, Suite: 01, Closet , Tipo Apto.: 02, C/ A/e: 02, Home, Copa/cozinha: 01, Cozinha Planejada, Piscina, Varanda, rea de Servio, Wc. de Empregada/servio, Forro de Laje, M2/ Terreno: 450, M2 rea Construida: 240, rea de Lazer, Garagem Descoberta: 02, Garagem Coberta: 02, Churrasqueira, Valor Condominio R$-: 420,00\",Ref.: CA95902 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Damha III,https://thumbs4.properati.com/8/cqu5q3tBJOddQ526fWf2puVwINI=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2060/6064cf7e-f8ed-44f3-8a80-b6576de27d62.jpg\ncbfc4c495b3578c995363825a85a821217fab4ec,2014-10-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,14000,BRL,11069.36,3584.87,,,,,,,,http://www.properati.com.br/ri3p_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95918Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Mini Dist. Industrial Adail Vetorasso..: Salo Comercial No Mini Distrito Industrial Adail Vetorasso, Salo Comercial, Wcs.: 02, Cozinha: 01, Escritrio, M2/ Terreno: 2.100, M2 rea Construida: 1.350, Detalhes: Cobertura Metlica.p Direito Com 7 Metros.corredor Lateral.\",Ref.: SA95918 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Mini Dist. Industrial Adail Vetorasso,https://thumbs4.properati.com/9/INPTa4YGuWfsekPfC8ez-rqd3PI=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2285/Mhd9hMU2ZwU9YXAC9Hzi.jpg\nb4dab15f9d4411d0847d1871e0a62e107b492fdc,2014-08-02,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.8773135,-46.7592613\",-23.8773135,-46.7592613,28000,BRL,22138.72,7169.74,,,,,,,,http://www.properati.com.br/lud3_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95869Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Eng. Schimidt..: Salo Comercial Em Engenheiro Schimidt, Salo Comercial, Obs: Salo Ideal Para Transportadora Com Frente Para 03 Marginal, Esquina Com Rua Projetada 01 e Rodovia W. Luiz, M2/ Terreno: 5.500, M2 rea Construida: 2.200\",Ref.: SA95869 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Eng. Schimidt,https://thumbs4.properati.com/3/oJm3M_UtBn2PVRsZ2O4n48IvhuA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/780/60d090bc-4a05-4929-88ae-aca5b9873a76.jpg\nd3769eb1b41c780c83f2d176adae8ad9a81b7ba3,2014-10-08,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.818728,-49.4212608\",-20.818728,-49.4212608,16000,BRL,12650.68,4096.99,,,,,,,,http://www.properati.com.br/r6d9_alugar_comercial_sao-jose-do-rio-preto_avenida-joao-batista-vetorasso,\"Ref.: SA95810Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Waldemar VerdiM2/ Terreno: 5.000, M2 rea Construida: 1.400, Detalhes: Com Recepo e 8 Salas. P Direito Com 7 M.\",Salo,https://thumbs4.properati.com/6/GFkI3LbwZQAhB8USv5fTltHxz0E=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2179/QEWBOD1T8GCOjBi0H6WI.jpg\nf51aebdb554e9b5dfa16c3538d3376040f5f2b5c,2014-08-20,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.1423284,-51.3750141\",-22.1423284,-51.3750141,16000,BRL,12650.68,4096.99,,,,,,,,http://www.properati.com.br/np97_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95723Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Moyss Miguel HaddadM2 rea Construida: 322, Obs: Salo Ideal Para Loja, 217m Terreo e 105m Mezanino. Estacionamento Na Frente.imvel Novo.\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Moyss Miguel Haddad,https://thumbs4.properati.com/2/viy2bV22HhxBkY_449PiH9sLQPw=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1548/9242514f-75f0-4bdc-a5b1-68a958cbda17.jpg\n7266f270625a52c84adaf69ac08a53b397617247,2014-09-01,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,6000,BRL,4744,1536.37,,,,,,,,http://www.properati.com.br/o20x_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95742Tipo: Salo IndustrialCidade: So Jos do Rio Preto - SPBairro: Quinta das PaineirasWcs.: 02, Cozinha: 01, M2/ Terreno: 720, M2 rea Construida: 458,90, Obs: Salo Industrial Grande Com 458m, Com Boa Acessibilidade e tima Localizao, 02 Quadras da Avenida Potirendaba, Fcil Acesso e Entrada Para Caminhes.\",Tipo: Salo Industrial Cidade: So Jos do Rio Preto - SP Bairro: Quinta das Paineiras,https://thumbs4.properati.com/3/0rnMsn1G6rWTjCQ9lnrLn6WR7JA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1771/KET9NdQ0WNrtQlhGEVEq.jpg\nc1e10a8afe111ba5caa5034df1ecb56b25b772f9,2014-08-19,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.1423284,-51.3750141\",-22.1423284,-51.3750141,12000,BRL,9488,3072.74,,,,,,,,http://www.properati.com.br/muvz_alugar_casas_sao-jose-do-rio-preto,\"Ref.: CA95766Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Moyss Miguel HaddadWc. Social: 04, M2/ Terreno: 980, M2 rea Construida: 500, Obs: Entrada Lateral Com Acesso Para Caminho, Com 04 Wcs. Sendo 02 Wc P/ Deficiente.\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Moyss Miguel Haddad,https://thumbs4.properati.com/3/GvRImi73Q9koPTqVulTG5pg1J2s=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1519/T181YBWZd62P9tMfgs1F.jpg\nd156f7cc95141ef1fca4de81d6dc65b143c9988f,2014-08-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.1423284,-51.3750141\",-22.1423284,-51.3750141,12000,BRL,9488,3072.74,,,,,,,,http://www.properati.com.br/muwd_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95749Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Moyss Miguel HaddadM2 rea Construida: 280, Obs: Salo Ideal Para Loja, 217mterreo + 68m Mezanino.estacionamento Na Frente,\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Moyss Miguel Haddad,https://thumbs4.properati.com/5/A5TB5m6yLugDjIdQVsXy9br70YQ=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1533/eeec7b18-daa6-422b-aac1-82894f366e60.jpg\n90ed612641d0db18967ee9c07edc8b0647c97976,2014-08-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.1423284,-51.3750141\",-22.1423284,-51.3750141,12000,BRL,9488,3072.74,,,,,,,,http://www.properati.com.br/muwc_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95725Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Moyss Miguel HaddadM2 rea Construida: 280, Obs: Salo Ideal Para Loja, 217m Terreo, + 68m Mezanino.estacionamento Na Frente, Imvel Novo\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Moyss Miguel Haddad,https://thumbs4.properati.com/2/8rbyOC1iGXRWRZqh5Z6pcOsdsfQ=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1532/a142f7a0-ff97-4794-84d8-4144253429c3.jpg\nc69e1ca4e7cd3346bc510240893bf2c2c7437e8e,2014-08-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.1423284,-51.3750141\",-22.1423284,-51.3750141,12000,BRL,9488,3072.74,,,,,,,,http://www.properati.com.br/muvh_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95724Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Moyss Miguel HaddadM2/ Terreno: 280, Obs: Salo Ideal Para Loja, 217m Terreo e + 68m Mezanino.Estacionamento Na Frente,imvel Novo.\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Moyss Miguel Haddad,https://thumbs4.properati.com/1/3gyCoSFzrSme_NcQhKWIEnuoeaY=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1501/CeAfrlKKrQIRE9uzNxoa.jpg\n0c5e391bac4d007585efb02466681c760a758423,2014-09-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8379345,-49.3370139\",-20.8379345,-49.3370139,8000,BRL,6325.32,2048.49,,,,,,,,http://www.properati.com.br/q4jv_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95899Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Ch. Estancia Jockey Clube..: Salo Comercial , Salo Comercial, Wcs.: 04, Wcs. C/ A/e, Cozinha: 01, Obs: P Direito 9 Metros, M2 rea Construida: 1.000, Detalhes: Salo Novo, Sendo Os Wcs Piso Porcelanato, Cozinha Porcelanato e Piso Liso, Com Telhado Vulcanizado.\",Ref.: SA95899 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Ch. Estancia Jockey Clube,https://thumbs4.properati.com/8/OM-MkRbrVgdcQa163wlgXjWDHqU=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2007/8541c9f9-4477-448d-a193-d2b00dc5eed4.jpg\n01bdf823f7827d745574bb7a180a39e4db359463,2014-08-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,8000,BRL,6325.32,2048.49,,,,,,,,http://www.properati.com.br/muux_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95894Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Ch. Jockey Clube..: Salo Comercial Na Chcara Jockey Clube, Salo Comercial, M2/ Terreno: 5.000, M2 rea Construida: 1.150, Detalhes: Galpo Com Piso Cimento Polido, Estrutura Metlica, Entrada Lateral Para Caminho.p Direito Alto Com 6,/2 M. \",Ref.: SA95894 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Ch. Jockey Clube,https://thumbs4.properati.com/1/HZjM3Xdq2xWgpQ5gSrCVIASVnJA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1481/Tz9VYOVWXC1ZVU5fUHwL.jpg\n050a20b55332403b962575877b81d609a5988a15,2014-09-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8379345,-49.3370139\",-20.8379345,-49.3370139,8000,BRL,6325.32,2048.49,,,,,,,,http://www.properati.com.br/q4ju_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95900Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Ch. Estancia Jockey Clube..: Salo Comercial , Salo Comercial, Wcs.: 04, Wcs. C/ A/e, Cozinha: 01, Obs: P Direito 9 Metros, M2 rea Construida: 1.000, Detalhes: Salo Novo, Sendo Os Wcs Piso Porcelanato, Cozinha Porcelanato e Piso Liso, Com Telhado Vulcanizado.\",Ref.: SA95900 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Ch. Estancia Jockey Clube,https://thumbs4.properati.com/3/ZL10NlMLKOM5C49dt-MjpOTaaMo=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2006/9fbe5c67-00ba-4e7b-9904-08316f433dd4.jpg\nfeb178373d5eab7df3b6c546a5d1e6a192156c7f,2014-08-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8457948,-49.353464\",-20.8457948,-49.353464,8000,BRL,6325.32,2048.49,,,,,,,,http://www.properati.com.br/muuv_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95892Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Ch. Jockey Clube..: Salo Comercial Na Chcara Jockey Clube, Salo Comercial, M2/ Terreno: 5.000, M2 rea Construida: 1.150, Detalhes: Galpo Com Piso Cimento Polido, Estrutura Metlica, Entrada Lateral Para Caminho.p Direito Alto Com 6,/2 M.\",Ref.: SA95892 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Ch. Jockey Clube ,https://thumbs4.properati.com/5/xwV26hopilS3ZK6xLE-O3iy4rE4=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1479/vT0mPYs7U2dAsti8LWGQ.jpg\n882a8542b44e551782d3126a1d43d907cdba854b,2014-08-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8442587,-49.3291753\",-20.8442587,-49.3291753,7000,BRL,5534.66,1792.43,,,,,,,,http://www.properati.com.br/mt5y_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95817Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Marginal Eng. SchimidtWc. Social: 02, Cozinha, Mesanino, Escritrio, M2/ Terreno: 2.000, M2 rea Construida: 1.100, Pintura Nova, Piso Dormitrios: Cimentado;, Piso Salas: Polido;, Detalhes: Salo Novo, Com Estrutura Metlica e Banheiro C/ Acessibilidade.\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Marginal Eng. Schimidt,https://thumbs4.properati.com/4/FPT3HYl7BCrZMA5Okj6iNxUgPRA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1432/MaEwnQ1cL6HLcrscPFb8.jpg\n201e0ccc9fc63a78f68391bdd74ac5407e07da9b,2014-08-04,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,1000,BRL,790.66,256.06,,,,,,1,,http://www.properati.com.br/lxpd_alugar_casas_sao-jose-do-rio-preto,\"Ref.: CA95884Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Parque Liberdade III..:Casa Condomnio Parque da Liberdade III, Casa Condominio, Dormitrios: 03, C/ A/e: 02, Wc. Social: 01, Wcs. C/ A/e, Sala de Visita: 01, Cozinha: 01, Cozinha Planejada, Interfone, Acabamento Em Gesso, Sanca, Campainha, Forro de Laje, Obs: Imvel Semi Novo, Com Projeto da Arquiteta Kenia Miranda, o Imvel Tem Papel de Parede, Cortinas Nos Dormitrios e Sala, Luminrias Na Cozinha., M2/ Terreno: 143, Garagem Coberta: 02, Churrasqueira, Detalhes: R$ 1.000,00 + Iptu + Condominio\",Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Parque Liberdade III,https://thumbs4.properati.com/2/v319TrEqOc-5Hy9xmTQXh1KL2UE=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/807/7331be4a-3945-41cd-b761-4322696192f5.jpg\n05cf0728d4ba6016469b6b4a864542a1824dc25c,2014-08-15,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.7688712,-46.7100661\",-23.7688712,-46.7100661,2000,BRL,1581.32,512.12,,,,,,,,http://www.properati.com.br/mqtt_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95463Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Jardim So MarcosWc. Social: 2, Cozinha: 1, Mesanino, Recepo, M2/ Terreno: 406, M2 rea Construida: 110, Pintura Nova, Piso Salas: Piso Frio\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Jardim So Marcos,https://thumbs4.properati.com/9/EMUy3dbQiGwd8LmfHH92qsmCQ7Q=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1375/srbDQgpudCyI2lewxvjS.jpg\nf5942694fe76bfe705275acfe74148c588367f86,2014-09-01,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.7688712,-46.7100661\",-23.7688712,-46.7100661,4000,BRL,3162.64,1024.24,,,,,,8,,http://www.properati.com.br/o215_alugar_casas_sao-jose-do-rio-preto_rua-antonio-dias,\"Ref.: CO95681Tipo: Casa ComercialCidade: So Jos do Rio Preto - SPBairro: Jardim So MarcosWc. Social: 04, Sala(s): 08, M2/ Terreno: 280, Garagem Coberta: 02, Forro de Laje, Piso Salas: Frio, Iptu Valor: 58,00, Detalhes: timo Local Para Clincas.\",Tipo: Casa Comercial Cidade: So Jos do Rio Preto - SP Bairro: Jardim So Marcos,https://thumbs4.properati.com/4/F58YgAYlsu22NFL9RPPH5RURZJ8=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1779/sr0aS0NcXQGZ7HsOtyan.jpg\n1b093694ca05135b213162c0bd499e9adb708309,2014-12-10,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.6302071,-46.5818983\",-23.6302071,-46.5818983,4000,BRL,3162.64,1024.24,,,,,,,,http://www.properati.com.br/ufsq_alugar_comercial_sao-jose-do-rio-preto_avenida-marginal,\"Ref.: SA95942Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Pq. Res. Manor Daud..: Salo Comercial No Parque Residencial Manor Daud, Salo Comercial, Detalhes: Salo Com 340m, Entrada Para Caminho.frente Para Br153\",Ref.: SA95942 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Pq. Res. Manor Daud,https://thumbs4.properati.com/4/4e8bVPqS0g1ezrFKP9fcdzvSn0I=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2493/rJ3aboE1bZnwuqJHy4Lr.jpg\n50bd70c45a9a9b087c404cac6b67c491f64c211e,2014-10-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2500,BRL,1976.65,640.15,,,,,,,,http://www.properati.com.br/ri3l_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95916Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Res. Caetano..: Salo Comercial No Residencial Caetano, Salo Comercial, Wcs.: 02, Cozinha: 01, M2 rea Construida: 350, Detalhes: Cozinha2 Wc Com Acessibilidade;1 Porta Na Frente1 Porta Na Lateral;barraco Novo.cobertura Com Estrutura Metlica. P Direito de 6 Metros.\",\"Ref.: SA95916 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Res. Caetano ..: Salo Comercial No Residencial Caetano, Salo Comercial, Wcs.: 02, Cozinha: 01, M2 rea Construida: 350, Detalhes: Cozinha 2 Wc Com Acessibilidade\",https://thumbs4.properati.com/9/l325GXwN3fD9xS0dglH5hmaB83A=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2281/FjKJBqBJFxhvJ4atJVuO.jpg\n50a4a96d3ec01b7b1032e5eec4a3496b38f35c4f,2014-10-09,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7780086,-49.3450562\",-20.7780086,-49.3450562,2500,BRL,1976.65,640.15,,,,,,,,http://www.properati.com.br/r9j7_alugar_casas_sao-jose-do-rio-preto_avenida-belvedere,\"Ref.: CA95904Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Village Damha Rio Preto I..: Casa Em Condomnio Village Damha Rio Preto I, Casa Condominio, Dormitrios: 03, Tipo Apto.: 01, C/ A/e: 03, Cozinha: 01, Cozinha Planejada, Varanda, rea de Servio, Wc. de Empregada/servio, Garagem Coberta: 02, Churrasqueira\",Ref.: CA95904 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Village Damha Rio Preto I,https://thumbs4.properati.com/1/CVM0xMvGlg_DX1BluR3vWpRkhMU=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2206/7f2a5d99-2465-48fb-859c-a52311ba0c18.jpg\nf5be311dcee4a66dcb26f463f76c49b6084de8ab,2014-11-11,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,1600,BRL,1411.74,457.2,,,,,2,1,,http://www.properati.com.br/t8nu_alugar_apartamentos_tatuape_rua-serra-de-braganca,\"APTO DE 40M/2 COM 01 DORMITRIO, SALA AMPLA COM SACADA, COZINHA PLANEJADA, WC SOCIAL, REA DE SERVIO, 01 VAGA DE GARAGEM LIVRE, LAZER COMPLETO COM PISCINA, PLAYGROUD, SALO DE FESTA, CHURRASQUEIRA, SAUNA, SALA DE FITINESS, SALA DE LEITURA, SALO DE JOGOS, EXCELENTE LOCALIZAO. O APTO ESTA COM FOGO, GELADEIRA, MICROONDAS, SUGGAR, BALCO ESTILO COZINHA AMERICANA, 02 BANQUETAS, 02 MESINHAS DE CANTO, 01 HOME-OFFICER, CAMA BOX COM COLCHO, VENTILADOR DE TETO, ARMRIO NO DORMITRIO.\",TOLEDO CONSULTORIA JURIDICA E IMOBILIARIA,https://thumbs4.properati.com/6/-9lTZIOGIGHwHaddpPoJu6s92hY=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/2/6c5e21eb-1c7b-41d6-9257-b6e7994ea93c.jpg\na031b9b0ccce57678aab134025713cdb4ad7ed19,2014-10-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7630911,-49.3810839\",-20.7630911,-49.3810839,1500,BRL,1185.99,384.09,,,,,,,,http://www.properati.com.br/ri3h_alugar_comercial_sao-jose-do-rio-preto_rua-gumercindo-tomas-de-aquino,\"Ref.: SA95914Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Centenrio da Emancipao..: Salo Comercial No Distrito Industrial Centenrio da Emancipao, Salo Comercial, Wcs.: 02, Cozinha: 01, M2/ Terreno: 200, M2 rea Construida: 100, Detalhes: Salo Em Construo, Com 2 Wc Com Acessibilidade e Cozinha.porta Frente e Lateral.estrutura Metlica, P Direito 5 Metros.\",Ref.: SA95914 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Dist. Industrial Centenrio da Emancipao,https://thumbs4.properati.com/5/cuTILpWk120n1EtpTTP7CuHqFTI=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2277/xOFbBdd0MAPLxuFIMMMc.jpg\n8198126233f30e45a7ec723640ecd09fc933f35f,2014-10-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7630911,-49.3810839\",-20.7630911,-49.3810839,1500,BRL,1185.99,384.09,,,,,,,,http://www.properati.com.br/ri3j_alugar_comercial_sao-jose-do-rio-preto_rua-gumercindo-tomas-de-aquino,\"Ref.: SA95915Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Centenrio da Emancipao..: Salo Comercial No Distrito Industrial Centenrio da Emancipao, Salo Comercial, Wcs.: 02, Cozinha: 01, M2/ Terreno: 200, M2 rea Construida: 100, Detalhes: Salo Em Construo, Com 2 Wc Com Acessibilidade e Cozinha.porta Frente e Lateral.estrutura Metlica, P Direito 5 Metros.\",Ref.: SA95915 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Dist. Industrial Centenrio da Emancipao,https://thumbs4.properati.com/0/LWklCEKjfuTI94hwh7U-tpkiQxw=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2279/YBRlngu70KNBBuf3pXju.jpg\ncfe8aedbfe7496306c9ee598fdb0799d1a4d43a7,2014-08-14,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178411,-49.387605\",-20.8178411,-49.387605,3000,BRL,2371.98,768.18,,,,,,,,http://www.properati.com.br/mpsw_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95860Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: RedentoraSalo Comercial, Terrea, Acabamento Em Gesso, Forro de Laje, Piso Salas: Frio, M2 rea Construida: 160\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Redentora,https://thumbs4.properati.com/1/w-odT7rMEUYcr3TVS4fo2ausAAI=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1278/Kp7YsojHwZdQDjK4JvMz.jpg\n9002dc7d32f4f097a4f9c789ad93b7f5304396cf,2014-08-14,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178411,-49.387605\",-20.8178411,-49.387605,3000,BRL,2371.98,768.18,,,,,,,,http://www.properati.com.br/mpsz_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95862Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: RedentoraM2 rea Construida: 190, Garagem Descoberta: 02, Forro de Laje, Piso Salas: Frio\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Redentora,https://thumbs4.properati.com/7/xW33i6TXrwRgMFrpyW_syKKKlPs=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1281/UKC5P4P7lZPyQSY9l8xC.jpg\n2128d47314a494ddecda6b6e981c46afbd3fae51,2014-10-30,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,3000,BRL,2371.98,768.18,,,,,,,,http://www.properati.com.br/s9we_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95921Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Redentora..: Salo Comercial Na Redentora, Salo Comercial, M2/ Terreno: 150, Detalhes: tima Localizao!\",Ref.: SA95921 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Redentora,https://thumbs4.properati.com/6/HVrSVpwKgIJpnnFxGcMzyHIeUx4=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2347/abTB8PxHKedvADO9yyhF.jpg\n0329fa7a5536c99eee743612010897cafed7f340,2014-10-15,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8030634,-49.4324803\",-20.8030634,-49.4324803,3000,BRL,2371.98,768.18,,,,,,,,http://www.properati.com.br/re15_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95910Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Res. Palestra..: Salo Comercial No Residencial Palestra, Salo Comercial, Wc. Social: 02, Forro de Laje, Obs: timo Salo, Novo., M2/ Terreno: 250, M2 rea Construida: 200\",Ref.: SA95910 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Res. Palestra,https://thumbs4.properati.com/8/MBuRdEvx5x-V-zpeycnxFNg-n70=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2238/NOqLX7BtA7KEH0SUs5rV.jpg\nc822a8819d8874916877cc6b3c91194cbf5968ca,2014-10-09,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7780086,-49.3450562\",-20.7780086,-49.3450562,3000,BRL,2371.98,768.18,,,,,,,,http://www.properati.com.br/r9j6_alugar_casas_sao-jose-do-rio-preto_avenida-belvedere,\"Ref.: CA95903Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Village Damha Rio Preto I..: Casa Condomnio Village Damha Rio Preto I, Casa Condominio, Dormitrios: 03, Tipo Apto.: 03, C/ A/e: 03, Cozinha: 01, Cozinha Planejada, Fogo, Lavabo, Salas : 01, Sala P/ Ambientes : 02, Piscina, Ducha Externa, Varanda, rea de Servio, Wc. de Empregada/servio, Garagem Coberta: 02, Churrasqueira\",Ref.: CA95903 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Village Damha Rio Preto I,https://thumbs4.properati.com/2/595nD1yJ6OYSKSxIr0D1iMhNilQ=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2205/060de194-4e66-4f1e-b0cc-dd05e276539f.jpg\n2568b8aa05b9d3cb3e9e8ef74c4461c34d2d57b5,2014-10-05,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8350772,-49.369111\",-20.8350772,-49.369111,3000,BRL,2371.98,768.18,,,,,,,,http://www.properati.com.br/r1q8_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95905Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Quinta das Paineiras..: Salo Comercial No Quinta das Paineiras, Salo Comercial, Terrea, Cozinha: 01, Escritrio, M2 rea Construida: 225\",Ref.: SA95905 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Quinta das Paineiras,https://thumbs4.properati.com/6/2tu7W_u475v3n8Ubll7avmjLXPI=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2130/0y7ijJHaZqFbrC0LSLFy.jpg\n0dff14f277324eb9f04d59b6c26758ccdb744e27,2014-12-05,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8126181,-49.3404534\",-20.8126181,-49.3404534,3700,BRL,2925.47,947.43,,,,,,,,http://www.properati.com.br/udzy_alugar_casas_sao-jose-do-rio-preto_avenida-miguel-damha,\"Ref.: CA95938Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Damha III..: Linda Casa Tipo Sobrado No Condomnio Damha Iii, Casa Condominio, Sobrado, Dormitrios: 03, Suite Master: 01, C/ Hidro, Tipo Apto.: 02, C/ A/e, Ducha Dupla, Lavatrio Duplo, Cozinha: 01, Cozinha Planejada, Despensa, Escritrio, Lavabo, Salas : 01, Sala P/ Ambientes : 02, Varanda, rea de Servio, Lavanderia, Quarto de Empregada, Wc. de Empregada/servio, Forro de Laje, Garagem Descoberta: 02, Garagem Coberta: 02, Churrasqueira\",Ref.: CA95938 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Damha III,https://thumbs4.properati.com/0/FGZdTzG9TG6qqioIMRxZ7WLDQWY=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2452/bVU2c6naoVF7KCpphJqL.jpg\n6b3bff7cc70a79dfed41fc0ae514a7ad16a328b8,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,7000,BRL,6640.22,2150.47,,88,24.437159090909088,79.54545454545455,,,,http://www.properati.com.br/ifvc_alugar_comercial_vila-olimpia,\"\tEdifício comercial de excelente padrão, localizado em ponto nobre da Vila Olímpia, próximo da Av. dos Bandeirantes e Shopping Vila Olímpia.\t Prédio conta com 3 elevadores de alta velocidade, sistema de proteção contra incêndio, ar condicionado central, próximo a bancos. Referíªncia: CO65\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",\nc26e111d703af6f65be91df94c274bbd41585a40,2014-08-21,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.6357809,-46.5324419\",-23.6357809,-46.5324419,50000,BRL,39533.44,12803.11,,,,,,,,http://www.properati.com.br/nqbl_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95307Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Rodovia Assis ChateaubriandWcs.: 4, Escritrio, M2/ Terreno: 4.000, Detalhes: Barraco Com 4.000 M\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Rodovia Assis Chateaubriand,https://thumbs4.properati.com/0/lJ2ffPr7gtS2vlQuGTg_zDX6844=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1592/WQmB3JTS7Y2N72aUI5Ud.jpg\n2e8ffab1b55b5245e917b3597009338cb92b6586,2014-10-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7807632,-49.3985157\",-20.7807632,-49.3985157,50000,BRL,39533.44,12803.11,,,,,,,,http://www.properati.com.br/rgyw_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95804Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Waldemar VerdiM2/ Terreno: 6.000, M2 rea Construida: 3.200\",Salo,https://thumbs4.properati.com/3/X38EXdJIkvCXPQCdWURfrgMMMWQ=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2270/OTptGk75zRPMzZ1pL1on.jpg\nc522d5f57ea8e14d18fa3ba746cb581cd379330a,2014-08-20,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,100000,BRL,79066.88,25606.22,,,,,,,,http://www.properati.com.br/np98_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95721Tipo: Salo IndustrialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial IWcs.: Vrios, M2/ Terreno: 13.000, M2 rea Construida: 8.500, Detalhes: tima Localizao\",Tipo: Salo Industrial Cidade: So Jos do Rio Preto - SP Bairro: Dist. Industrial I,https://thumbs4.properati.com/6/jARKWDWV0rGe-HzGUtUeE0X3knw=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1549/ZaCxToSHCaeCL7GxZ08g.jpg\n07383fafc72a9aa9f0286b841b782ca718485de8,2014-09-01,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178198,-49.3468294\",-20.8178198,-49.3468294,3500,BRL,2767.31,896.21,,,,,,1,,http://www.properati.com.br/o246_alugar_casas_sao-jose-do-rio-preto_avenida-nadima-damha,\"Ref.: CA95827Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Damha II (Res. Jardins)Dormitrios: 03, Suite: 03, C/ A/e: 03, Sacada, Sala de Visita, Copa, Cozinha, Cozinha Planejada, Despensa, Piscina, rea de Servio, Lavanderia, Wc. de Empregada/servio, Garagem Descoberta: 02, Garagem Coberta: 02, Churrasqueira, Acabamento Em Gesso, Sanca, Forro de Laje, Piso Salas: Frio;, Documentao: Em Dia.\",Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Damha II (Res. Jardins),https://thumbs4.properati.com/6/Bq9TbjreWNnjd2VrvJ5oieGegeQ=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1889/db5caa0b-ec86-44f4-9c0f-ab26a6816b62.jpg\n179f70a47a9ce50e161ea483ffee741a8e1c7fb2,2014-08-14,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178411,-49.387605\",-20.8178411,-49.387605,3500,BRL,2767.31,896.21,,,,,,,,http://www.properati.com.br/mpsx_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95861Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Redentora TerreaM2 rea Construida: 190, Acabamento Em Gesso, Forro de Laje, Pintura Nova, Piso Salas: Frio\",Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Redentora Terrea,https://thumbs4.properati.com/1/VQPzYdCL1X2L1IkzU17WHDuej9s=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1279/nGCLTL2QhwMJSHGtxR7y.jpg\ne48c41f6ad3dba93e0ac6038a5aa5cda39d651d0,2014-09-01,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.1423284,-51.3750141\",-22.1423284,-51.3750141,3500,BRL,2767.31,896.21,,,,,,,,http://www.properati.com.br/o2m6_alugar_casas_sao-jose-do-rio-preto,\"Ref.: CA95898Tipo: Casa Comercial, Casa ResidencialCidade: So Jos do Rio Preto - SPBairro: Moyss Miguel Haddad..: Casa Residencial No Moyss Miguel Haddad, Casa Residencial, Dormitrios: 03, Suite: 03, C/ Hidro: 01, C/ A/e: 03, Sacada, Wc. Social: 01, Wcs. C/ A/e, Sala de Visita: 01, Copa: 01, Cozinha: 01, Cozinha Planejada, Despensa, Escritrio, Salas : 01, Sala P/ Ambientes : 03, Piscina, Varanda, rea de Servio, Lavanderia, Quarto de Empregada, Wc. de Empregada/servio, Ar Split, Ventilador, Interfone, Acabamento Em Gesso, Sanca, Tv Cabo, Campainha, Quintal, Grade, Murado, Forro de Laje, Piso Salas: Frio, Obs: Imvel Prximo Ao Shopping Iguatemi, M2 rea Construida: 450, Garagem Descoberta: 04, Garagem Coberta: 02, Churrasqueira, Jardim de Inverno, Jardim Interno, Iptu Valor: 199,00\",\"Ref.: CA95898 Tipo: Casa Comercial, Casa Residencial Cidade: So Jos do Rio Preto - SP Bairro: Moyss Miguel Haddad\",https://thumbs4.properati.com/5/fZwdpPACH02ObP9aj7-UFvVm0lE=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1937/a7WmbhKqWo7JqFgAHcOD.jpg\n9ea36b0e269fbf2581eef1510f0148594919b330,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,3150,BRL,2988.09,967.71,,45,21.50466666666667,70,,,,http://www.properati.com.br/ifxf_alugar_comercial_chacara-santo-antonio,\"\tNovAmérica Inside Park, o novo marco imobiliário de São Paulo. É um novo espaço, um novo bairro, uma nova opção de vida. É a expansão urbana mais consciente e mais urbana. Um mundo para morar, trabalhar e viver em plena harmonia. Uma região onde a vida social e a vida familiar se equilibram. Um lugar que concretiza o prazer de viver em uma grande metrópole. 1 torre comercial, escritórios de vila e lojas, 5 condomínios residenciais independentes e 2 parques em mais de 70.000 m² de terreno.\t\tNovAmérica Office Park é um conceito totalmente novo de local de trabalho, que valoriza eficiência e a qualidade de vida de seus ocupantes. EDSA em parceria com Neusa Nakata tiveram a missão de conceber um produto inusitado, diferenciado e particular. O resultado é um cenário privilegiado para que você e seus clientes tenham bem-estar em horário comercial.\t\tA região do NovAmérica reúne as principais empresas nacionais e multinacionais, que chegaram por aqui atraídas pela infraestrutura e pelas importantes e fáceis vias de acesso. O que confirma que a região é o novo pólo econômico de São Paulo.\t\tConheça os diferenciais do NovAmérica Office Park:\t\tÚnico na Nações Unidas a integrar um complexo formado por 1 torre comercial, escritórios de vila, lojas e 5 condomínios residenciais independentes.\tConceito consagrado de bem-estar em horário comercial.\tAcesso ao parque com mais de 10 mil m² destinado à cidade.\tPotencial de clientes vindos dos 5 condomínios residenciais.\tA oportunidade de morar e trabalhar de forma integrada e independente.\tServiços by Facilities Office.\tArquitetura e decoração inspirados nas ultimas tendências mundiais.\tProjeto paisagístico assinado por um dos mais conceituados escritórios do mundo, a EDSA. Referíªncia: CO150\",\"Comercio no(a) Chácara Santo Antônio , São Paulo - SP\",https://thumbs4.properati.com/2/2S3OsO4umzIVXFHbHKTrb7dk-x8=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/150/c0d9b8fc-3da8-4a27-ac1f-4e1684d35312.jpg\na5c14fe842664d12fe4bdfad313d5af251121d89,2014-10-01,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5882535,-46.6167776\",-23.5882535,-46.6167776,1400,BRL,1106.91,358.48,,,,,,,,http://www.properati.com.br/qz98_alugar_comercial_sao-jose-do-rio-preto_rua-da-imprensa,Ref.: SA95836Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Vila DinizDetalhes: Salo Comercial Com Aproximadamente 50 M e 02 Banheiros Com Acessibilidade.,Ref.: SA95836 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Vila Diniz,https://thumbs4.properati.com/9/CRgjdJjcRp1Lz-pPZChI7eL8ZIY=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2075/fOuQlJsX61PBHGGwhPSh.jpg\nb64a9bd212d9e91821e5e892eeff464bbc0202cd,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,9600,BRL,9106.57,2949.21,,120,24.57675,80,,,,http://www.properati.com.br/ifwi_alugar_comercial_vila-olimpia,\"\tConjunto Comercial com 120m² de área útil, 3 vagas, 3 banheiros, 1 copa. Referíªncia: CO112\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/0/3pwYR5bzXi_fuQfUVbzkPbFkst4=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/112/93f2b4dc-86f7-4544-803f-62dfec9dc967.jpg\n59a2898d29cb6860a70355c1b2028b9ab38d89d9,2015-01-13,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5456177,-46.563645\",-23.5456177,-46.563645,1801,BRL,1459.35,472.62,,,,,,2,,http://www.properati.com.br/vyso_alugar_apartamentos_tatuape,\"APTO DE 75M/2, COM 03 DORMITRIOS, SALA AMPLA COM SACADA, COZINHA PLANEJADA, WC SOCIAL, REA DE SERVIO COM WC, REPLETOS DE ARMRIOS, 01 VAGA DE GARAGEM FIXA, EXCELENTE ESTRUTURA DE LAZER COM PISCINA, PLAYGROUD, SALO DE FESTA, CHURRASQUEIRA, SALA DE GINASTICA, EXCELENTE LOCALIZAO, A 100 METROS DO METR.\",LOCAO TATUAPE CONDOMINIO ILHAS GREGAS,https://thumbs4.properati.com/6/-xzzzVWk3lxFITvW285d3YmP00c=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/13/e7c88a20-dcac-49b2-ae42-e782447d3f07.jpg\n1925426e5575ecd98f1e63422a187081754e0f5c,2015-01-13,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5444872,-46.5657875\",-23.5444872,-46.5657875,1499,BRL,1214.64,393.37,,,,,2,1,,http://www.properati.com.br/vysp_alugar_apartamentos_tatuape_rua-serra-de-braganca,\"APTO DE 40M/2, COM 01 DORMITRIO, SALA AMPLA COM SACADA, COZINHA, WC SOCIAL, SEMI-MOBILIADO COM FOGO, SUGGAR, GELADEIRA, MICRO-ONDAS, ARMRIOS PLANEJADOS NA COZINHA, CAMA BOX, GUARDA ROUPA, VENTILADOR DE TETO, RACK DE TV, 02 BANQUETAS, 02 MESINHAS DE CANTO, EXCELENTE ESTRUTURA DE LAZER COM PISCINA, PLAYGROUD, SALO DE FESTA, CHURRASQUEIRA, SAUNA, SALA DE FITINESS, BRINQUEDOTECA, SALO DE JOGOS, SALA DE LEITURA. EXCELENTE LOCALIZAO, PRXIMO DO SUPERMERCADO PO DE ACAR, FCIL ACESSO PARA O METR.\",NEW CONCEPT 22 A,https://thumbs4.properati.com/5/SXF7T5Zfxal6lcQifCYOufBKjYA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/14/0522b83e-c37e-4736-ac81-ca8540d2d806.jpg\nfda45d95b6fe8daf9215dcc80ad057531879eda4,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,4575,BRL,4339.84,1405.48,,120,11.712333333333333,38.125,,,,http://www.properati.com.br/ifxz_alugar_comercial_vila-olimpia,\"\tConjunto Comercial na Vila Olimpia, com 61m², podendo aumentar a área para 117m². Referíªncia: CO179\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/5/cZY_8L_8bfKOV9ay-F-6DsnRZ-c=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/179/0df8ffa9-49a9-49c0-9968-37c13719d904.jpg\n7eb9fb8ad21ff1da490b75fd04643939fd72edf1,2015-01-13,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5508578,-46.5679013\",-23.5508578,-46.5679013,1550,BRL,1255.99,406.76,,,,,11,1,,http://www.properati.com.br/vysn_alugar_apartamentos_tatuape,\"APTO DE 57M/2, COM 02 DORMITRIOS, SALA AMPLA COM SACADA, WC SOCIAL, COZINHA PLANEJADA, AMPLA REA DE SERVIO COM WC, 01 VAGA DE GARAGEM, SALO DE FESTA, CHURRASQUEIRA, PLAYGROUD, QUADRA DE FUTEBOL, EXCELENTE LOCALIZAO, PRXIMO AO SHOPP/METR BOULEVAR TATUAP.\",Apartamento,https://thumbs4.properati.com/4/mwisK4iz0H0viKmBVOGr8B40c1o=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/12/612ab301-0ac4-4c4c-9691-7278200c2b62.jpg\n59a2934bc5a4c3530613fae471a210ae63498d80,2014-09-02,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.826094,-49.376396\",-20.826094,-49.376396,1200,BRL,960.76,311.15,,,,,,1,,http://www.properati.com.br/ob16_alugar_apartamentos_sao-jose-do-rio-preto,\"Apartamento mobiliado, pronto para morar e com excelente localizao, na zona sul.2 dormitrios sendo 1 tipo apto todos com armrio, ventilador de teto e ar-condicionadosala com sacada para 2 ambientes com sofa e estantecozinha planejada com mesa com 4 cadeiras e fogo2 banheiros com box blindex, gabinete e chuveirorea de servio com armrio, varal e mquina de lavar1 vaga de garagem pilotisCondomnio: Porto eletrnico, portaria 24h, elevador, churrasqueira e piscina.\",Apartamento com 2 dormitrios em Rio Preto,https://thumbs4.properati.com/5/VXcYDJRN6VtNxvgVw-mxJOlL_sA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/premier/photos/111/91c65753-86b6-40fd-8673-7f8f107a8459.jpg\nd08581768058f5286ca4f209222d59a3f10af84d,2015-01-13,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-22.8877586,-47.081265\",-22.8877586,-47.081265,2401,BRL,1945.56,630.08,,,,,19,2,,http://www.properati.com.br/vysm_alugar_apartamentos_tatuape,\"APTO DE 93M/2, COM 03 DORMITRIOS, SENDO UMA SUTE, SALA AMPLA COM SACADA E DOIS AMBIENTES, WC SOCIAL, COZINHA, AMPLA REA DE SERVIO, REPLETO DE ARMRIOS, 02 VAGAS DE GARAGEM, LAZER COMPLETO COM PISCINA, PLAYGROUD, SALO DE FESTA, SALO DE JOGOS, SAUNA, CHURRASQUEIRA, EXCELENTE LOCALIZAO, PRXIMO DA PRAA SILVIO ROMERO.\",APTO LOCAO TATUAP,https://thumbs4.properati.com/3/d45ivnQIryA-xDQvwZrOc1pBPlE=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/11/85e5aee8-90fa-4295-bcb5-dce1ed7e789c.jpg\n7739326a3915df1654866f5c27d42e40f0038365,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2200,BRL,2086.92,675.86,,102,6.626078431372549,21.568627450980394,,,,http://www.properati.com.br/ifwp_alugar_comercial_vila-olimpia,\"\tConjunto Comercial com 46m², 2 banheiros, 3 salas, 1 vaga. Referíªncia: CO122\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/6/QhZrO4ITAg_PJagrwPKR0ywe4GI=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/122/80e20053-aaba-4f3b-a8f7-9dc2cdcb44a7.jpg\n4d949c2fcb78e76cf0cb2376ae3a3acc3b27994a,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2200,BRL,2086.92,675.86,,46,14.692608695652174,47.82608695652174,,,,http://www.properati.com.br/ifut_alugar_comercial_vila-olimpia,\"Conjunto Comercial na Rua Helena, com 46m², 1 vaga. Referíªncia: CO44\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/7/rah-1WLiSRF_nrLl-U2mEY27Gus=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/44/3d3a55f5-dd0c-4969-bb57-19f9a554c1f2.jpg\nc98dc531eb6cb68bcec0e60d7dc042bd663caa4d,2014-08-02,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.815191,-49.389435\",-20.815191,-49.389435,5000,BRL,4003.24,1296.47,,,,,,,,http://www.properati.com.br/ludd_alugar_casas_sao-jose-do-rio-preto,\"Imvel com excelente localizao, com recepo, 1 sala com banheiro privativo, 3 salas amplas + 1 interna, todos os ambientes com ar condicionado, cozinha, despensa, garagem interna para vrios veculos. IMVEL SER ENTREGUE REFORMADO E COM AS ACESSIBILIDADES EXIGIDAS!\",Casa Comercial,https://thumbs4.properati.com/8/3TeTIOIgyjtraKZz08buZLIU8W8=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/premier/photos/80/6a0fcb3e-3e78-434f-9624-a5621798b2b2.jpg\ne85c67a2bc55f4834be8d4cf1fd96340ef4ce129,2014-08-04,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8379877,-49.385659\",-20.8379877,-49.385659,800,BRL,632.5,204.84,,,,,,1,,http://www.properati.com.br/lxpc_alugar_casas_higienopolis,\"Ref.: AP95874 Tipo: ApartamentoCidade: So Jos do Rio Preto - SPBairro: Higienpolis..: Apartamento Novo No Jardim Higienopolis, Apartamento, rea Util M2: 50, Dormitrios: 01, C/ A/e, Sacada, Wc. Social: 01, Cozinha C/ A/e, Lavanderia, Elevador, Piso Dormitrios: Porcelanato, Piso Salas: Porcelanato, Obs: Prdio Novo.apto Nunca Habitado., rea de Lazer, Garagem Coberta: 01, Churrasqueira, Espao Gourmet\",Tipo: Apartamento Cidade: So Jos do Rio Preto - SP Bairro: Higienpolis,https://thumbs4.properati.com/6/8tmxgf5PTdg11vI4rVdPwXy39gw=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/806/2077f853-c360-4cd7-b5c8-a33f76415c40.jpg\n33b22b30a043e5a868df61862bb97698b453df89,2014-12-05,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7910821,-49.3781115\",-20.7910821,-49.3781115,800,BRL,632.5,204.84,,,,,,1,,http://www.properati.com.br/ue05_alugar_apartamentos_sao-jose-do-rio-preto_rua-pedro-mulati,\"Ref.: AP95816Tipo: ApartamentoCidade: So Jos do Rio Preto - SPBairro: Jardim ConceioDormitrios: 02, C/ A/e, Wc. Social, Box Wcs., Sala de Estar, Cozinha, Piscina, rea de Servio, Garagem Coberta: 01, rea Util M2: 60, Condominio C/ rea de Lazer, Piscina Adulto, Playground, Valor Condominio R$-: 190,00\",Ref.: AP95816 Tipo: Apartamento Cidade: So Jos do Rio Preto - SP Bairro: Jardim Conceio,https://thumbs4.properati.com/2/4RA-EyT8LswOeQ6lcBbkzLlKjII=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2459/jWyxMNGlETMMxgj2uW9o.jpg\ne2235d97414fcc1a31865b1abe71c1cf85ae01fa,2014-11-17,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7780086,-49.3450562\",-20.7780086,-49.3450562,2700,BRL,2134.78,691.36,,,,,,,,http://www.properati.com.br/tdi5_alugar_casas_sao-jose-do-rio-preto_avenida-belvedere,\"Ref.: CA95926Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Village Damha Rio Preto I..: Casa Condomnio Village Damha Rio Preto, Casa Condominio, Terrea, Dormitrios: 3, Suite: 1, Tipo Apto.: 2, C/ A/e, Lavatrio Duplo: 1, Cozinha C/ A/e: 1, Cozinha Planejada, Escritrio, Lavabo, Salas : 1, Sala P/ Ambientes : 2, Varanda, rea de Servio, Wc. de Empregada/servio, Obs: Espao Para Colocar Piscina, M2 rea Construida: 180, Garagem Descoberta: 2, Garagem Coberta: 2, Churrasqueira, Detalhes: Com Armrios .\",Ref.: CA95926 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Village Damha Rio Preto I ,https://thumbs4.properati.com/3/ZZ3MVCiFvwDaZxqgfl5oQJ1Vp6c=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2390/5d2ae653-6549-4772-b486-cd9360af6ebd.jpg\n1334a26f10895f5a21b6db0adf96e2ff1dc83799,2014-09-16,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7780086,-49.3450562\",-20.7780086,-49.3450562,1250,BRL,988.31,320.07,,,,,,,,http://www.properati.com.br/q4jz_alugar_casas_sao-jose-do-rio-preto_avenida-belvedere,\"Ref.: CA95901Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Maria Stella..: Casa Condomnio Maria Stella, Casa Condominio, Terrea, Dormitrios: 3, Tipo Apto.: 1, Wc. Social: 1, Cozinha: 1, Cozinha Planejada, Salas : 01, Sala P/ Ambientes : 02, Varanda, rea de Servio, Lavanderia, Garagem Coberta: 02, Salo de Festa, Playground, Piscina Adulto, Quadras Poliesportivas: 1, Campo de Futebol: 1, Valor Condominio R$-: 260,00\",Ref.: CA95901 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Maria Stella,https://thumbs4.properati.com/3/nKZAghWN-90yQywuniXpPPLO9sk=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2011/e55aad60-d657-4c71-b732-96032067b76f.jpg\n40c34e74b932ff6e10ff49774a8f7fb6e982c1c2,2014-11-30,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8081017,-49.3505771\",-20.8081017,-49.3505771,4500,BRL,3558.01,1152.28,,,,,,,,http://www.properati.com.br/tz24_alugar_comercial_sao-jose-do-rio-preto_rua-valdomiro-nadotti,\"Ref.: SA95928Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Tres Maria..: Salo Comercial No Bairro Trs Maria, Salo Comercial, Detalhes: 160 Metros Mais 40 Metros de Mesanino.\",Ref.: SA95928 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Tres Maria,https://thumbs4.properati.com/3/Yg9eVpfZKwd2s12w6w1yQ4YYVhY=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2402/MTVaVFERWIxvf0IcXQaQ.jpg\n716428a7c9f46f98fd78e36a72109b0c0ec43753,2014-11-30,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8081017,-49.3505771\",-20.8081017,-49.3505771,4500,BRL,3558.01,1152.28,,,,,,,,http://www.properati.com.br/tz25_alugar_comercial_sao-jose-do-rio-preto_rua-valdomiro-nadotti,\"Ref.: SA95929Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Tres Maria..: Salo Comercial No Bairro Trs Maria, Salo Comercial, M2/ Terreno: 200, Detalhes: 140 Metros Mais 40 Metros de Mesanino.\",Ref.: SA95929 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Tres Maria,https://thumbs4.properati.com/9/a_rVYKLimoBl774T612e8o5Icfo=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2403/fhkihJbLNgNCmHo7eBRG.jpg\n2102860e4c561ee2afec1c15fb71f7c6cfafc28d,2014-08-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,9000,BRL,7116.02,2304.56,,,,,,,,http://www.properati.com.br/muuy_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95893Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Ch. Jockey Clube..: Salo Comercial Na Chcara Jockey Clube, Salo Comercial, M2/ Terreno: 5.000, M2 rea Construida: 1.200, Detalhes: Galpo Com Piso Cimento Polido, Estrutura Metlica, Escritrio, Cozinha, 02 Wc, Entrada Pela Frente e Lateral Para Caminho.p Direito Alto Com 6,/2 M.\",Ref.: SA95893 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Ch. Jockey Clube,https://thumbs4.properati.com/3/H-b0Ol05_NX0A5soGXBvD_dA3wk=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1482/gCB4KEDxOoIlG9HlGbCW.jpg\ndb16c4572d4f19875153b041d1dcb6b82115e6a7,2014-11-03,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8174527,-49.4306981\",-20.8174527,-49.4306981,18000,BRL,14232.04,4609.12,,,,,,,,http://www.properati.com.br/sjyy_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95923Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Parque Industrial..: Salo Comercial No Parque Industrial, Salo Comercial, M2/ Terreno: 3.000, M2 rea Construida: 1.780, Detalhes: 1.000m de Patio.escritrio Com Elevado Vrias Salas, Cozinha, Wc, Vestirio Mas/fem;04 Salas de Descanso Para Motorista Com Vestirio, 02 Chuveiros e 04 Wc;cozinha Externa Com Quiosque + 02 Wc Mas/fem;parte Operacional Com P Direito de 7 Metros, e A Lateral Toda Com Embarque e Desembarque;ptio Com Espao Para Carretas, Caminhes e Carros;portaria Na Entrada do Ptio.\",Ref.: SA95923 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Parque Industrial,https://thumbs4.properati.com/0/wtHJ8Xcu4pqyV7YSP06g_N1yrfg=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2356/rO0uXvqSM9ilLshNDz0f.jpg\nc8c81389391a237255bade4a0608212fa62e13b1,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,4200,BRL,3984.12,1290.28,,107,12.058691588785047,39.25233644859813,,,,http://www.properati.com.br/ifxy_alugar_comercial_vila-olimpia,\"\tConjunto Comercial na Vila Olimpia, com 56m² de área útil, excelente localização.  Referíªncia: CO178\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/7/YjqSlFDSnOcayBrp2UtD_X2xaJM=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/178/fa4df6b6-bb36-40a4-a46b-7b1438c77d03.jpg\ne1f129a3f1296a7e7a3b60d5b96d61c49159900c,2014-11-19,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.9295411,-46.3418105\",-23.9295411,-46.3418105,1600,BRL,1628.47,527.39,,32,16.4809375,50,,1,,http://www.properati.com.br/tkvf_alugar_apartamentos_sao-paulo,\"A 3 Milenio oferece este(a) Apartamento em Sao Vicente, no bairro Morro dos Barbosas - 1 dormitórios. Gostou desse(a) Apartamento em Sao Vicente? Então veja mais informações! Acesse o nosso site clicando no botão Contate o anunciante ou ligue - ou ainda entre em contato conosco pelo email vendas@ Obrigado!\",\"Apartamento em Sao Vicente, no bairro Morro dos Barbosas - 1 dormitórios\",https://thumbs4.properati.com/5/FvlCdG4KWDtvmzsszDUttj3AuAY=/trim/198x0/smart/filters:strip_icc()/www.imobiliariasdesantos.com.br/fotos/F00/72/807200-DSC03573.JPG\na8821d1c24cccd45d37ef69cf2b29ef3be744fad,2014-11-17,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8456698,-49.4030718\",-20.8456698,-49.4030718,3200,BRL,2530.11,819.39,,,,,,1,,http://www.properati.com.br/tdi2_alugar_apartamentos_sao-jose-do-rio-preto_avenida-anisio-haddad,\"Ref.: AP95925Tipo: ApartamentoCidade: So Jos do Rio Preto - SPBairro: Cond. Green Fields..: Apartamento No Condomnio Green Fields, Apartamento, rea Util M2: 152, Dormitrios: 03, Suite Master: 01, Closet , Tipo Apto.: 02, C/ A/e: 02, Wc. Social: 02, Sala de Visita: 01, Cozinha Planejada, Garagem Coberta: 02\",Ref.: AP95925 Tipo: Apartamento Cidade: So Jos do Rio Preto - SP Bairro: Cond. Green Fields,https://thumbs4.properati.com/4/oRIx16Fpw4LPkRsB59wlBS_mxVo=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2387/ae2a6d87-5760-44ff-a47f-d237a5321c3c.jpg\n08918f4a93c54f4505b783a8e31ef11842c55e56,2014-10-01,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5882535,-46.6167776\",-23.5882535,-46.6167776,80000,BRL,63253.52,20484.98,,,,,,,,http://www.properati.com.br/qz9a_alugar_comercial_sao-jose-do-rio-preto_rua-da-imprensa,\"Ref.: SA95835Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Vila DinizM2/ Terreno: 12.000, Detalhes: - Salo Com 5.000 M e Bastante rea Para Estacionamento Aberto.Ideal Para Atacadista, Hipermercado e Distribuidora, Entre Outros.\",Ref.: SA95835 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Vila Diniz,https://thumbs4.properati.com/1/PkKXX6cNiwu9krqBtdWDinLG89A=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2077/vSsX8s9IzXdbNCXPId0W.jpg\n1ce358d0b5c35f146d70dff4089a8b3d287cb7b9,2014-10-08,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8085627,-49.3452813\",-20.8085627,-49.3452813,5500,BRL,4348.67,1408.34,,,,,,,,http://www.properati.com.br/r6de_alugar_comercial_sao-jose-do-rio-preto_avenida-sebastiao-tavares-da-silva,\"Ref.: SA95809Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Vista AlegreM2/ Terreno: 360, M2 rea Construida: 360, Detalhes: Salo Com Vrias Divisrias.\",Salo,https://thumbs4.properati.com/8/dhtnMWfIFZ8mMCFVDpxpvjoF0LA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2184/l63oynNjEecn8u1Dzf3W.jpg\nb6ed51b61bb57831cc00d904741b4f544cafc28f,2014-08-04,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178198,-49.3468294\",-20.8178198,-49.3468294,5500,BRL,4348.67,1408.34,,,,,,1,,http://www.properati.com.br/lxoz_alugar_casas_sao-jose-do-rio-preto,\"Ref.: CA95886Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Damha II(Res. Jardins)..: Casa Condomnio Damha II, Casa Condominio, Sobrado, Dormitrios: 03, Suite: 01, C/ Hidro, Tipo Apto.: 02, C/ A/e: 03, Roupeiro, Home, Cozinha: 01, Cozinha Planejada, Despensa, Escritrio, Lavabo, Salas : 01, Sala P/ Ambientes : 03, Piscina, Varanda, rea de Servio, Quarto de Empregada, Wc. de Empregada/servio, Aquecedor Solar, M2 rea Construida: 350, rea de Lazer, Garagem Descoberta: 03, Garagem Coberta: 03, Churrasqueira\", Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Damha II,https://thumbs4.properati.com/1/gEw1FIkmFLn2_zGBjqnuUzcifYU=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/793/e9d2d588-8d92-4070-b7d6-5b55e4484038.jpg\n1273c64fb8b9402dfad98d3984dec2998d8bdb68,2014-08-15,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8126181,-49.3404534\",-20.8126181,-49.3404534,5500,BRL,4348.67,1408.34,,,,,,1,,http://www.properati.com.br/mqtl_alugar_casas_sao-jose-do-rio-preto_avenida-miguel-damha,\"Ref.: CA95731Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Damha IVDormitrios: 03, Suite: 01, Closet : 01, C/ Hidro, Tipo Apto.: 02, C/ A/e: 02, Wcs.: 05, Wcs. C/ A/e: 04, Box Wcs.: 04, Copa: 01, Cozinha: 01, Cozinha C/ A/e, Despensa, Escritrio, Lavabo, Salas : 01, Sala P/ Ambientes : 02, Piscina, Varanda, rea de Servio, Wc. de Empregada/servio, M2/ Terreno: 420, M2 rea Construida: 380, rea de Lazer, Garagem Descoberta: 02, Garagem Coberta: 02, Churrasqueira, Piso Dormitrios: Porcelanatoq, Piso Salas: Porcelanato, Obs: Imvel Muito Bem Conservado, timo Acabamento., Valor Condominio R$-: 300,00, Detalhes: Toda Reformada.\",Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Damha IV,https://thumbs4.properati.com/6/H5vuIYMzk8pMuWJ-OjcdH4GItq8=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1367/9717e95d-fe6f-4cbc-bb5d-21c2fe92d294.jpg\n6aa6bf8a204f123441efb9f97699ee24cf8f9932,2014-08-15,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8178198,-49.3468294\",-20.8178198,-49.3468294,5500,BRL,4348.67,1408.34,,,,,,1,,http://www.properati.com.br/mqtn_alugar_casas_sao-jose-do-rio-preto_avenida-nadima-damha,\"Ref.: CA95797Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Damha ISobrado, Dormitrios: 03, Suite: 01, Tipo Apto.: 02, Wcs.: 01, Cozinha Planejada, Escritrio, Lavabo, Salas : 01, Sala P/ Ambientes : 03, Piscina, rea de Servio, Wc. de Empregada/servio, rea de Lazer, Garagem Coberta: 03, Churrasqueira, Ar Condicionado, Ventilador, Interfone, Piso Dormitrios: Taco, Piso Salas: Frio\",Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Damha I,https://thumbs4.properati.com/0/NAjAu7cPHQwzwT2j3k1G4X7-A3U=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1369/7b6ca8dd-648a-4e18-b9f5-272073bfbf69.jpg\n8a977c0c4b9ef700024cb2ee3e59de53bcf599c8,2014-07-16,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2000,BRL,1897.2,614.42,,70,8.77742857142857,28.571428571428573,,2,,http://www.properati.com.br/ifzl_alugar_apartamentos_vila-olimpia,\"\tApartamento na Vila Olimpia, sala para 2 ambientes, 2 dormitórios com armários embutidos, cozinha, lavanderia, quarto na área de serviço, 2 banheiros, 1 vaga. Referíªncia: AP237\",\"Apartamento no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/9/waPGo7zWMk2XTzN-br6B0h4Nrgo=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/237/75daca8f-ee37-4813-97af-b4fa00920d4f.jpg\nb48b18eca01fc2732d6afe024904eb1e900cc52a,2014-07-16,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2000,BRL,1897.2,614.42,,54,11.378148148148147,37.03703703703704,,2,,http://www.properati.com.br/ifzn_alugar_apartamentos_saude,\"\tÓtimo apartamento proximo ao Metrê Praça da Arvore, sala para 2 ambientes, 2 dormitórios com armários embutidos, cozinha com armários, banheiro social e de serviço, 1 vaga na garagem, quadra, piscina e play.\tCom pintura nova, pronto para morar!! Referíªncia: AP239\",\"Apartamento no(a) Saúde , São Paulo - SP\",https://thumbs4.properati.com/0/Zof1-heqqvAgC3xdyYRYiQHIX2I=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/239/450071da-5288-4f26-bbb4-66bcacaef572.jpg\n636cbd951ef34773973cfdef37746b911d07a24c,2014-07-16,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,4000,BRL,3794.41,1228.84,,200,6.1442,20,,4,,http://www.properati.com.br/ifxa_alugar_casas_saude,\"\tAluga sobrado em zona mista, residencial e ou serviços, a uma quadra da Av. do Cursino e a 1000m, do Shopping Plaza Sul, 4 dormitórios, sendo uma suite, ampla sala, mais sala de jantar, cozinha, edicula com 3 quartos, mais lavanderia, garagem para 3 veiculos, casa de esquina, com portões automaticos.  Referíªncia: CA145\",\"Casa no(a) Saúde , São Paulo - SP\",https://thumbs4.properati.com/3/0sie3N08lMquoZ655zNy1CeDUbU=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/145/9fef5234-2fa4-4974-b24c-2b3cf6c4c542.jpg\n0812a419c00dcbaaaa926ad4e8de47da7959f9d9,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,5700,BRL,5407.01,1751.09,,127,13.788110236220472,44.881889763779526,,,,http://www.properati.com.br/ifzp_alugar_comercial_saude,\"\tConjunto Comercial proximo do Metrô São Judas, com 109m² de área útil, dividido em 5 salas, com possibilidade de vão livre, 3 banheiro, 1 copa, 3 vagas, prédio 24 horas.  Referíªncia: CO241\",\"Comercio no(a) Saúde , São Paulo - SP\",https://thumbs4.properati.com/1/0kl3BRCM4riJX3LhCObIu4wuBxQ=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/241/25ac4ee5-f867-4808-b226-837aefd7ba2c.jpg\n570fece17687d05345022d1567c79dd80bd1dcb0,2014-12-19,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8312527,-49.360102\",-20.8312527,-49.360102,15000,BRL,11860.02,3840.93,,,,,,,,http://www.properati.com.br/viin_alugar_comercial_sao-jose-do-rio-preto_avenida-marginal-lineu-alcantara-gil,\"Ref.: SA95950Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Campo Verde..: Salo Comercial No Distrito Industrial Campo Verde, Salo Comercial, M2/ Terreno: 5.000, M2 rea Construida: 3.000, Detalhes: tima Localizao Com Asfalto Para Rua, Estacionamento Para 60 Carros.barraco 5.000m2c/ Escritrio Isolado Ao Lado do Galpo C/ 6 Salas Grandes Von Livre Cond. Port.24h.\",Ref.: SA95950 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Dist. Industrial Campo Verde,https://thumbs4.properati.com/6/7lTVZ92lzm8ap5amDGM_eb1EHOU=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2528/yS1CaXFW8XYwJdPuhgGn.jpg\n2ee8e3818d61fdc4e01a5d89be181974d74e4380,2014-08-15,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8424141,-49.3549387\",-20.8424141,-49.3549387,15000,BRL,11860.02,3840.93,,,,,,,,http://www.properati.com.br/mqtc_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95109Tipo: Salo Comercial, Salo IndustrialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Tancredo Neves .Terrea M2/ Terreno: 2.100, M2 rea Construida: 936, Detalhes: Estacionamento Na Frente,entrada Lateral Para Carga e Descarga,prox. do Carrefour\",\"Tipo: Salo Comercial, Salo Industrial Cidade: So Jos do Rio Preto - SP Bairro: Dist. Industrial Tancredo Neves .\",https://thumbs4.properati.com/9/KVlFV9eR-3HhzpzA5EtDKJICEgY=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1358/k6zhNAyNgH9P1excuuTM.jpg\n0f0577616ba85404705aaead7f35ff6e8b4a91da,2014-08-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5733308,-46.544242\",-23.5733308,-46.544242,15000,BRL,11860.02,3840.93,,,,,,,,http://www.properati.com.br/mt62_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: CO95825 Tipo: Predio Comercial, Salo Comercial, Salo Industrial Cidade: So Jos do Rio Preto - SP Bairro: Pq. IndustrialWc. Social: 02, Salas : 06, M2/ Terreno: 1.113, Documentao: Em Dia., Detalhes: Banheiro Feminino e Masculino, 06 Salas Amplas, Sendo de 420 M a Maior.o Salo Possui Ambientes Para Reunies, Sala de Refeitrio de 93 M e Armrio Embutido, Alarme, Campainha, Interfone, Cerca Eltrica e Estacionamento de 258 M Com 25 Vagas Cobertas.\",\"Tipo: Predio Comercial, Salo Comercial, Salo Industrial Cidade: So Jos do Rio Preto - SP Bairro: Pq. Industrial\",https://thumbs4.properati.com/5/ug_ZifuqqZGKLp9_hQAm2sSvkgE=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/1436/Q14vgp5W0wZIU71vOSui.jpg\n8d6a13266a268bd8dd46f19df78ef71e3509ee5a,2014-10-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7700326,-49.3956468\",-20.7700326,-49.3956468,6500,BRL,5139.33,1664.4,,,,,,,,http://www.properati.com.br/ri3n_alugar_comercial_sao-jose-do-rio-preto_avenida-ada-marzochi-polachini,\"Ref.: SA95917Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Mini Dist. Industrial Adail Vetorasso..: Salo Comercial No Mini Destrito Industrial Adail Vetorasso, Salo Comercial, Wcs.: 02, Cozinha: 01, Escritrio, M2/ Terreno: 1.050, M2 rea Construida: 680, Detalhes: Barraco Novo, Com Pilar No Centro;porta Na Frente e Lateral;cobertura Metlica;p Direito 6 Metros.\",Ref.: SA95917 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Mini Dist. Industrial Adail Vetorasso,https://thumbs4.properati.com/2/3gLCbr6emuqSINA3fAYUW1zaIUM=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2283/grmYrDDM8HnJtcT4RzOD.jpg\ndac06563fc851c6596496ceaff68cbf177bb6dde,2014-10-01,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7863702,-49.3690389\",-20.7863702,-49.3690389,6500,BRL,5139.33,1664.4,,,,,,,,http://www.properati.com.br/qz9p_alugar_comercial_sao-jose-do-rio-preto_avenida-solon-da-silva-varginha,\"Ref.: SA95834Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Vila NovaesWc. Social: 03, Mesanino, M2/ Terreno: 530, M2 rea Construida: 480, Detalhes: Salo Comercial Com P Direito de 6m e Mezanino de 55 M.possui Aparelhagem de Ar Condicionado, Som Ambiente, Cmeras de Segurana e Estacionamento Para 18 Carros.local Ideal Para Lojas, Mercados, Igreja, Depsito, Entre Outros.\",Ref.: SA95834 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Vila Novaes,https://thumbs4.properati.com/8/qD9kCsVbiYyB0WGFw5WesI2Ny6s=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2092/d62f4d68-2ea5-4f83-bde9-fdc53bb504f2.jpg\n1ccba6f23edef69215ca9cfe74214a5276597714,2014-10-18,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,6500,BRL,5139.33,1664.4,,,,,,,,http://www.properati.com.br/ri3q_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: SA95919Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Dist. Industrial Centenrio da Emancipao..: Salo Comercial No Distrito Industrial Centenrio da Emancipao., Salo Comercial, Cozinha: 02, Mesanino, Escritrio, M2 rea Construida: 1.015, Detalhes: Escritrio, Cozinha, 02 Wc, Mezanino, 2 Salas, Entrada Lateral.salo 700 Metrosdiviso 315 Metros.\",Ref.: SA95919 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Dist. Industrial Centenrio da Emancipao,https://thumbs4.properati.com/0/FlEAiRaerT0pRZEeW7AhhCuJjJc=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2286/v22UnUeHl8YbhJaP8IaU.jpg\na9d04cd869b56cac7bcb3a54a27147996a973a3d,2015-01-20,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5418835,-46.5583192\",-23.5418835,-46.5583192,1900,BRL,1539.57,498.6,,,,,16,1,,http://www.properati.com.br/w730_alugar_apartamentos_tatuape,\"APTO DE 58M/2, COM 02 DORMITRIOS, SENDO UMA SUTE, SALA AMPLA COM SACADA, COZINHA, WC SOCIAL, REA DE SERVIO, COM ALGUMAS MOBILIAS, TUDO DE PRIMEIRA, 02 VAGAS DE GARAGEM, LAZER COMPLETE, EXCELENTE LOCALIZAO, A UMA QUADRA DO METR.\",MOBILIADO EXCLUSIVE,https://thumbs4.properati.com/2/KuQXATs4BGrSaZvfCzOSMN2pqWs=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/19/30ad0c15-c9ef-48f7-a06e-2a0201bb7433.jpg\n5de8d0e3c8872b0af03bdc517a4a12021c48da59,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,24700,BRL,23430.5,7588.09,,289,26.25636678200692,85.46712802768167,,,,http://www.properati.com.br/ifvd_alugar_comercial_vila-olimpia,\"EDIFí�CIO COMERCIAL DE ALTí�SSIMO PADRí�O,  LOCALIZADO NO PONTO MAIS NOBRE DA REGIí�O, EM FRENTE AOSHOPPING VILA OLí�MPIA, ENTRE AV. DOS BANDEIRANTES E JUSCELINO KUBITSCHEK. OPRí�DIO CONTA COM 6 ELEVADORES DE ALTA VELOCIDADE, SENDO 1 PANORí�MICO, ARCONDICIONADO CENTRAL, FACHADA EM CORTINA DE VIDRO. EDIFí�CIO INTELIGENTE COMSOFISTICADO SISTEMA DE CONTROLE DE INCí�NDIO, CONSUMO DE ENERGIA. Referíªncia: CO66\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",\n705fdcf676aca2c9f51fcc0a332fcff39ee1706c,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,19500,BRL,18497.74,5990.59,,260,23.04073076923077,75,,,,http://www.properati.com.br/ifyk_alugar_comercial_vila-olimpia,\"\tConjunto Comercial com 260m² de área útil, 6 vagas, Ar condicionado Central. Referíªncia: CO200\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/0/-wzyHwNVYSdVIvzDSj7dz-RtyfY=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/200/f2ef8797-b051-4b62-b4fe-e8fdb7523a26.jpg\n179ce00d44c6fafbac93e139f052ab4ce304100d,2014-08-04,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,4200,BRL,3320.8,1075.46,,,,,,,,http://www.properati.com.br/lxpa_alugar_casas_sao-jose-do-rio-preto,\"Ref.: CA95877 Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SPBairro: Cond. Village La MontangneDormitrios: 3, Suite: 1, C/ Hidro: 1, Tipo Apto.: 2, C/ A/e: 3, Cozinha Planejada, Escritrio, Lavabo, Salas : 1, Sala P/ Ambientes : 3, Piscina, rea de Servio, M2/ Terreno: 360, M2 rea Construida: 250, Garagem Descoberta: 2, Garagem Coberta: 2\",Tipo: Casa Condominio Cidade: So Jos do Rio Preto - SP Bairro: Cond. Village La Montangne,https://thumbs4.properati.com/8/XTvYImGZcecKNC8xwzjnrrqWibg=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/804/ce485ed8-97e3-4af6-bc5e-3d347e06b31d.jpg\n868d3ff8ea898557e9819638705d2f823431d000,2015-01-13,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.521407,-46.5769202\",-23.521407,-46.5769202,1500,BRL,1215.45,393.63,,,,,13,1,,http://www.properati.com.br/vysr_alugar_apartamentos_tatuape,\"APTO DE 60M/2, COM 02 DORMITRIO, SALA AMPLA COM SACADA, WC SOCIAL, COZINHA, REA DE SERVIO, 01 VAGA DE GARAGEM, EXCELENTE ESTRUTURA DE LAZER COM PISCINA, PLAYGROUD, SALO DE FESTA, CHURRASQUEIRA, EXCELENTE LOCALIZAO, FCIL ACESSO AO SHOPPING METR/TATUAP.\",131 VITORIA,https://thumbs4.properati.com/0/yyioUci-ExAIuKlfIudXKNKaMAs=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/toledo/photos/16/ff90ae98-dbde-47dc-9f04-32cdb2d2d0d3.jpg\nb9de26b4b13ad0f58469677b72b5171c2b04ae1f,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,13500,BRL,12806.12,4147.33,,183,22.663005464480875,73.77049180327869,,,,http://www.properati.com.br/ifv7_alugar_comercial_vila-olimpia,CONJUNTO COMERCIAL - RECEPCAO - HD - 4 SALAS - 2 WC - COPA  Referíªncia: CO60,\"Comercio no(a) Vila Olímpia , São Paulo - SP\",\n416be9056b69e83819532b65a04c6d1f7135f1ca,2014-12-11,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2400,BRL,1897.57,614.54,,,,,,,,http://www.properati.com.br/uict_alugar_comercial_jardim-maracana,\"Ref.: SA95945Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Jardim Maracan..: Salo Comercial No Jardim Maracan, Salo Comercial, Wc. Social: 02, Cozinha: 01, Forro de Laje, Piso Salas: Frio, M2/ Terreno: 225, M2 rea Construida: 130\",Ref.: SA95945 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Jardim Maracan,https://thumbs4.properati.com/5/3964ltfTag6YXQlyxEM19akYy1s=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2500/f25a8d90-6759-426c-a4ed-d8aefc6b19a4.jpg\nc1aff8edd38c3254c5775927802a8b8fae45a1d8,2014-08-05,rent,house,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,2400,BRL,1897.57,614.54,,,,,,1,,http://www.properati.com.br/mel5_alugar_casas_bosque-da-saude,\"Ref.: CA95883Tipo: Casa ResidencialCidade: So Jos do Rio Preto - SPBairro: Bosque Da Saude..: Casa Residencial No Bosque da Saude, Casa Residencial, Dormitrios: 03, Tipo Apto.: 01, C/ A/e: 03, Wc. Social: 01, Copa: 01, Cozinha: 01, Despensa, Salas : 02, Varanda, Garagem Descoberta: 02, Garagem Coberta: 02\",Tipo: Casa Residencial Cidade: So Jos do Rio Preto - SP Bairro: Bosque Da Saude,https://thumbs4.properati.com/0/aAdm951DKitDcqkiJ8p68O6xdNA=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/848/083f9a71-b22a-4897-bf14-72fbe585dea5.jpg\ne4d569301fb8a21047d67f193929ecf360e9405e,2015-01-11,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,750,BRL,600.6,194.51,,,,,,1,,http://www.properati.com.br/vxnv_alugar_apartamentos_jardim-satelite,\"Excelente apartamento em frente ao condomnio Quinta das Flores totalmente reformado com 2 dormitrios, sala, cozinha planejada, rea de servio, lavabo com gabinete, wc com box blindex e 1 vaga de garagem.Ideal para casal sem filhos e sem animais\",Excelente apartamento no Jardim Satlite,https://thumbs4.properati.com/1/RhUtbG6YnK8FCa_yOduiEf3yyj0=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/tyrreno/photos/1074/71219c81-463f-4710-a46d-5e7e2fee9362.jpg\n6b59e27767f7570db49b2175077b1c059fa20b88,2014-10-01,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-23.5715766,-46.6697673\",-23.5715766,-46.6697673,3100,BRL,2451.06,793.79,,,,,,,,http://www.properati.com.br/qz9r_alugar_comercial_sao-jose-do-rio-preto_avenida-brasil,\"Ref.: SA95828Tipo: Salo ComercialCidade: So Jos do Rio Preto - SPBairro: Jardim MugnaniWc. Social: 02, Cozinha, M2/ Terreno: 350, M2 rea Construida: 210, Detalhes: - Salo Novo!\", Ref.: SA95828 Tipo: Salo Comercial Cidade: So Jos do Rio Preto - SP Bairro: Jardim Mugnani,https://thumbs4.properati.com/5/ShU0-2rvOmZQkWG3Ml57SSATz_s=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2094/VmmbZZ9w1FykW0ldwpGM.jpg\n3931096ab81c0a74496858654375447e859df8f2,2014-12-05,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.7910821,-49.3781115\",-20.7910821,-49.3781115,880,BRL,695.77,225.33,,,,,,1,,http://www.properati.com.br/ue04_alugar_apartamentos_sao-jose-do-rio-preto_rua-pedro-mulati,\"Ref.: AP95815Tipo: ApartamentoCidade: So Jos do Rio Preto - SPBairro: Jardim ConceioCobertura, Dormitrios: 02, C/ A/e, Wc. Social, Box Wcs., Sala de Estar, Cozinha, Piscina, rea de Servio, rea de Lazer, Garagem Coberta: 01, rea Util M2: 65, Playground\",Ref.: AP95815 Tipo: Apartamento Cidade: So Jos do Rio Preto - SP Bairro: Jardim Conceio,https://thumbs4.properati.com/3/0zqbkQ73LUnQeQMp0yntvzoZrq8=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2458/Dv0976z6fjHNbJf7oAX0.jpg\nc15e079e557ec6ad9d86baede07324e678686764,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,3800,BRL,3604.66,1167.39,,88,13.265795454545456,43.18181818181818,,,,http://www.properati.com.br/ifzr_alugar_comercial_saude,\"\tConjunto Comercial proximo do Metrô São Judas, com 76m², 2 banheiros, 2 vagas, 1 copa, predio 24 horas. Referíªncia: CO243\",\"Comercio no(a) Saúde , São Paulo - SP\",https://thumbs4.properati.com/4/h5_FesPCfkGnmz5ac8c3DvXy_cE=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/243/68c5314b-39b1-4ebd-af49-694d915540b0.jpg\n62cbd166c6e120af08202b4db367db83240ed7e1,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,8500,BRL,8063.11,2611.28,,300,8.704266666666667,28.333333333333332,,,,http://www.properati.com.br/ifw2_alugar_comercial_vila-olimpia,\"\t\t\tLindo(a) Comercio de 300 metros quadrados no bairro Vila Olímpia na cidade de São Paulo - SP.\t\t\t, 2 banheiro(s), 6 vagas(s) de garagem.\t \t\tCondições de Pagamento: \t \t \t \t\tCaracteristicas: Referíªncia: CO93\",\"Comercio no(a) Vila Olímpia , São Paulo - SP\",https://thumbs4.properati.com/1/gH6VwXVOHsfAy5JV8elaJg59lGA=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/93/4276fcba-994a-4296-9a35-65c580711457.jpg\n5a5bfb194fdbec1a633f5894a66c8bf45c8ae463,2015-01-06,rent,apartment,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,1100,BRL,869.7,281.66,,,,,,,,http://www.properati.com.br/vv2s_alugar_apartamentos_sao-jose-do-rio-preto,\"Ref.: AP95935Tipo: ApartamentoCidade: So Jos do Rio Preto - SPBairro: Vila Itlia..: Apartamento Residencial Na Vila Itlia, Apartamento, rea Util M2: 63, Dormitrios: 02, Closet , Tipo Apto.: 01, Wc. Social: 01, Sala de Tv, Cozinha: 01, Cozinha C/ A/e, Garagem Coberta: 01, Detalhes: Prdio Novo.\",Ref.: AP95935 Tipo: Apartamento Cidade: So Jos do Rio Preto - SP Bairro: Vila Itlia,https://thumbs4.properati.com/5/XPnfndqmnEKY04smTHRwdeanGd8=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2535/atPPaTZcVegFbIYjH45d.jpg\n8f0adde258e0b9ad5897ba55288b52005ca749a8,2014-07-16,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,,,,3200,BRL,3035.52,983.07,,100,9.8307,32,,,,http://www.properati.com.br/ifxp_alugar_comercial_republica,\"\tLoja/Galpão com mezanino, pé direito duplo, localizada na Av. Amaral Guegel, proximo da Consolação, 2 banheiro e 2 vagas demarcadas. Referíªncia: CO169\",\"Comercio no(a) República , São Paulo - SP\",https://thumbs4.properati.com/6/XJyKobKfgKlfwiO0SB2Tt2i0Y9w=/trim/198x0/smart/filters:strip_icc()/souzapinto.imobfusion01.com.br/accounts/souzapinto/data/photo/169/50b1ac29-6a0b-4488-aaa4-07bc131dd969.jpg\n480229dcb811d916f90a02ffd9c5b62e8a72ccbe,2014-10-15,rent,store,São Paulo,|Brasil|São Paulo|,Brasil,São Paulo,,\"-20.8168432,-49.3930989\",-20.8168432,-49.3930989,17000,BRL,13441.34,4353.05,,,,,,,,http://www.properati.com.br/re16_alugar_comercial_sao-jose-do-rio-preto,\"Ref.: CO95289Tipo: Predio ComercialCidade: So Jos do Rio Preto - SPBairro: Vila dos BancariosM2 rea Construida: 800, Garagem Descoberta: 20, Detalhes: Predio Comercial Com 10m Salas de 80 M Cada, Fica Em Um Pavimento Com Elevador, 20 Vagas Para Estacionar .\",Loja,https://thumbs4.properati.com/4/Z-A_sLSPQOFzDbPb8MkkcY9IwMU=/trim/198x0/smart/filters:strip_icc()/static.if2.com.br/acc/interplan/photos/2239/bsfsEYepcv9Cu4EHDvjU.jpg\n\n", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_content" } - ], - "schemaVersion": 32, - "tags": [ - "gdev", - "panel-tests", - "table" - ], - "templating": { - "list": [] + ], + "title": "No pagination, no footer", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "country_name": true, + "created_on": true, + "expenses": true, + "floor": true, + "geonames_id": true, + "id": true, + "image_thumbnail": true, + "lat": true, + "lat_lon": true, + "lon": true, + "operation": true, + "place_with_parent_names": true, + "price_aprox_local_currency": true, + "price_aprox_usd": true, + "state_name": true, + "surface_total_in_m2": true + }, + "indexByName": { + "country_name": 13, + "created_on": 9, + "currency": 19, + "description": 5, + "expenses": 24, + "floor": 7, + "geonames_id": 15, + "id": 0, + "image_thumbnail": 26, + "lat": 17, + "lat_lon": 16, + "lon": 18, + "operation": 8, + "place_name": 4, + "place_with_parent_names": 12, + "price": 11, + "price_aprox_local_currency": 20, + "price_aprox_usd": 21, + "price_per_m2": 23, + "price_usd_per_m2": 22, + "properati_url": 25, + "property_type": 2, + "rooms": 6, + "state_name": 14, + "surface_covered_in_m2": 3, + "surface_total_in_m2": 10, + "title": 1 + }, + "renameByName": { + "description": "Description", + "place_name": "City", + "price": "Price", + "properati_url": "URL", + "property_type": "Type", + "rooms": "Rooms", + "surface_covered_in_m2": "Surface", + "title": "Property name" + } + } + } + ], + "type": "table" }, - "time": { - "from": "now-6h", - "to": "now" + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [ + { + "options": { + "rent": { + "color": "yellow", + "index": 0 + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "property_type" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "store": { + "color": "blue", + "index": 0 + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "title" + }, + "properties": [ + { + "id": "custom.width", + "value": 205 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Number of rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 66 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Description" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URL" + }, + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Show details", + "url": "${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Surface" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "orange", + "value": 100 + }, + { + "color": "yellow", + "value": 200 + }, + { + "color": "green", + "value": 300 + }, + { + "color": "#EAB839", + "value": 500 + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "#EF843C", + "value": 2000 + } + ] + } + }, + { + "id": "unit", + "value": "areaM2" + }, + { + "id": "custom.width", + "value": 93 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Type" + }, + "properties": [ + { + "id": "custom.width", + "value": 94 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "City" + }, + "properties": [ + { + "id": "custom.width", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Price" + }, + "properties": [ + { + "id": "unit", + "value": "currencyUSD" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 6, + "options": { + "footer": { + "enablePagination": false, + "fields": "", + "reducer": ["sum"], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Surface" + } + ] + }, + "pluginVersion": "9.0.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "title": "No pagination, footer", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "country_name": true, + "created_on": true, + "expenses": true, + "floor": true, + "geonames_id": true, + "id": true, + "image_thumbnail": true, + "lat": true, + "lat_lon": true, + "lon": true, + "operation": true, + "place_with_parent_names": true, + "price_aprox_local_currency": true, + "price_aprox_usd": true, + "state_name": true, + "surface_total_in_m2": true + }, + "indexByName": { + "country_name": 13, + "created_on": 9, + "currency": 19, + "description": 5, + "expenses": 24, + "floor": 7, + "geonames_id": 15, + "id": 0, + "image_thumbnail": 26, + "lat": 17, + "lat_lon": 16, + "lon": 18, + "operation": 8, + "place_name": 4, + "place_with_parent_names": 12, + "price": 11, + "price_aprox_local_currency": 20, + "price_aprox_usd": 21, + "price_per_m2": 23, + "price_usd_per_m2": 22, + "properati_url": 25, + "property_type": 2, + "rooms": 6, + "state_name": 14, + "surface_covered_in_m2": 3, + "surface_total_in_m2": 10, + "title": 1 + }, + "renameByName": { + "description": "Description", + "place_name": "City", + "price": "Price", + "properati_url": "URL", + "property_type": "Type", + "rooms": "Rooms", + "surface_covered_in_m2": "Surface", + "title": "Property name" + } + } + } + ], + "type": "table" }, - "timepicker": {}, - "timezone": "", - "title": "Panel Tests - Table - Pagination", - "uid": "1YGJxPUnz", - "version": 3, - "weekStart": "" + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [ + { + "options": { + "rent": { + "color": "yellow", + "index": 0 + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "property_type" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "store": { + "color": "blue", + "index": 0 + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "title" + }, + "properties": [ + { + "id": "custom.width", + "value": 205 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Number of rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 66 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Description" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URL" + }, + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Show details", + "url": "${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Surface" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "orange", + "value": 100 + }, + { + "color": "yellow", + "value": 200 + }, + { + "color": "green", + "value": 300 + }, + { + "color": "#EAB839", + "value": 500 + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "#EF843C", + "value": 2000 + } + ] + } + }, + { + "id": "unit", + "value": "areaM2" + }, + { + "id": "custom.width", + "value": 93 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Type" + }, + "properties": [ + { + "id": "custom.width", + "value": 94 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "City" + }, + "properties": [ + { + "id": "custom.width", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Price" + }, + "properties": [ + { + "id": "unit", + "value": "currencyUSD" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 9, + "options": { + "footer": { + "enablePagination": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": false, + "sortBy": [ + { + "desc": true, + "displayName": "Surface" + } + ] + }, + "pluginVersion": "9.0.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "country_name": true, + "created_on": true, + "expenses": true, + "floor": true, + "geonames_id": true, + "id": true, + "image_thumbnail": true, + "lat": true, + "lat_lon": true, + "lon": true, + "operation": true, + "place_with_parent_names": true, + "price_aprox_local_currency": true, + "price_aprox_usd": true, + "state_name": true, + "surface_total_in_m2": true + }, + "indexByName": { + "country_name": 13, + "created_on": 9, + "currency": 19, + "description": 5, + "expenses": 24, + "floor": 7, + "geonames_id": 15, + "id": 0, + "image_thumbnail": 26, + "lat": 17, + "lat_lon": 16, + "lon": 18, + "operation": 8, + "place_name": 4, + "place_with_parent_names": 12, + "price": 11, + "price_aprox_local_currency": 20, + "price_aprox_usd": 21, + "price_per_m2": 23, + "price_usd_per_m2": 22, + "properati_url": 25, + "property_type": 2, + "rooms": 6, + "state_name": 14, + "surface_covered_in_m2": 3, + "surface_total_in_m2": 10, + "title": 1 + }, + "renameByName": { + "description": "Description", + "place_name": "City", + "price": "Price", + "properati_url": "URL", + "property_type": "Type", + "rooms": "Rooms", + "surface_covered_in_m2": "Surface", + "title": "Property name" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [ + { + "options": { + "rent": { + "color": "yellow", + "index": 0 + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "property_type" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "store": { + "color": "blue", + "index": 0 + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "title" + }, + "properties": [ + { + "id": "custom.width", + "value": 205 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Number of rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 66 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Description" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URL" + }, + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Show details", + "url": "${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Surface" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "orange", + "value": 100 + }, + { + "color": "yellow", + "value": 200 + }, + { + "color": "green", + "value": 300 + }, + { + "color": "#EAB839", + "value": 500 + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "#EF843C", + "value": 2000 + } + ] + } + }, + { + "id": "unit", + "value": "areaM2" + }, + { + "id": "custom.width", + "value": 93 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Type" + }, + "properties": [ + { + "id": "custom.width", + "value": 94 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "City" + }, + "properties": [ + { + "id": "custom.width", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Price" + }, + "properties": [ + { + "id": "unit", + "value": "currencyUSD" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 7, + "options": { + "footer": { + "enablePagination": true, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Surface" + } + ] + }, + "pluginVersion": "9.0.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "title": "Pagination, no footer", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "country_name": true, + "created_on": true, + "expenses": true, + "floor": true, + "geonames_id": true, + "id": true, + "image_thumbnail": true, + "lat": true, + "lat_lon": true, + "lon": true, + "operation": true, + "place_with_parent_names": true, + "price_aprox_local_currency": true, + "price_aprox_usd": true, + "state_name": true, + "surface_total_in_m2": true + }, + "indexByName": { + "country_name": 13, + "created_on": 9, + "currency": 19, + "description": 5, + "expenses": 24, + "floor": 7, + "geonames_id": 15, + "id": 0, + "image_thumbnail": 26, + "lat": 17, + "lat_lon": 16, + "lon": 18, + "operation": 8, + "place_name": 4, + "place_with_parent_names": 12, + "price": 11, + "price_aprox_local_currency": 20, + "price_aprox_usd": 21, + "price_per_m2": 23, + "price_usd_per_m2": 22, + "properati_url": 25, + "property_type": 2, + "rooms": 6, + "state_name": 14, + "surface_covered_in_m2": 3, + "surface_total_in_m2": 10, + "title": 1 + }, + "renameByName": { + "description": "Description", + "place_name": "City", + "price": "Price", + "properati_url": "URL", + "property_type": "Type", + "rooms": "Rooms", + "surface_covered_in_m2": "Surface", + "title": "Property name" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [ + { + "options": { + "rent": { + "color": "yellow", + "index": 0 + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "property_type" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "store": { + "color": "blue", + "index": 0 + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "title" + }, + "properties": [ + { + "id": "custom.width", + "value": 205 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Number of rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 66 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Description" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URL" + }, + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Show details", + "url": "${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Surface" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "orange", + "value": 100 + }, + { + "color": "yellow", + "value": 200 + }, + { + "color": "green", + "value": 300 + }, + { + "color": "#EAB839", + "value": 500 + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "#EF843C", + "value": 2000 + } + ] + } + }, + { + "id": "unit", + "value": "areaM2" + }, + { + "id": "custom.width", + "value": 93 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Type" + }, + "properties": [ + { + "id": "custom.width", + "value": 94 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "City" + }, + "properties": [ + { + "id": "custom.width", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Price" + }, + "properties": [ + { + "id": "unit", + "value": "currencyUSD" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 8, + "options": { + "footer": { + "enablePagination": true, + "fields": "", + "reducer": ["sum"], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Surface" + } + ] + }, + "pluginVersion": "9.0.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "title": "Pagination and footer", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "country_name": true, + "created_on": true, + "expenses": true, + "floor": true, + "geonames_id": true, + "id": true, + "image_thumbnail": true, + "lat": true, + "lat_lon": true, + "lon": true, + "operation": true, + "place_with_parent_names": true, + "price_aprox_local_currency": true, + "price_aprox_usd": true, + "state_name": true, + "surface_total_in_m2": true + }, + "indexByName": { + "country_name": 13, + "created_on": 9, + "currency": 19, + "description": 5, + "expenses": 24, + "floor": 7, + "geonames_id": 15, + "id": 0, + "image_thumbnail": 26, + "lat": 17, + "lat_lon": 16, + "lon": 18, + "operation": 8, + "place_name": 4, + "place_with_parent_names": 12, + "price": 11, + "price_aprox_local_currency": 20, + "price_aprox_usd": 21, + "price_per_m2": 23, + "price_usd_per_m2": 22, + "properati_url": 25, + "property_type": 2, + "rooms": 6, + "state_name": 14, + "surface_covered_in_m2": 3, + "surface_total_in_m2": 10, + "title": 1 + }, + "renameByName": { + "description": "Description", + "place_name": "City", + "price": "Price", + "properati_url": "URL", + "property_type": "Type", + "rooms": "Rooms", + "surface_covered_in_m2": "Surface", + "title": "Property name" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [ + { + "options": { + "rent": { + "color": "yellow", + "index": 0 + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "property_type" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "store": { + "color": "blue", + "index": 0 + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "title" + }, + "properties": [ + { + "id": "custom.width", + "value": 205 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Number of rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 66 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Description" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URL" + }, + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Show details", + "url": "${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Surface" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "orange", + "value": 100 + }, + { + "color": "yellow", + "value": 200 + }, + { + "color": "green", + "value": 300 + }, + { + "color": "#EAB839", + "value": 500 + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "#EF843C", + "value": 2000 + } + ] + } + }, + { + "id": "unit", + "value": "areaM2" + }, + { + "id": "custom.width", + "value": 93 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Type" + }, + "properties": [ + { + "id": "custom.width", + "value": 94 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "City" + }, + "properties": [ + { + "id": "custom.width", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Price" + }, + "properties": [ + { + "id": "unit", + "value": "currencyUSD" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 16 + }, + "id": 10, + "options": { + "footer": { + "enablePagination": true, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": false, + "sortBy": [ + { + "desc": true, + "displayName": "Surface" + } + ] + }, + "pluginVersion": "9.0.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "title": "Pagination, no footer, no header", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "country_name": true, + "created_on": true, + "expenses": true, + "floor": true, + "geonames_id": true, + "id": true, + "image_thumbnail": true, + "lat": true, + "lat_lon": true, + "lon": true, + "operation": true, + "place_with_parent_names": true, + "price_aprox_local_currency": true, + "price_aprox_usd": true, + "state_name": true, + "surface_total_in_m2": true + }, + "indexByName": { + "country_name": 13, + "created_on": 9, + "currency": 19, + "description": 5, + "expenses": 24, + "floor": 7, + "geonames_id": 15, + "id": 0, + "image_thumbnail": 26, + "lat": 17, + "lat_lon": 16, + "lon": 18, + "operation": 8, + "place_name": 4, + "place_with_parent_names": 12, + "price": 11, + "price_aprox_local_currency": 20, + "price_aprox_usd": 21, + "price_per_m2": 23, + "price_usd_per_m2": 22, + "properati_url": 25, + "property_type": 2, + "rooms": 6, + "state_name": 14, + "surface_covered_in_m2": 3, + "surface_total_in_m2": 10, + "title": 1 + }, + "renameByName": { + "description": "Description", + "place_name": "City", + "price": "Price", + "properati_url": "URL", + "property_type": "Type", + "rooms": "Rooms", + "surface_covered_in_m2": "Surface", + "title": "Property name" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [ + { + "options": { + "rent": { + "color": "yellow", + "index": 0 + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "property_type" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "store": { + "color": "blue", + "index": 0 + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "title" + }, + "properties": [ + { + "id": "custom.width", + "value": 205 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Number of rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 66 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Description" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URL" + }, + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Show details", + "url": "${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Surface" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "orange", + "value": 100 + }, + { + "color": "yellow", + "value": 200 + }, + { + "color": "green", + "value": 300 + }, + { + "color": "#EAB839", + "value": 500 + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "#EF843C", + "value": 2000 + } + ] + } + }, + { + "id": "unit", + "value": "areaM2" + }, + { + "id": "custom.width", + "value": 93 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Type" + }, + "properties": [ + { + "id": "custom.width", + "value": 94 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "City" + }, + "properties": [ + { + "id": "custom.width", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Price" + }, + "properties": [ + { + "id": "unit", + "value": "currencyUSD" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 16 + }, + "id": 11, + "options": { + "footer": { + "enablePagination": true, + "fields": "", + "reducer": ["sum"], + "show": true + }, + "showHeader": false, + "sortBy": [ + { + "desc": true, + "displayName": "Surface" + } + ] + }, + "pluginVersion": "9.0.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "title": "Pagination, footer, no header", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "country_name": true, + "created_on": true, + "expenses": true, + "floor": true, + "geonames_id": true, + "id": true, + "image_thumbnail": true, + "lat": true, + "lat_lon": true, + "lon": true, + "operation": true, + "place_with_parent_names": true, + "price_aprox_local_currency": true, + "price_aprox_usd": true, + "state_name": true, + "surface_total_in_m2": true + }, + "indexByName": { + "country_name": 13, + "created_on": 9, + "currency": 19, + "description": 5, + "expenses": 24, + "floor": 7, + "geonames_id": 15, + "id": 0, + "image_thumbnail": 26, + "lat": 17, + "lat_lon": 16, + "lon": 18, + "operation": 8, + "place_name": 4, + "place_with_parent_names": 12, + "price": 11, + "price_aprox_local_currency": 20, + "price_aprox_usd": 21, + "price_per_m2": 23, + "price_usd_per_m2": 22, + "properati_url": 25, + "property_type": 2, + "rooms": 6, + "state_name": 14, + "surface_covered_in_m2": 3, + "surface_total_in_m2": 10, + "title": 1 + }, + "renameByName": { + "description": "Description", + "place_name": "City", + "price": "Price", + "properati_url": "URL", + "property_type": "Type", + "rooms": "Rooms", + "surface_covered_in_m2": "Surface", + "title": "Property name" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [ + { + "options": { + "rent": { + "color": "yellow", + "index": 0 + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "property_type" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "store": { + "color": "blue", + "index": 0 + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "title" + }, + "properties": [ + { + "id": "custom.width", + "value": 205 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Number of rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 66 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Description" + }, + "properties": [ + { + "id": "custom.inspect", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "URL" + }, + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Show details", + "url": "${__value.raw}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Surface" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "orange", + "value": 100 + }, + { + "color": "yellow", + "value": 200 + }, + { + "color": "green", + "value": 300 + }, + { + "color": "#EAB839", + "value": 500 + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "#EF843C", + "value": 2000 + } + ] + } + }, + { + "id": "unit", + "value": "areaM2" + }, + { + "id": "custom.width", + "value": 93 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Type" + }, + "properties": [ + { + "id": "custom.width", + "value": 94 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "City" + }, + "properties": [ + { + "id": "custom.width", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Rooms" + }, + "properties": [ + { + "id": "custom.width", + "value": 77 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Price" + }, + "properties": [ + { + "id": "unit", + "value": "currencyUSD" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 16 + }, + "id": 12, + "options": { + "footer": { + "enablePagination": true, + "fields": "", + "reducer": ["sum"], + "show": true + }, + "showHeader": false, + "sortBy": [ + { + "desc": true, + "displayName": "Surface" + } + ] + }, + "pluginVersion": "9.0.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "country_name": true, + "created_on": true, + "expenses": true, + "floor": true, + "geonames_id": true, + "id": true, + "image_thumbnail": true, + "lat": true, + "lat_lon": true, + "lon": true, + "operation": true, + "place_with_parent_names": true, + "price_aprox_local_currency": true, + "price_aprox_usd": true, + "state_name": true, + "surface_total_in_m2": true + }, + "indexByName": { + "country_name": 13, + "created_on": 9, + "currency": 19, + "description": 5, + "expenses": 24, + "floor": 7, + "geonames_id": 15, + "id": 0, + "image_thumbnail": 26, + "lat": 17, + "lat_lon": 16, + "lon": 18, + "operation": 8, + "place_name": 4, + "place_with_parent_names": 12, + "price": 11, + "price_aprox_local_currency": 20, + "price_aprox_usd": 21, + "price_per_m2": 23, + "price_usd_per_m2": 22, + "properati_url": 25, + "property_type": 2, + "rooms": 6, + "state_name": 14, + "surface_covered_in_m2": 3, + "surface_total_in_m2": 10, + "title": 1 + }, + "renameByName": { + "description": "Description", + "place_name": "City", + "price": "Price", + "properati_url": "URL", + "property_type": "Type", + "rooms": "Rooms", + "surface_covered_in_m2": "Surface", + "title": "Property name" + } + } + } + ], + "type": "table" + } + ], + "schemaVersion": 32, + "tags": ["gdev", "panel-tests", "table"], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Panel Tests - Table - Pagination", + "uid": "1YGJxPUnz", + "version": 3, + "weekStart": "" } diff --git a/devenv/dev-dashboards/panel-table/table_sparkline_cell.json b/devenv/dev-dashboards/panel-table/table_sparkline_cell.json index 24ec5a57326..d36609b1678 100644 --- a/devenv/dev-dashboards/panel-table/table_sparkline_cell.json +++ b/devenv/dev-dashboards/panel-table/table_sparkline_cell.json @@ -23,8 +23,7 @@ "panels": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -69,9 +68,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -80,8 +77,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "ca3da78e-6bcc-4a2a-a080-d338a14528ca" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -103,8 +99,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -151,9 +146,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -162,8 +155,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "ca3da78e-6bcc-4a2a-a080-d338a14528ca" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -185,8 +177,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -233,9 +224,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -244,8 +233,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "ca3da78e-6bcc-4a2a-a080-d338a14528ca" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -267,8 +255,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -317,9 +304,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -328,8 +313,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "ca3da78e-6bcc-4a2a-a080-d338a14528ca" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -351,8 +335,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -401,9 +384,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -412,8 +393,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "ca3da78e-6bcc-4a2a-a080-d338a14528ca" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -435,8 +415,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -487,9 +466,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -498,8 +475,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "ca3da78e-6bcc-4a2a-a080-d338a14528ca" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -521,8 +497,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -566,9 +541,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true diff --git a/devenv/dev-dashboards/panel-table/table_tests.json b/devenv/dev-dashboards/panel-table/table_tests.json index a8d0a0d5253..be4041d45d6 100644 --- a/devenv/dev-dashboards/panel-table/table_tests.json +++ b/devenv/dev-dashboards/panel-table/table_tests.json @@ -19,7 +19,9 @@ "panels": [ { "columns": [], - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fontSize": "100%", "gridPos": { "h": 11, @@ -114,7 +116,9 @@ "value": "current" } ], - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fontSize": "100%", "gridPos": { "h": 11, @@ -196,7 +200,9 @@ }, { "columns": [], - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fontSize": "100%", "gridPos": { "h": 7, @@ -260,7 +266,9 @@ }, { "columns": [], - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fontSize": "100%", "gridPos": { "h": 8, @@ -342,7 +350,9 @@ }, { "columns": [], - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fontSize": "100%", "gridPos": { "h": 10, @@ -431,11 +441,7 @@ ], "refresh": false, "schemaVersion": 16, - "tags": [ - "gdev", - "panel-tests", - "table" - ], + "tags": ["gdev", "panel-tests", "table"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-table/table_tests_new.json b/devenv/dev-dashboards/panel-table/table_tests_new.json index e928e9fc578..801b6e3fbd9 100644 --- a/devenv/dev-dashboards/panel-table/table_tests_new.json +++ b/devenv/dev-dashboards/panel-table/table_tests_new.json @@ -36,8 +36,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -139,9 +138,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true, @@ -157,8 +154,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -171,18 +167,16 @@ { "id": "reduce", "options": { - "reducers": [ - "max", - "mean", - "last" - ] + "reducers": ["max", "mean", "last"] } } ], "type": "table" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -276,9 +270,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true, @@ -294,8 +286,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk_table", @@ -329,7 +320,9 @@ "type": "table" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -423,9 +416,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true, @@ -436,8 +427,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "labels": "cluster=eu,service=checkout", "min": 0.1, @@ -466,7 +456,9 @@ "type": "table" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -598,9 +590,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true, @@ -610,8 +600,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "labels": "cluster=eu,service=checkout", "min": 0.1, @@ -621,8 +610,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "hide": false, "labels": "cluster=eu,service=checkout", @@ -678,8 +666,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -762,9 +749,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true, @@ -775,8 +760,7 @@ { "alias": "S1", "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "labels": "server=A", "refId": "A", @@ -787,8 +771,7 @@ { "alias": "S2", "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "labels": "server=B", "refId": "B", @@ -799,8 +782,7 @@ { "alias": "S3", "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "labels": "server=C", "refId": "C", @@ -820,8 +802,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -873,9 +854,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": false, @@ -891,8 +870,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk_table", @@ -925,8 +903,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -968,9 +945,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": true }, "showHeader": true, @@ -980,8 +955,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "refId": "A" } @@ -993,11 +967,7 @@ "preload": false, "refresh": "", "schemaVersion": 41, - "tags": [ - "gdev", - "panel-tests", - "table" - ], + "tags": ["gdev", "panel-tests", "table"], "templating": { "list": [] }, @@ -1006,17 +976,7 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "", "title": "Panel Tests - React Table", diff --git a/devenv/dev-dashboards/panel-text/text-options.json b/devenv/dev-dashboards/panel-text/text-options.json index 696bda08d52..bff4a12bfd0 100644 --- a/devenv/dev-dashboards/panel-text/text-options.json +++ b/devenv/dev-dashboards/panel-text/text-options.json @@ -29,7 +29,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 9, "w": 12, @@ -50,8 +52,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" @@ -61,7 +62,9 @@ "type": "text" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 9, "w": 12, @@ -82,8 +85,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" @@ -93,7 +95,9 @@ "type": "text" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 9, "w": 12, @@ -114,8 +118,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" @@ -125,7 +128,9 @@ "type": "text" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 9, "w": 12, @@ -146,8 +151,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" @@ -165,16 +169,11 @@ { "current": { "selected": false, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "definition": "*", "hide": 0, @@ -198,16 +197,11 @@ { "current": { "selected": false, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": ["All"], + "value": ["$__all"] }, "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "definition": "$datacenter.*", "hide": 0, @@ -231,18 +225,11 @@ { "current": { "selected": false, - "text": [ - "AAA", - "ACB" - ], - "value": [ - "AAA", - "ACB" - ] + "text": ["AAA", "ACB"], + "value": ["AAA", "ACB"] }, "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "definition": "$datacenter.$server.*", "hide": 0, @@ -289,17 +276,7 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "", "title": "Text options", diff --git a/devenv/dev-dashboards/panel-timeline/timeline-align-endtime.json b/devenv/dev-dashboards/panel-timeline/timeline-align-endtime.json index 8542c7349b6..67fe2391167 100644 --- a/devenv/dev-dashboards/panel-timeline/timeline-align-endtime.json +++ b/devenv/dev-dashboards/panel-timeline/timeline-align-endtime.json @@ -23,8 +23,7 @@ "panels": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -85,8 +84,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"meta\": {\n \"typeVersion\": [\n 0,\n 0\n ]\n },\n \"name\": \"A\",\n \"fields\": [\n {\n \"name\": \"channel\",\n \"config\": {\n \"selector\": \"channel\"\n },\n \"type\": \"string\"\n },\n {\n \"name\": \"name\",\n \"config\": {\n \"selector\": \"name\"\n },\n \"type\": \"string\"\n },\n {\n \"name\": \"starttime\",\n \"config\": {\n \"selector\": \"starttime\"\n },\n \"type\": \"string\"\n },\n {\n \"name\": \"endtime\",\n \"config\": {\n \"selector\": \"endtime\"\n },\n \"type\": \"string\"\n },\n {\n \"name\": \"duration_minutes\",\n \"config\": {\n \"selector\": \"duration_minutes\"\n },\n \"type\": \"number\"\n },\n {\n \"name\": \"state\",\n \"config\": {\n \"selector\": \"state\"\n },\n \"type\": \"string\"\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n \"Channel 1\",\n \"Channel 2\",\n \"Channel 1\",\n \"Channel 2\"\n ],\n [\n \"Event 1\",\n \"Event 2\",\n \"Event 3\",\n \"Event 4\"\n ],\n [\n \"2024-02-28T08:00:00Z\",\n \"2024-02-28T09:00:00Z\",\n \"2024-02-28T11:00:00Z\",\n \"2024-02-28T12:30:00Z\"\n ],\n [\n \"2024-02-28T10:00:00Z\",\n \"2024-02-28T10:30:00Z\",\n \"2024-02-28T14:00:00Z\",\n \"2024-02-28T13:30:00Z\"\n ],\n [\n 120,\n 90,\n 180,\n 60\n ],\n [\n \"OK\",\n \"ERROR\",\n \"NO_DATA\",\n \"WARNING\"\n ]\n ]\n }\n }\n]", "refId": "A", @@ -131,12 +129,7 @@ { "destinationType": "enum", "enumConfig": { - "text": [ - "OK", - "ERROR", - "NO_DATA", - "WARNING" - ] + "text": ["OK", "ERROR", "NO_DATA", "WARNING"] }, "targetField": "state" } @@ -147,9 +140,7 @@ { "id": "partitionByValues", "options": { - "fields": [ - "channel" - ], + "fields": ["channel"], "keepFields": false, "naming": { "asLabels": false @@ -161,8 +152,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -225,8 +215,7 @@ "alias": "Channel 1", "csvContent": "starttime,endtime,state\n1709107200000,1709114400000,OK\n1709118000000,1709128800000,NO_DATA", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -235,8 +224,7 @@ "alias": "Channel 2", "csvContent": "starttime,endtime,state\n1709110800000,1709116200000,ERROR\n1709123400000,1709127000000,WARNING", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_content" @@ -248,12 +236,7 @@ ], "refresh": "", "schemaVersion": 39, - "tags": [ - "gdev", - "panel-tests", - "graph-ng", - "demo" - ], + "tags": ["gdev", "panel-tests", "graph-ng", "demo"], "templating": { "list": [] }, @@ -268,4 +251,4 @@ "uid": "cdf3gkge5reo0f", "version": 4, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-timeline/timeline-align-nulls-retain.json b/devenv/dev-dashboards/panel-timeline/timeline-align-nulls-retain.json index 49907cca771..8d2f86bcdd7 100644 --- a/devenv/dev-dashboards/panel-timeline/timeline-align-nulls-retain.json +++ b/devenv/dev-dashboards/panel-timeline/timeline-align-nulls-retain.json @@ -23,8 +23,7 @@ "panels": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { @@ -176,8 +175,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"Dose\",\n \"meta\": {\n \"executedQueryString\": \"from(bucket: \\\"data\\\")\\r\\n |> range(start: 2023-10-20T05:04:00Z, stop: 2023-10-20T07:22:00Z)\\r\\n |> filter(fn: (r) => r[\\\"_field\\\"] == \\\"FactoryManager_Analogs_DB.A01C02U09.PHS.Dose\\\")\\r\\n |> keep(columns: [\\\"_time\\\", \\\"_value\\\"])\\r\\n |> map(fn: (r) => ({ \\r\\n \\\"Dose\\\": r._value,\\r\\n time: r._time,\\r\\n }))\\r\\n\",\n \"typeVersion\": [\n 0,\n 0\n ]\n },\n \"fields\": [\n {\n \"config\": {},\n \"labels\": {},\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {},\n \"name\": \"Dose\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1697781872300,\n 1697781963303,\n 1697784138453,\n 1697784160451\n ],\n [\n \"Cold Water Dosing Active (150 ltrs)\",\n null,\n \"Hot Water Dosing Active (50 ltrs)\",\n null\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"Mix\",\n \"meta\": {\n \"executedQueryString\": \"from(bucket: \\\"data\\\")\\r\\n |> range(start: 2023-10-20T05:04:00Z, stop: 2023-10-20T07:22:00Z)\\r\\n |> filter(fn: (r) => r[\\\"_field\\\"] == \\\"FactoryManager_Analogs_DB.A01C02U09.PHS.Mix\\\")\\r\\n |> keep(columns: [\\\"_time\\\", \\\"_value\\\"])\\r\\n |> map(fn: (r) => ({ \\r\\n \\\"Mix\\\": r._value,\\r\\n time: r._time,\\r\\n }))\\r\\n\",\n \"typeVersion\": [\n 0,\n 0\n ]\n },\n \"fields\": [\n {\n \"config\": {},\n \"labels\": {},\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {},\n \"name\": \"Mix\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1697778291972,\n 1697778393992,\n 1697778986994,\n 1697786485890\n ],\n [\n \"Running Constant Forward\",\n null,\n \"Running Constant Forward\",\n null\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"Cook\",\n \"meta\": {\n \"executedQueryString\": \"from(bucket: \\\"data\\\")\\r\\n |> range(start: 2023-10-20T05:04:00Z, stop: 2023-10-20T07:22:00Z)\\r\\n |> filter(fn: (r) => r[\\\"_field\\\"] == \\\"FactoryManager_Analogs_DB.A01C02U09.PHS.Cook\\\")\\r\\n |> keep(columns: [\\\"_time\\\", \\\"_value\\\"])\\r\\n |> map(fn: (r) => ({ \\r\\n \\\"Cook\\\": r._value,\\r\\n time: r._time,\\r\\n }))\\r\\n\",\n \"typeVersion\": [\n 0,\n 0\n ]\n },\n \"fields\": [\n {\n \"config\": {},\n \"labels\": {},\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {},\n \"name\": \"Cook\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1697779163986,\n 1697779921045,\n 1697780221094,\n 1697780521111,\n 1697781186192,\n 1697781786291,\n 1697783332361,\n 1697783784395,\n 1697783790397,\n 1697784146478,\n 1697784517471,\n 1697784523487,\n 1697784949480,\n 1697785369505\n ],\n [\n \"Heating to Setpoint (92c)\",\n \"Stage Time Running (5 mins)\",\n null,\n \"Heating to Setpoint (96c)\",\n \"Stage Time Running (10 mins)\",\n null,\n \"Heating to Setpoint (92c)\",\n \"Stage Time Running (0 mins)\",\n null,\n \"Heating to Setpoint (92c)\",\n \"Stage Time Running (0 mins)\",\n null,\n \"CCP in Progress (7 mins)\",\n null\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"Shear\",\n \"meta\": {\n \"executedQueryString\": \"from(bucket: \\\"data\\\")\\r\\n |> range(start: 2023-10-20T05:04:00Z, stop: 2023-10-20T07:22:00Z)\\r\\n |> filter(fn: (r) => r[\\\"_field\\\"] == \\\"FactoryManager_Analogs_DB.A01C02U09.PHS.Shear\\\")\\r\\n |> keep(columns: [\\\"_time\\\", \\\"_value\\\"])\\r\\n |> map(fn: (r) => ({ \\r\\n \\\"Int. Shear\\\": r._value,\\r\\n time: r._time,\\r\\n }))\\r\\n\",\n \"typeVersion\": [\n 0,\n 0\n ]\n },\n \"fields\": [\n {\n \"config\": {},\n \"labels\": {},\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {},\n \"name\": \"Int. Shear\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1697782100330,\n 1697782832342\n ],\n [\n \"Shearing Active (12 mins)\",\n null\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"Recirc\",\n \"meta\": {\n \"executedQueryString\": \"from(bucket: \\\"data\\\")\\r\\n |> range(start: 2023-10-20T05:04:00Z, stop: 2023-10-20T07:22:00Z)\\r\\n |> filter(fn: (r) => r[\\\"_field\\\"] == \\\"FactoryManager_Analogs_DB.A01C02U09.PHS.Recirc\\\")\\r\\n |> keep(columns: [\\\"_time\\\", \\\"_value\\\"])\\r\\n |> map(fn: (r) => ({ \\r\\n \\\"Ext. Shear\\\": r._value,\\r\\n time: r._time,\\r\\n }))\\r\\n\",\n \"typeVersion\": [\n 0,\n 0\n ]\n },\n \"fields\": []\n },\n \"data\": {\n \"values\": []\n }\n },\n {\n \"schema\": {\n \"refId\": \"Transfer\",\n \"meta\": {\n \"executedQueryString\": \"from(bucket: \\\"data\\\")\\r\\n |> range(start: 2023-10-20T05:04:00Z, stop: 2023-10-20T07:22:00Z)\\r\\n |> filter(fn: (r) => r[\\\"_field\\\"] == \\\"FactoryManager_Analogs_DB.A01C02U09.PHS.Transfer\\\")\\r\\n |> keep(columns: [\\\"_time\\\", \\\"_value\\\"])\\r\\n |> map(fn: (r) => ({ \\r\\n \\\"Transfer\\\": r._value,\\r\\n time: r._time,\\r\\n }))\\r\\n\",\n \"typeVersion\": [\n 0,\n 0\n ]\n },\n \"fields\": [\n {\n \"config\": {},\n \"labels\": {},\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {},\n \"name\": \"Transfer\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1697785713869,\n 1697785753879,\n 1697785764887,\n 1697785875872,\n 1697786481929\n ],\n [\n \"Pre-Start Drain\",\n null,\n \"Build Pressure (0.6 Barg)\",\n \"Transfer in progress (0.7 Barg)\",\n \"Wait for pressure dissipation (0.2 Barg)\"\n ]\n ]\n }\n }\n]", "refId": "A", @@ -190,12 +188,7 @@ ], "refresh": "", "schemaVersion": 39, - "tags": [ - "gdev", - "panel-tests", - "graph-ng", - "demo" - ], + "tags": ["gdev", "panel-tests", "graph-ng", "demo"], "templating": { "list": [] }, @@ -210,4 +203,4 @@ "uid": "edf55caay3w8wa", "version": 4, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-timeline/timeline-demo.json b/devenv/dev-dashboards/panel-timeline/timeline-demo.json index e25aa23ce1c..37daf4e71f1 100644 --- a/devenv/dev-dashboards/panel-timeline/timeline-demo.json +++ b/devenv/dev-dashboards/panel-timeline/timeline-demo.json @@ -29,7 +29,7 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -128,7 +128,7 @@ "type": "state-timeline" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -231,7 +231,7 @@ "type": "state-timeline" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "description": "Should show gaps", "fieldConfig": { "defaults": { @@ -334,7 +334,7 @@ "type": "state-timeline" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -428,12 +428,7 @@ ], "refresh": false, "schemaVersion": 36, - "tags": [ - "gdev", - "panel-tests", - "graph-ng", - "demo" - ], + "tags": ["gdev", "panel-tests", "graph-ng", "demo"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-timeline/timeline-modes.json b/devenv/dev-dashboards/panel-timeline/timeline-modes.json index 7c4d9ee05c3..348f6b97b62 100644 --- a/devenv/dev-dashboards/panel-timeline/timeline-modes.json +++ b/devenv/dev-dashboards/panel-timeline/timeline-modes.json @@ -29,7 +29,7 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -89,26 +89,11 @@ }, "lines": 10, "points": [ - [ - 0, - 1616551651000 - ], - [ - 1, - 1616556554000 - ], - [ - 2, - 1616559873000 - ], - [ - 0, - 1616561077000 - ], - [ - 3, - 1616563090000 - ] + [0, 1616551651000], + [1, 1616556554000], + [2, 1616559873000], + [0, 1616561077000], + [3, 1616563090000] ], "pulseWave": { "offCount": 3, @@ -137,22 +122,10 @@ "hide": false, "lines": 10, "points": [ - [ - 4, - 1616555060000 - ], - [ - 5, - 1616560081000 - ], - [ - 4, - 1616562217000 - ], - [ - 5, - 1616565458000 - ] + [4, 1616555060000], + [5, 1616560081000], + [4, 1616562217000], + [5, 1616565458000] ], "pulseWave": { "offCount": 3, @@ -174,31 +147,13 @@ }, { "points": [ - [ - 4, - 1616557148000 - ], - [ - 1616558756000 - ], - [ - 4, - 1616561658000 - ], - [ - 1616562446000 - ], - [ - 4, - 1616564104000 - ], - [ - 1616564548000 - ], - [ - 4, - 1616564871000 - ] + [4, 1616557148000], + [1616558756000], + [4, 1616561658000], + [1616562446000], + [4, 1616564104000], + [1616564548000], + [4, 1616564871000] ], "refId": "C", "scenarioId": "manual_entry" @@ -208,7 +163,7 @@ "type": "state-timeline" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -282,7 +237,7 @@ "type": "state-timeline" }, { - "datasource": { "type": "testdata" }, + "datasource": { "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { "color": { @@ -372,11 +327,7 @@ ], "refresh": false, "schemaVersion": 36, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-timeline/timeline-thresholds-mappings.json b/devenv/dev-dashboards/panel-timeline/timeline-thresholds-mappings.json index d1f0d745117..2a196670bc1 100644 --- a/devenv/dev-dashboards/panel-timeline/timeline-thresholds-mappings.json +++ b/devenv/dev-dashboards/panel-timeline/timeline-thresholds-mappings.json @@ -29,7 +29,7 @@ "panels": [ { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -92,8 +92,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -105,7 +104,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -176,8 +175,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -189,7 +187,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -260,8 +258,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -273,7 +270,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -369,8 +366,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -382,7 +378,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -486,8 +482,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -499,7 +494,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -616,8 +611,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -629,7 +623,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -692,8 +686,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"value\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"int64\",\n \"nullable\": true\n },\n \"config\": {\n \"thresholds\": {\n \"mode\": \"absolute\",\n \"steps\": [\n {\n \"color\": \"green\",\n \"value\": null\n },\n {\n \"color\": \"#EAB839\",\n \"value\": 10\n },\n {\n \"color\": \"red\",\n \"value\": 15\n },\n {\n \"color\": \"#6ED0E0\",\n \"value\": 25\n }\n ]\n }\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1674732835000,\n 1674736435000,\n 1674740035000,\n 1674743635000\n ],\n [\n 5,\n 10,\n 20,\n 30\n ]\n ]\n }\n }\n]", "refId": "A", @@ -705,7 +698,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -768,8 +761,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -777,8 +769,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "max": 30, @@ -808,7 +799,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -891,8 +882,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"value\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"int64\",\n \"nullable\": true\n },\n \"config\": {\n \"thresholds\": {\n \"mode\": \"absolute\",\n \"steps\": [\n {\n \"color\": \"green\",\n \"value\": null\n }\n ]\n }\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1674732835000,\n 1674736435000,\n 1674740035000,\n 1674743635000,\n 1674747235000\n ],\n [\n 5,\n null,\n 20,\n null,\n 40\n ]\n ],\n \"entities\": [null, { \"NaN\": [3]}]\n }\n }\n]", "refId": "A", @@ -904,7 +894,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -976,8 +966,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"value\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"int64\",\n \"nullable\": true\n },\n \"config\": {\n \"thresholds\": {\n \"mode\": \"absolute\",\n \"steps\": [\n {\n \"color\": \"green\",\n \"value\": null\n }\n ]\n }\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1674732835000,\n 1674736435000,\n 1674740035000,\n 1674743635000,\n 1674747235000\n ],\n [\n 5,\n null,\n 20,\n null,\n 40\n ]\n ],\n \"entities\": [null, { \"NaN\": [1]}]\n }\n }\n]", "refId": "A", @@ -989,7 +978,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1071,8 +1060,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"value\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"int64\",\n \"nullable\": true\n },\n \"config\": {\n \"thresholds\": {\n \"mode\": \"absolute\",\n \"steps\": [\n {\n \"color\": \"green\",\n \"value\": null\n }\n ]\n }\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1674732835000,\n 1674736435000,\n 1674740035000,\n 1674743635000,\n 1674747235000,\n 1674750835000,\n 1674754235000,\n 1674757835000\n ],\n [\n null,\n null,\n false,\n true,\n true,\n false,\n true,\n null\n ]\n ],\n \"entities\": [null, { \"NaN\": [0], \"Undefined\": [1]}]\n }\n }\n]", "refId": "A", @@ -1086,12 +1074,7 @@ "preload": false, "refresh": "", "schemaVersion": 41, - "tags": [ - "gdev", - "panel-tests", - "state-timeline", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "state-timeline", "graph-ng"], "templating": { "list": [] }, @@ -1104,4 +1087,4 @@ "title": "StateTimeline - Thresholds & Mappings", "uid": "Kce7z9TVz", "version": 18 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-bars-high-density.json b/devenv/dev-dashboards/panel-timeseries/timeseries-bars-high-density.json index 49e47870c71..158a1750a76 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-bars-high-density.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-bars-high-density.json @@ -1,600 +1,592 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 812, - "links": [], - "liveNow": false, - "panels": [ + "annotations": { + "list": [ { + "builtIn": 1, "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana", + "uid": "-- Grafana --" }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "bars", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 0 - }, - "id": 1, - "maxDataPoints": 500, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "random_walk", - "seriesCount": 1 - } - ], - "title": "Dense (stroke only)", - "type": "timeseries" - }, - { - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "bars", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 0 - }, - "id": 4, - "maxDataPoints": 50, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "random_walk", - "seriesCount": 1 - } - ], - "title": "Normal (stroke only)", - "type": "timeseries" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "bars", - "fillOpacity": 60, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 10 - }, - "id": 2, - "maxDataPoints": 500, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 1, - "refId": "A" - } - ], - "title": "Dense (fill only)", - "type": "timeseries" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "bars", - "fillOpacity": 60, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 10 - }, - "id": 3, - "maxDataPoints": 50, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 4, - "refId": "A" - } - ], - "title": "Normal (fill only)", - "type": "timeseries" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "bars", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 20 - }, - "id": 6, - "maxDataPoints": 500, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 1, - "refId": "A" - } - ], - "title": "Dense (stroke + fill)", - "type": "timeseries" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "bars", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 20 - }, - "id": 5, - "maxDataPoints": 50, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 4, - "refId": "A" - } - ], - "title": "Normal (stroke + fill)", - "type": "timeseries" + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" } - ], - "refresh": "", - "schemaVersion": 39, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], - "templating": { - "list": [] + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 812, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "maxDataPoints": 500, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1 + } + ], + "title": "Dense (stroke only)", + "type": "timeseries" }, - "time": { - "from": "now-6h", - "to": "now" + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 4, + "maxDataPoints": 50, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 1 + } + ], + "title": "Normal (stroke only)", + "type": "timeseries" }, - "timepicker": {}, - "timezone": "", - "title": "Panel Tests - TimeSeries - bars high density (stroke + fill)", - "uid": "c295a76e-79d3-43b3-a688-ef0373224158", - "version": 3, - "weekStart": "" - } \ No newline at end of file + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 60, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 2, + "maxDataPoints": 500, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 1, + "refId": "A" + } + ], + "title": "Dense (fill only)", + "type": "timeseries" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 60, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 3, + "maxDataPoints": 50, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 4, + "refId": "A" + } + ], + "title": "Normal (fill only)", + "type": "timeseries" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 6, + "maxDataPoints": 500, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 1, + "refId": "A" + } + ], + "title": "Dense (stroke + fill)", + "type": "timeseries" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 5, + "maxDataPoints": 50, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 4, + "refId": "A" + } + ], + "title": "Normal (stroke + fill)", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": ["gdev", "panel-tests", "graph-ng"], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Panel Tests - TimeSeries - bars high density (stroke + fill)", + "uid": "c295a76e-79d3-43b3-a688-ef0373224158", + "version": 3, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-by-value-color-schemes.json b/devenv/dev-dashboards/panel-timeseries/timeseries-by-value-color-schemes.json index 11671725397..9271ecea7d9 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-by-value-color-schemes.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-by-value-color-schemes.json @@ -29,8 +29,7 @@ "panels": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { @@ -116,8 +115,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -129,8 +127,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { @@ -216,8 +213,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -229,8 +225,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -315,8 +310,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -328,8 +322,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -410,8 +403,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -521,8 +513,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -608,8 +599,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "max": 40, "min": 0, @@ -931,8 +921,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1021,8 +1010,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "max": 45, "min": 20, @@ -1034,8 +1022,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "max": 20, @@ -1052,11 +1039,7 @@ ], "refresh": "", "schemaVersion": 38, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-formats.json b/devenv/dev-dashboards/panel-timeseries/timeseries-formats.json index 9740e74a16b..bd42409a2f2 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-formats.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-formats.json @@ -79,9 +79,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "frameIndex": 0, @@ -103,128 +101,20 @@ "data": { "values": [ [ - 1677256641358, - 1677257007358, - 1677257373358, - 1677257739358, - 1677258105358, - 1677258471358, - 1677258837358, - 1677259203358, - 1677259569358, - 1677259935358, - 1677260301358, - 1677260667358, - 1677261033358, - 1677261399358, - 1677261765358, - 1677262131358, - 1677262497358, - 1677262863358, - 1677263229358, - 1677263595358, - 1677263961358, - 1677264327358, - 1677264693358, - 1677265059358, - 1677265425358, - 1677265791358, - 1677266157358, - 1677266523358, - 1677266889358, - 1677267255358, - 1677267621358, - 1677267987358, - 1677268353358, - 1677268719358, - 1677269085358, - 1677269451358, - 1677269817358, - 1677270183358, - 1677270549358, - 1677270915358, - 1677271281358, - 1677271647358, - 1677272013358, - 1677272379358, - 1677272745358, - 1677273111358, - 1677273477358, - 1677273843358, - 1677274209358, - 1677274575358, - 1677274941358, - 1677275307358, - 1677275673358, - 1677276039358, - 1677276405358, - 1677276771358, - 1677277137358, - 1677277503358, - 1677277869358, - 1677278235358 + 1677256641358, 1677257007358, 1677257373358, 1677257739358, 1677258105358, 1677258471358, + 1677258837358, 1677259203358, 1677259569358, 1677259935358, 1677260301358, 1677260667358, + 1677261033358, 1677261399358, 1677261765358, 1677262131358, 1677262497358, 1677262863358, + 1677263229358, 1677263595358, 1677263961358, 1677264327358, 1677264693358, 1677265059358, + 1677265425358, 1677265791358, 1677266157358, 1677266523358, 1677266889358, 1677267255358, + 1677267621358, 1677267987358, 1677268353358, 1677268719358, 1677269085358, 1677269451358, + 1677269817358, 1677270183358, 1677270549358, 1677270915358, 1677271281358, 1677271647358, + 1677272013358, 1677272379358, 1677272745358, 1677273111358, 1677273477358, 1677273843358, + 1677274209358, 1677274575358, 1677274941358, 1677275307358, 1677275673358, 1677276039358, + 1677276405358, 1677276771358, 1677277137358, 1677277503358, 1677277869358, 1677278235358 ], [ - 1, - 3, - 5, - 7, - 4, - 6, - 8, - 10, - 1, - 3, - 5, - 7, - 4, - 6, - 8, - 10, - 1, - 3, - 5, - 7, - 4, - 6, - 8, - 10, - 1, - 3, - 5, - 7, - 4, - 6, - 8, - 10, - 1, - 3, - 5, - 7, - 4, - 6, - 8, - 10, - 1, - 3, - 5, - 7, - 4, - 6, - 8, - 10, - 1, - 3, - 5, - 7, - 4, - 6, - 8, - 10, - 1, - 3, - 5, - 7 + 1, 3, 5, 7, 4, 6, 8, 10, 1, 3, 5, 7, 4, 6, 8, 10, 1, 3, 5, 7, 4, 6, 8, 10, 1, 3, 5, 7, 4, 6, 8, 10, + 1, 3, 5, 7, 4, 6, 8, 10, 1, 3, 5, 7, 4, 6, 8, 10, 1, 3, 5, 7, 4, 6, 8, 10, 1, 3, 5, 7 ], [ "a", @@ -394,10 +284,7 @@ ], "meta": { "type": "timeseries-long", - "typeVersion": [ - 0, - 0 - ] + "typeVersion": [0, 0] }, "name": "New Frame", "refId": "A" @@ -407,128 +294,20 @@ "data": { "values": [ [ - 1677256641358, - 1677257007358, - 1677257373358, - 1677257739358, - 1677258105358, - 1677258471358, - 1677258837358, - 1677259203358, - 1677259569358, - 1677259935358, - 1677260301358, - 1677260667358, - 1677261033358, - 1677261399358, - 1677261765358, - 1677262131358, - 1677262497358, - 1677262863358, - 1677263229358, - 1677263595358, - 1677263961358, - 1677264327358, - 1677264693358, - 1677265059358, - 1677265425358, - 1677265791358, - 1677266157358, - 1677266523358, - 1677266889358, - 1677267255358, - 1677267621358, - 1677267987358, - 1677268353358, - 1677268719358, - 1677269085358, - 1677269451358, - 1677269817358, - 1677270183358, - 1677270549358, - 1677270915358, - 1677271281358, - 1677271647358, - 1677272013358, - 1677272379358, - 1677272745358, - 1677273111358, - 1677273477358, - 1677273843358, - 1677274209358, - 1677274575358, - 1677274941358, - 1677275307358, - 1677275673358, - 1677276039358, - 1677276405358, - 1677276771358, - 1677277137358, - 1677277503358, - 1677277869358, - 1677278235358 + 1677256641358, 1677257007358, 1677257373358, 1677257739358, 1677258105358, 1677258471358, + 1677258837358, 1677259203358, 1677259569358, 1677259935358, 1677260301358, 1677260667358, + 1677261033358, 1677261399358, 1677261765358, 1677262131358, 1677262497358, 1677262863358, + 1677263229358, 1677263595358, 1677263961358, 1677264327358, 1677264693358, 1677265059358, + 1677265425358, 1677265791358, 1677266157358, 1677266523358, 1677266889358, 1677267255358, + 1677267621358, 1677267987358, 1677268353358, 1677268719358, 1677269085358, 1677269451358, + 1677269817358, 1677270183358, 1677270549358, 1677270915358, 1677271281358, 1677271647358, + 1677272013358, 1677272379358, 1677272745358, 1677273111358, 1677273477358, 1677273843358, + 1677274209358, 1677274575358, 1677274941358, 1677275307358, 1677275673358, 1677276039358, + 1677276405358, 1677276771358, 1677277137358, 1677277503358, 1677277869358, 1677278235358 ], [ - 1, - 2, - 3, - 2, - 3, - 5, - 6, - 3, - 1, - 2, - 3, - 2, - 3, - 5, - 6, - 3, - 1, - 2, - 3, - 2, - 3, - 5, - 6, - 3, - 1, - 2, - 3, - 2, - 3, - 5, - 6, - 3, - 1, - 2, - 3, - 2, - 3, - 5, - 6, - 3, - 1, - 2, - 3, - 2, - 3, - 5, - 6, - 3, - 1, - 2, - 3, - 2, - 3, - 5, - 6, - 3, - 1, - 2, - 3, - 2 + 1, 2, 3, 2, 3, 5, 6, 3, 1, 2, 3, 2, 3, 5, 6, 3, 1, 2, 3, 2, 3, 5, 6, 3, 1, 2, 3, 2, 3, 5, 6, 3, 1, + 2, 3, 2, 3, 5, 6, 3, 1, 2, 3, 2, 3, 5, 6, 3, 1, 2, 3, 2, 3, 5, 6, 3, 1, 2, 3, 2 ], [ "e", @@ -698,10 +477,7 @@ ], "meta": { "type": "timeseries-long", - "typeVersion": [ - 0, - 0 - ] + "typeVersion": [0, 0] }, "name": "New Frame", "refId": "B" @@ -803,7 +579,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 8, "w": 5, @@ -825,7 +603,9 @@ "type": "text" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -899,8 +679,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-nulls.json b/devenv/dev-dashboards/panel-timeseries/timeseries-nulls.json index a757845daa9..4e8da5c78df 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-nulls.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-nulls.json @@ -29,10 +29,7 @@ { "asDropdown": true, "icon": "external link", - "tags": [ - "gdev", - "graph-ng" - ], + "tags": ["gdev", "graph-ng"], "title": "Graph Tests", "type": "dashboards" } @@ -53,8 +50,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "description": "This visualizes a time series of enumerated values, displaying minimum, maximum, and average values over time to track fluctuations and trends", "fieldConfig": { @@ -167,10 +163,10 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, - "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"name\": \"A\",\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"Min\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"Max\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"Status\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n },\n \"config\": {}\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1686730601000,\n 1686730610000,\n 1686730615000,\n 1686730635000,\n 1686730666000,\n 1686730679000,\n 1686730700000,\n 1686730705000\n ],\n [\n 97.56700088585262,\n 97.51875596242603,\n 97.88367836664669,\n 97.64813860191066,\n 97.46344237059202,\n 97.06932713353162,\n 97.11185691118344,\n 97.4315327939052\n ],\n [\n 96.17381933561288,\n 96.86449303671965,\n 95.5851820937877,\n 96.94658694041154,\n 96.7433590164638,\n 96.74913605945137,\n 95.61938577725707,\n 96.24186355022567\n ],\n [\n 99.69898997339244,\n 98.68620205532211,\n 99.5800005905314,\n 98.2998754185445,\n 98.02873998081307,\n 99.01798295660049,\n 97.95260164072228,\n 98.24811606848421\n ],\n [\n \"ON\",\n \"ON\",\n \"OFF\",\n \"ON\",\n \"OFF\",\n \"ON\",\n \"STANDBY\",\n \"OFF\"\n ]\n ]\n }\n }\n]", "refId": "A", + "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"name\": \"A\",\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"Min\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"Max\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"Status\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n },\n \"config\": {}\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1686730601000,\n 1686730610000,\n 1686730615000,\n 1686730635000,\n 1686730666000,\n 1686730679000,\n 1686730700000,\n 1686730705000\n ],\n [\n 97.56700088585262,\n 97.51875596242603,\n 97.88367836664669,\n 97.64813860191066,\n 97.46344237059202,\n 97.06932713353162,\n 97.11185691118344,\n 97.4315327939052\n ],\n [\n 96.17381933561288,\n 96.86449303671965,\n 95.5851820937877,\n 96.94658694041154,\n 96.7433590164638,\n 96.74913605945137,\n 95.61938577725707,\n 96.24186355022567\n ],\n [\n 99.69898997339244,\n 98.68620205532211,\n 99.5800005905314,\n 98.2998754185445,\n 98.02873998081307,\n 99.01798295660049,\n 97.95260164072228,\n 98.24811606848421\n ],\n [\n \"ON\",\n \"ON\",\n \"OFF\",\n \"ON\",\n \"OFF\",\n \"ON\",\n \"STANDBY\",\n \"OFF\"\n ]\n ]\n }\n }\n]", + "refId": "A", "scenarioId": "raw_frame" } ], @@ -183,11 +179,7 @@ { "destinationType": "enum", "enumConfig": { - "text": [ - "OFF", - "STANDBY", - "ON" - ] + "text": ["OFF", "STANDBY", "ON"] }, "targetField": "Status" } @@ -200,8 +192,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { @@ -288,8 +279,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"name\": \"A\",\n \"fields\": [\n {\n \"name\": \"Time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"Value\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"Min\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"Max\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"config\": {}\n },\n {\n \"name\": \"Status\",\n \"type\": \"string\",\n \"typeInfo\": {\n \"frame\": \"string\",\n \"nullable\": true\n },\n \"config\": {}\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1686730601000,\n 1686730610000,\n 1686730615000,\n 1686730635000,\n 1686730666000,\n 1686730679000,\n 1686730700000,\n 1686730705000\n ],\n [\n 97.56700088585262,\n 97.51875596242603,\n 97.88367836664669,\n 97.64813860191066,\n 97.46344237059202,\n 97.06932713353162,\n 97.11185691118344,\n 97.4315327939052\n ],\n [\n 96.17381933561288,\n 96.86449303671965,\n 95.5851820937877,\n 96.94658694041154,\n 96.7433590164638,\n 96.74913605945137,\n 95.61938577725707,\n 96.24186355022567\n ],\n [\n 99.69898997339244,\n 98.68620205532211,\n 99.5800005905314,\n 98.2998754185445,\n 98.02873998081307,\n 99.01798295660049,\n 97.95260164072228,\n 98.24811606848421\n ],\n [\n \"ON\",\n \"ON\",\n \"OFF\",\n \"ON\",\n \"OFF\",\n \"ON\",\n \"STANDBY\",\n \"OFF\"\n ]\n ]\n }\n }\n]", "refId": "A", @@ -305,11 +295,7 @@ { "destinationType": "enum", "enumConfig": { - "text": [ - "OFF", - "STANDBY", - "ON" - ] + "text": ["OFF", "STANDBY", "ON"] }, "targetField": "Status" } @@ -335,7 +321,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -447,7 +433,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "description": "Series A have no nulls and is not aligned with series B", "fieldConfig": { @@ -569,7 +555,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { @@ -711,7 +697,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -823,7 +809,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "description": "Series A have no nulls and is not aligned with series B", "fieldConfig": { @@ -945,7 +931,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "description": "Should look the same as above\n", "fieldConfig": { @@ -1087,7 +1073,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1235,7 +1221,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1383,7 +1369,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1474,7 +1460,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1556,8 +1542,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1569,7 +1554,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1649,8 +1634,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1662,7 +1646,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1742,8 +1726,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1755,7 +1738,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1835,8 +1818,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1848,7 +1830,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1928,8 +1910,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1941,7 +1922,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2021,8 +2002,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -2034,7 +2014,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2114,8 +2094,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -2127,7 +2106,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2207,8 +2186,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -2220,7 +2198,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2300,8 +2278,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -2326,8 +2303,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2409,8 +2385,7 @@ "alias": "", "csvContent": "time, val\n2023-06-14T08:16:41Z, 20\n2023-06-14T08:16:42Z, 22\n2023-06-14T08:16:43Z, 24\n2023-06-14T08:16:45Z, 10\n2023-06-14T08:16:46Z, 12\n2023-06-14T08:17:46Z, 13\n2023-06-14T08:17:47Z, 14\n2023-06-14T08:17:57Z, 20\n2023-06-14T08:17:58Z, null\n2023-06-14T08:18:00Z, 22\n2023-06-14T08:18:25Z, 22", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -2421,7 +2396,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2503,8 +2478,7 @@ "alias": "", "csvContent": "x, val\n1, 20\n2, 22\n3, 24\n5, 10\n6, 12\n66, 13\n67, 14\n77, 20\n78, null\n80, 22\n105, 22", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -2515,7 +2489,7 @@ }, { "datasource": { - "type": "testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -2592,8 +2566,7 @@ "alias": "", "csvContent": "time, val\n2023-06-14T08:16:41Z, 20\n2023-06-14T08:16:42Z, 22\n2023-06-14T08:16:43Z, 24\n2023-06-14T08:16:45Z, 10\n2023-06-14T08:16:46Z, 12\n2023-06-14T08:17:46Z, 13\n2023-06-14T08:17:47Z, 14\n2023-06-14T08:17:57Z, 20\n2023-06-14T08:17:58Z, null\n2023-06-14T08:18:00Z, 22\n2023-06-14T08:18:25Z, 22", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -3428,15 +3401,7 @@ "preload": false, "refresh": false, "schemaVersion": 41, - "tags": [ - "gdev", - "panel-tests", - "graph-ng", - "timeseries", - "trend", - "state-timeline", - "transform" - ], + "tags": ["gdev", "panel-tests", "graph-ng", "timeseries", "trend", "state-timeline", "transform"], "templating": { "list": [] }, @@ -3449,4 +3414,4 @@ "title": "Panel Tests - Graph NG - Discrete panels", "uid": "8mmCAF1Mz", "version": 1 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-out-of-rage.json b/devenv/dev-dashboards/panel-timeseries/timeseries-out-of-rage.json index 383085604f0..b368963cc47 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-out-of-rage.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-out-of-rage.json @@ -1,512 +1,498 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 1435, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" }, - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "blue", - "mode": "fixed" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 10, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 8, - "x": 0, - "y": 0 - }, - "id": 3, - "maxDataPoints": 6, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "9.4.0-pre", - "targets": [ - { - "csvContent": "Time,Value,Name\n2022-09-01T05:00:00Z,100,Before\n2022-09-01T06:00:00Z,100,Middle", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "B", - "scenarioId": "csv_content" - } - ], - "title": "Before + Middle", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "blue", - "mode": "fixed" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 10, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 8, - "x": 8, - "y": 0 - }, - "id": 2, - "maxDataPoints": 6, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "9.4.0-pre", - "targets": [ - { - "csvContent": "Time,Value,Name\n2022-09-01T05:00:00Z,100,Before\n2022-09-01T07:00:00Z,100,After\n", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "B", - "scenarioId": "csv_content" - } - ], - "title": "Before + After", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "blue", - "mode": "fixed" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 10, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 8, - "x": 16, - "y": 0 - }, - "id": 4, - "maxDataPoints": 6, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "9.4.0-pre", - "targets": [ - { - "csvContent": "Time,Value,Name\n2022-09-01T06:00:00Z,100,Middle\n2022-09-01T07:00:00Z,100,After\n", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "B", - "scenarioId": "csv_content" - } - ], - "title": "Middle + After", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "blue", - "mode": "fixed" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 10, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 9 - }, - "id": 5, - "maxDataPoints": 6, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "9.4.0-pre", - "targets": [ - { - "csvContent": "Time,Value,Name\n2022-09-01T04:00:00Z,100,Before1\n2022-09-01T05:00:00Z,100,Before2\n", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "B", - "scenarioId": "csv_content" - } - ], - "title": "Two points before (show zoom button)", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "blue", - "mode": "fixed" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 10, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 9 - }, - "id": 6, - "maxDataPoints": 6, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "9.4.0-pre", - "targets": [ - { - "csvContent": "Time,Value,Name\n2022-09-01T07:00:00Z,100,After1\n2022-09-01T08:00:00Z,100,After2\n", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "B", - "scenarioId": "csv_content" - } - ], - "title": "Two points after (show zoom button)", - "type": "timeseries" + "type": "dashboard" } - ], - "refresh": false, - "schemaVersion": 37, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], - "templating": { - "list": [] + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1435, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 10, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 3, + "maxDataPoints": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.4.0-pre", + "targets": [ + { + "csvContent": "Time,Value,Name\n2022-09-01T05:00:00Z,100,Before\n2022-09-01T06:00:00Z,100,Middle", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "B", + "scenarioId": "csv_content" + } + ], + "title": "Before + Middle", + "type": "timeseries" }, - "time": { - "from": "now-6h", - "to": "now" + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 10, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 2, + "maxDataPoints": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.4.0-pre", + "targets": [ + { + "csvContent": "Time,Value,Name\n2022-09-01T05:00:00Z,100,Before\n2022-09-01T07:00:00Z,100,After\n", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "B", + "scenarioId": "csv_content" + } + ], + "title": "Before + After", + "type": "timeseries" }, - "timepicker": {}, - "timezone": "", - "title": "Panel Tests - Timeseries - Out of range", - "uid": "pqnrfd4Vz", - "version": 1, - "weekStart": "" - } + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 10, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 4, + "maxDataPoints": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.4.0-pre", + "targets": [ + { + "csvContent": "Time,Value,Name\n2022-09-01T06:00:00Z,100,Middle\n2022-09-01T07:00:00Z,100,After\n", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "B", + "scenarioId": "csv_content" + } + ], + "title": "Middle + After", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 10, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 5, + "maxDataPoints": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.4.0-pre", + "targets": [ + { + "csvContent": "Time,Value,Name\n2022-09-01T04:00:00Z,100,Before1\n2022-09-01T05:00:00Z,100,Before2\n", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "B", + "scenarioId": "csv_content" + } + ], + "title": "Two points before (show zoom button)", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "blue", + "mode": "fixed" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 10, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 6, + "maxDataPoints": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.4.0-pre", + "targets": [ + { + "csvContent": "Time,Value,Name\n2022-09-01T07:00:00Z,100,After1\n2022-09-01T08:00:00Z,100,After2\n", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "B", + "scenarioId": "csv_content" + } + ], + "title": "Two points after (show zoom button)", + "type": "timeseries" + } + ], + "refresh": false, + "schemaVersion": 37, + "tags": ["gdev", "panel-tests", "graph-ng"], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Panel Tests - Timeseries - Out of range", + "uid": "pqnrfd4Vz", + "version": 1, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-shared-tooltip-cursor-position.json b/devenv/dev-dashboards/panel-timeseries/timeseries-shared-tooltip-cursor-position.json index f7fb3dc6455..74b3f2bae16 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-shared-tooltip-cursor-position.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-shared-tooltip-cursor-position.json @@ -540,11 +540,7 @@ ], "refresh": false, "schemaVersion": 28, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-stacking.json b/devenv/dev-dashboards/panel-timeseries/timeseries-stacking.json index ed99cd6c08c..2b4f64dce05 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-stacking.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-stacking.json @@ -879,11 +879,7 @@ } ], "schemaVersion": 27, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-stacking2.json b/devenv/dev-dashboards/panel-timeseries/timeseries-stacking2.json index 18588cd8830..64c4a21d1ad 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-stacking2.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-stacking2.json @@ -28,7 +28,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "", "fieldConfig": { "defaults": { @@ -101,8 +103,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -110,8 +111,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_metric_values", @@ -119,8 +119,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "csv_metric_values", @@ -305,7 +304,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "", "fieldConfig": { "defaults": { @@ -379,8 +380,7 @@ { "alias": "+100", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "A", @@ -390,8 +390,7 @@ { "alias": "+50", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_metric_values", @@ -400,8 +399,7 @@ { "alias": "+25", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "csv_metric_values", @@ -410,8 +408,7 @@ { "alias": "-50", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "csv_metric_values", @@ -420,8 +417,7 @@ { "alias": "-100", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "E", "scenarioId": "csv_metric_values", @@ -606,7 +602,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "", "fieldConfig": { "defaults": { @@ -693,8 +691,7 @@ { "alias": "NegY", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "csv_metric_values", @@ -702,8 +699,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -711,8 +707,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_metric_values", @@ -721,8 +716,7 @@ { "alias": "Neg", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "csv_metric_values", @@ -933,7 +927,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "", "fieldConfig": { "defaults": { @@ -984,9 +980,7 @@ "barWidth": 1, "groupWidth": 0.89, "legend": { - "calcs": [ - "max" - ], + "calcs": ["max"], "displayMode": "hidden", "placement": "right" }, @@ -1005,8 +999,7 @@ { "csvContent": "Name,Stat1,Stat2,Stat3,Stat4,Stat5,Stat6,Stat7,Stat8\nA, 10, 15,8,3,4,12,14,1\nB, 19, 5,8,3,4,12,14,6\nC, 15, 5,8,3,4,10,4,6\n", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -1070,9 +1063,7 @@ "barWidth": 1, "groupWidth": 0.89, "legend": { - "calcs": [ - "max" - ], + "calcs": ["max"], "displayMode": "hidden", "placement": "right" }, @@ -1155,9 +1146,7 @@ "barWidth": 1, "groupWidth": 0.89, "legend": { - "calcs": [ - "max" - ], + "calcs": ["max"], "displayMode": "hidden", "placement": "right" }, @@ -1486,7 +1475,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1579,8 +1570,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1588,8 +1578,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_metric_values", @@ -1597,8 +1586,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "csv_metric_values", @@ -1606,8 +1594,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "csv_metric_values", @@ -1833,7 +1820,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "", "fieldConfig": { "defaults": { @@ -1907,8 +1896,7 @@ { "alias": "+100", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "A", @@ -1918,8 +1906,7 @@ { "alias": "+50", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_metric_values", @@ -1928,8 +1915,7 @@ { "alias": "+25", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "csv_metric_values", @@ -1938,8 +1924,7 @@ { "alias": "-50", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "csv_metric_values", @@ -1948,8 +1933,7 @@ { "alias": "-100", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "E", "scenarioId": "csv_metric_values", @@ -2047,7 +2031,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "", "fieldConfig": { "defaults": { @@ -2133,8 +2119,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "A", @@ -2144,8 +2129,7 @@ { "alias": "NegY", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_metric_values", @@ -2156,7 +2140,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -2228,8 +2214,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -2237,8 +2222,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_metric_values", @@ -2246,8 +2230,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "csv_metric_values", @@ -2255,8 +2238,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "csv_metric_values", @@ -2474,7 +2456,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -2584,8 +2568,7 @@ { "csvContent": "\"Time\",\"Sum daily.cost_per_kwh\"\n1639612800000,\n1639872000000,0\n1639958400000,272\n1640044800000,272\n1640131200000,327\n1640217600000,290\n1640304000000,286\n1640390400000,256\n1640476800000,397\n1640563200000,295\n1640649600000,310\n1640736000000,224\n1640822400000,291\n1640908800000,265\n1640995200000,256\n1641081600000,399\n1641168000000,471\n1641254400000,325\n1641340800000,363\n1641427200000,375\n1641513600000,365\n1641600000000,492\n1641686400000,409\n1641772800000,371\n1641859200000,448\n1641945600000,372\n1642032000000,0\n1642118400000,0\n1642204800000,0\n1642291200000,0\n1642377600000,0\n1642464000000,0\n\n", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "A", @@ -2594,8 +2577,7 @@ { "csvContent": "\"Time\",\"Sum morning.cost_per_kwh\",\"Sum afternoon.cost_per_kwh\",\"Sum evening.cost_per_kwh\",\"Sum night.cost_per_kwh\",\"Sum late.cost_per_kwh\"\n1639612800000,0,0,0,0,0\n1639872000000,,,,,\n1639958400000,,,,,\n1640044800000,,,,,\n1640131200000,,,,,\n1640217600000,32,28,62,63,32\n1640304000000,,,,,\n1640390400000,,,,,\n1640476800000,,,,,\n1640563200000,,,,,\n1640649600000,,,,,\n1640736000000,,,,,\n1640822400000,47,53,68,96,45\n1640908800000,,,,,\n1640995200000,,,,,\n1641081600000,,,,,\n1641168000000,,,,,\n1641254400000,,,,,\n1641340800000,,,,,\n1641427200000,112,130,147,152,115\n1641513600000,,,,,\n1641600000000,,,,,\n1641686400000,,,,,\n1641772800000,,,,,\n1641859200000,,,,,\n1641945600000,,,,,\n1642032000000,0,0,0,0,0\n1642118400000,,,,,\n1642204800000,,,,,\n1642291200000,,,,,\n1642377600000,,,,,\n1642464000000,,,,,\n\n", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "B", @@ -2607,7 +2589,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -2717,8 +2701,7 @@ { "csvContent": "\"Time\",\"Sum daily.cost_per_kwh\"\n1639612800000,\n1639872000000,0\n1639958400000,272\n1640044800000,272\n1640131200000,327\n1640217600000,290\n1640304000000,286\n1640390400000,256\n1640476800000,397\n1640563200000,295\n1640649600000,310\n1640736000000,224\n1640822400000,291\n1640908800000,265\n1640995200000,256\n1641081600000,399\n1641168000000,471\n1641254400000,325\n1641340800000,363\n1641427200000,375\n1641513600000,365\n1641600000000,492\n1641686400000,409\n1641772800000,371\n1641859200000,448\n1641945600000,372\n1642032000000,0\n1642118400000,0\n1642204800000,0\n1642291200000,0\n1642377600000,0\n1642464000000,0\n\n", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "A", @@ -2727,8 +2710,7 @@ { "csvContent": "\"Time\",\"Sum morning.cost_per_kwh\",\"Sum afternoon.cost_per_kwh\",\"Sum evening.cost_per_kwh\",\"Sum night.cost_per_kwh\",\"Sum late.cost_per_kwh\"\n1639612800000,0,0,0,0,0\n1639872000000,,,,,\n1639958400000,,,,,\n1640044800000,,,,,\n1640131200000,,,,,\n1640217600000,32,28,62,63,32\n1640304000000,,,,,\n1640390400000,,,,,\n1640476800000,,,,,\n1640563200000,,,,,\n1640649600000,,,,,\n1640736000000,,,,,\n1640822400000,47,53,68,96,45\n1640908800000,,,,,\n1640995200000,,,,,\n1641081600000,,,,,\n1641168000000,,,,,\n1641254400000,,,,,\n1641340800000,,,,,\n1641427200000,112,130,147,152,115\n1641513600000,,,,,\n1641600000000,,,,,\n1641686400000,,,,,\n1641772800000,,,,,\n1641859200000,,,,,\n1641945600000,,,,,\n1642032000000,0,0,0,0,0\n1642118400000,,,,,\n1642204800000,,,,,\n1642291200000,,,,,\n1642377600000,,,,,\n1642464000000,,,,,\n\n", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "B", @@ -2740,7 +2722,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -2850,8 +2834,7 @@ { "csvContent": "\"Time\",\"Sum daily.cost_per_kwh\"\n1639612800000,\n1639872000000,0\n1639958400000,272\n1640044800000,272\n1640131200000,327\n1640217600000,290\n1640304000000,286\n1640390400000,256\n1640476800000,397\n1640563200000,295\n1640649600000,310\n1640736000000,224\n1640822400000,291\n1640908800000,265\n1640995200000,256\n1641081600000,399\n1641168000000,471\n1641254400000,325\n1641340800000,363\n1641427200000,375\n1641513600000,365\n1641600000000,492\n1641686400000,409\n1641772800000,371\n1641859200000,448\n1641945600000,372\n1642032000000,0\n1642118400000,0\n1642204800000,0\n1642291200000,0\n1642377600000,0\n1642464000000,0\n\n", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "A", @@ -2860,8 +2843,7 @@ { "csvContent": "\"Time\",\"Sum morning.cost_per_kwh\",\"Sum afternoon.cost_per_kwh\",\"Sum evening.cost_per_kwh\",\"Sum night.cost_per_kwh\",\"Sum late.cost_per_kwh\"\n1639612800000,0,0,0,0,0\n1639872000000,,,,,\n1639958400000,,,,,\n1640044800000,,,,,\n1640131200000,,,,,\n1640217600000,32,28,62,63,32\n1640304000000,,,,,\n1640390400000,,,,,\n1640476800000,,,,,\n1640563200000,,,,,\n1640649600000,,,,,\n1640736000000,,,,,\n1640822400000,47,53,68,96,45\n1640908800000,,,,,\n1640995200000,,,,,\n1641081600000,,,,,\n1641168000000,,,,,\n1641254400000,,,,,\n1641340800000,,,,,\n1641427200000,112,130,147,152,115\n1641513600000,,,,,\n1641600000000,,,,,\n1641686400000,,,,,\n1641772800000,,,,,\n1641859200000,,,,,\n1641945600000,,,,,\n1642032000000,0,0,0,0,0\n1642118400000,,,,,\n1642204800000,,,,,\n1642291200000,,,,,\n1642377600000,,,,,\n1642464000000,,,,,\n\n", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "B", @@ -2873,7 +2855,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -2945,8 +2929,7 @@ { "csvContent": "time,Label 1\n2021-12-20T05:09:05.832Z,1000", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -2954,8 +2937,7 @@ { "csvContent": "time,Label 10\n2021-12-18T04:54:45.888Z,2500\n2021-12-20T05:09:05.832Z,600\n2021-12-22T05:23:25.776Z,350\n2022-01-03T06:49:25.440Z,500", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_content" @@ -2963,8 +2945,7 @@ { "csvContent": "time,Label 11\n2021-12-18T04:54:45.888Z,28000\n2021-12-20T05:09:05.832Z,3100\n2021-12-22T05:23:25.776Z,36000\n2021-12-24T05:37:45.720Z,2800", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "csv_content" @@ -2972,8 +2953,7 @@ { "csvContent": "time,Label 12\n2021-12-20T05:09:05.832Z,255\n2021-12-24T05:37:45.720Z,651\n2021-12-26T05:52:05.664Z,50", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "csv_content" @@ -2981,8 +2961,7 @@ { "csvContent": "time,Label 13\n2021-12-18T04:54:45.888Z,5000\n2021-12-20T05:09:05.832Z,1231", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "E", "scenarioId": "csv_content" @@ -2990,8 +2969,7 @@ { "csvContent": "time,Label 14\n2021-12-14T04:26:06.000Z,122\n2021-12-16T04:40:25.944Z,123\n2021-12-18T04:54:45.888Z,12345\n2021-12-20T05:09:05.832Z,23456\n2021-12-22T05:23:25.776Z,34567\n2021-12-24T05:37:45.720Z,12345\n2021-12-26T05:52:05.664Z,8000\n2021-12-28T06:06:25.608Z,3000\n2021-12-30T06:20:45.552Z,1000\n2022-01-01T06:35:05.496Z,21", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "csv_content" @@ -2999,8 +2977,7 @@ { "csvContent": "time,Label 15\n2022-01-07T07:18:05.328Z,20", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "G", "scenarioId": "csv_content" @@ -3008,8 +2985,7 @@ { "csvContent": "time,Label 16\n2022-01-03T06:49:25.440Z,210\n2022-01-07T07:18:05.328Z,321", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "H", "scenarioId": "csv_content" @@ -3017,8 +2993,7 @@ { "csvContent": "time,Label 17\n2021-12-28T06:06:25.608Z,210\n2022-01-07T07:18:05.328Z,210", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "I", "scenarioId": "csv_content" @@ -3026,8 +3001,7 @@ { "csvContent": "time,Label 18\n2021-12-18T04:54:45.888Z,250\n2021-12-20T05:09:05.832Z,852\n2021-12-22T05:23:25.776Z,1234\n2021-12-26T05:52:05.664Z,321\n2021-12-30T06:20:45.552Z,432", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "J", "scenarioId": "csv_content" @@ -3035,8 +3009,7 @@ { "csvContent": "time,Label 2\n2021-12-24T05:37:45.720Z,543\n2021-12-26T05:52:05.664Z,18000\n2021-12-28T06:06:25.608Z,17000\n2021-12-30T06:20:45.552Z,12000\n2022-01-01T06:35:05.496Z,8500\n2022-01-03T06:49:25.440Z,8000\n2022-01-05T07:03:45.384Z,5000\n2022-01-07T07:18:05.328Z,3000\n2022-01-09T07:32:25.272Z,2500\n2022-01-11T07:46:45.216Z,2200\n2022-01-13T08:01:05.160Z,3000\n2022-01-15T08:15:25.104Z,1520\n2022-01-17T08:29:45.048Z,665.35", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "K", "scenarioId": "csv_content" @@ -3044,8 +3017,7 @@ { "csvContent": "time,Label 3\n2022-01-11T07:46:45.216Z,800", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "L", "scenarioId": "csv_content" @@ -3053,8 +3025,7 @@ { "csvContent": "time,Label 4\n2021-12-22T05:23:25.776Z,14173\n2021-12-24T05:37:45.720Z,14805\n2021-12-26T05:52:05.664Z,5600\n2021-12-28T06:06:25.608Z,5950\n2021-12-30T06:20:45.552Z,775\n2022-01-01T06:35:05.496Z,725\n2022-01-03T06:49:25.440Z,1450\n2022-01-05T07:03:45.384Z,3175\n2022-01-07T07:18:05.328Z,1850\n2022-01-09T07:32:25.272Z,1025\n2022-01-11T07:46:45.216Z,2700\n2022-01-13T08:01:05.160Z,4825\n2022-01-15T08:15:25.104Z,3600", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "M", "scenarioId": "csv_content" @@ -3062,8 +3033,7 @@ { "csvContent": "time,Label 5\n2022-01-15T08:15:25.104Z,1675", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "N", "scenarioId": "csv_content" @@ -3071,8 +3041,7 @@ { "csvContent": "time,Label 6\n2021-12-22T05:23:25.776Z,433.16", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "O", "scenarioId": "csv_content" @@ -3080,8 +3049,7 @@ { "csvContent": "time,Label 7\n2021-12-24T05:37:45.720Z,41250\n2021-12-26T05:52:05.664Z,45150\n2021-12-28T06:06:25.608Z,45870.16\n2021-12-30T06:20:45.552Z,38728.17\n2022-01-01T06:35:05.496Z,39931.77\n2022-01-03T06:49:25.440Z,39831.8\n2022-01-05T07:03:45.384Z,38252.06\n2022-01-07T07:18:05.328Z,44332.92\n2022-01-09T07:32:25.272Z,51359.74\n2022-01-11T07:46:45.216Z,56155.84\n2022-01-13T08:01:05.160Z,55676.92\n2022-01-15T08:15:25.104Z,55323.84\n2022-01-17T08:29:45.048Z,13830.96", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "P", "scenarioId": "csv_content" @@ -3089,8 +3057,7 @@ { "csvContent": "time,Label 8\n2021-12-30T06:20:45.552Z,52.89\n2022-01-01T06:35:05.496Z,569.57", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "Q", "scenarioId": "csv_content" @@ -3098,8 +3065,7 @@ { "csvContent": "time,Label 9\n2022-01-01T06:35:05.496Z,2140.34\n2022-01-03T06:49:25.440Z,4074.92\n2022-01-05T07:03:45.384Z,1557.85\n2022-01-07T07:18:05.328Z,1097.74\n2022-01-09T07:32:25.272Z,692.06\n2022-01-11T07:46:45.216Z,758.67\n2022-01-13T08:01:05.160Z,957.56\n2022-01-15T08:15:25.104Z,1470.49\n2022-01-17T08:29:45.048Z,198.18", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "R", "scenarioId": "csv_content" @@ -3109,7 +3075,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -3181,8 +3149,7 @@ { "csvContent": "time,Label 1\n2021-12-20T05:09:05.832Z,1000", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -3190,8 +3157,7 @@ { "csvContent": "time,Label 10\n2021-12-18T04:54:45.888Z,2500\n2021-12-20T05:09:05.832Z,600\n2021-12-22T05:23:25.776Z,350\n2022-01-03T06:49:25.440Z,500", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_content" @@ -3199,8 +3165,7 @@ { "csvContent": "time,Label 11\n2021-12-18T04:54:45.888Z,28000\n2021-12-20T05:09:05.832Z,3100\n2021-12-22T05:23:25.776Z,36000\n2021-12-24T05:37:45.720Z,2800", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "csv_content" @@ -3208,8 +3173,7 @@ { "csvContent": "time,Label 12\n2021-12-20T05:09:05.832Z,255\n2021-12-24T05:37:45.720Z,651\n2021-12-26T05:52:05.664Z,50", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "csv_content" @@ -3217,8 +3181,7 @@ { "csvContent": "time,Label 13\n2021-12-18T04:54:45.888Z,5000\n2021-12-20T05:09:05.832Z,1231", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "E", "scenarioId": "csv_content" @@ -3226,8 +3189,7 @@ { "csvContent": "time,Label 14\n2021-12-14T04:26:06.000Z,122\n2021-12-16T04:40:25.944Z,123\n2021-12-18T04:54:45.888Z,12345\n2021-12-20T05:09:05.832Z,23456\n2021-12-22T05:23:25.776Z,34567\n2021-12-24T05:37:45.720Z,12345\n2021-12-26T05:52:05.664Z,8000\n2021-12-28T06:06:25.608Z,3000\n2021-12-30T06:20:45.552Z,1000\n2022-01-01T06:35:05.496Z,21", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "F", "scenarioId": "csv_content" @@ -3235,8 +3197,7 @@ { "csvContent": "time,Label 15\n2022-01-07T07:18:05.328Z,20", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "G", "scenarioId": "csv_content" @@ -3244,8 +3205,7 @@ { "csvContent": "time,Label 16\n2022-01-03T06:49:25.440Z,210\n2022-01-07T07:18:05.328Z,321", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "H", "scenarioId": "csv_content" @@ -3253,8 +3213,7 @@ { "csvContent": "time,Label 17\n2021-12-28T06:06:25.608Z,210\n2022-01-07T07:18:05.328Z,210", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "I", "scenarioId": "csv_content" @@ -3262,8 +3221,7 @@ { "csvContent": "time,Label 18\n2021-12-18T04:54:45.888Z,250\n2021-12-20T05:09:05.832Z,852\n2021-12-22T05:23:25.776Z,1234\n2021-12-26T05:52:05.664Z,321\n2021-12-30T06:20:45.552Z,432", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "J", "scenarioId": "csv_content" @@ -3271,8 +3229,7 @@ { "csvContent": "time,Label 2\n2021-12-24T05:37:45.720Z,543\n2021-12-26T05:52:05.664Z,18000\n2021-12-28T06:06:25.608Z,17000\n2021-12-30T06:20:45.552Z,12000\n2022-01-01T06:35:05.496Z,8500\n2022-01-03T06:49:25.440Z,8000\n2022-01-05T07:03:45.384Z,5000\n2022-01-07T07:18:05.328Z,3000\n2022-01-09T07:32:25.272Z,2500\n2022-01-11T07:46:45.216Z,2200\n2022-01-13T08:01:05.160Z,3000\n2022-01-15T08:15:25.104Z,1520\n2022-01-17T08:29:45.048Z,665.35", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "K", "scenarioId": "csv_content" @@ -3280,8 +3237,7 @@ { "csvContent": "time,Label 3\n2022-01-11T07:46:45.216Z,800", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "L", "scenarioId": "csv_content" @@ -3289,8 +3245,7 @@ { "csvContent": "time,Label 4\n2021-12-22T05:23:25.776Z,14173\n2021-12-24T05:37:45.720Z,14805\n2021-12-26T05:52:05.664Z,5600\n2021-12-28T06:06:25.608Z,5950\n2021-12-30T06:20:45.552Z,775\n2022-01-01T06:35:05.496Z,725\n2022-01-03T06:49:25.440Z,1450\n2022-01-05T07:03:45.384Z,3175\n2022-01-07T07:18:05.328Z,1850\n2022-01-09T07:32:25.272Z,1025\n2022-01-11T07:46:45.216Z,2700\n2022-01-13T08:01:05.160Z,4825\n2022-01-15T08:15:25.104Z,3600", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "M", "scenarioId": "csv_content" @@ -3298,8 +3253,7 @@ { "csvContent": "time,Label 5\n2022-01-15T08:15:25.104Z,1675", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "N", "scenarioId": "csv_content" @@ -3307,8 +3261,7 @@ { "csvContent": "time,Label 6\n2021-12-22T05:23:25.776Z,433.16", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "O", "scenarioId": "csv_content" @@ -3316,8 +3269,7 @@ { "csvContent": "time,Label 7\n2021-12-24T05:37:45.720Z,41250\n2021-12-26T05:52:05.664Z,45150\n2021-12-28T06:06:25.608Z,45870.16\n2021-12-30T06:20:45.552Z,38728.17\n2022-01-01T06:35:05.496Z,39931.77\n2022-01-03T06:49:25.440Z,39831.8\n2022-01-05T07:03:45.384Z,38252.06\n2022-01-07T07:18:05.328Z,44332.92\n2022-01-09T07:32:25.272Z,51359.74\n2022-01-11T07:46:45.216Z,56155.84\n2022-01-13T08:01:05.160Z,55676.92\n2022-01-15T08:15:25.104Z,55323.84\n2022-01-17T08:29:45.048Z,13830.96", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "P", "scenarioId": "csv_content" @@ -3325,8 +3277,7 @@ { "csvContent": "time,Label 8\n2021-12-30T06:20:45.552Z,52.89\n2022-01-01T06:35:05.496Z,569.57", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "Q", "scenarioId": "csv_content" @@ -3334,8 +3285,7 @@ { "csvContent": "time,Label 9\n2022-01-01T06:35:05.496Z,2140.34\n2022-01-03T06:49:25.440Z,4074.92\n2022-01-05T07:03:45.384Z,1557.85\n2022-01-07T07:18:05.328Z,1097.74\n2022-01-09T07:32:25.272Z,692.06\n2022-01-11T07:46:45.216Z,758.67\n2022-01-13T08:01:05.160Z,957.56\n2022-01-15T08:15:25.104Z,1470.49\n2022-01-17T08:29:45.048Z,198.18", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "R", "scenarioId": "csv_content" @@ -3345,7 +3295,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -3414,8 +3366,7 @@ { "csvContent": "name, number, number2, number3, number4\nName1, 40, 5, 20, 10\nName2, 0,0,0,0\nName3, 6, 3, 5, 1\nName4, 1, 1, 1, 2", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -3427,11 +3378,7 @@ ], "refresh": false, "schemaVersion": 36, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-thresholds.json b/devenv/dev-dashboards/panel-timeseries/timeseries-thresholds.json index da583b7d232..4275255778f 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-thresholds.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-thresholds.json @@ -1228,11 +1228,7 @@ } ], "schemaVersion": 29, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-y-ticks-zero-decimals.json b/devenv/dev-dashboards/panel-timeseries/timeseries-y-ticks-zero-decimals.json index 1c4e7466b64..cd41cd73e26 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-y-ticks-zero-decimals.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-y-ticks-zero-decimals.json @@ -1,845 +1,828 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 339, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 32, - "w": 4, - "x": 0, - "y": 0 - }, - "id": 2, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "1,2.3" - } - ], - "title": "Panel Title", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 0, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 32, - "w": 4, - "x": 4, - "y": 0 - }, - "id": 5, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "1,2.3" - } - ], - "title": "Panel Title", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 17, - "w": 4, - "x": 8, - "y": 0 - }, - "id": 6, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "1,2.3" - } - ], - "title": "Panel Title", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 0, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 17, - "w": 4, - "x": 12, - "y": 0 - }, - "id": 3, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "1,2.3" - } - ], - "title": "Panel Title", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 4, - "x": 16, - "y": 0 - }, - "id": 7, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "1,2.3" - } - ], - "title": "Panel Title", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 0, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 4, - "x": 20, - "y": 0 - }, - "id": 4, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "1,2.3" - } - ], - "title": "Panel Title", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 22, - "w": 4, - "x": 16, - "y": 10 - }, - "id": 8, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "1,2.3" - } - ], - "title": "Panel Title", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 0, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 22, - "w": 4, - "x": 20, - "y": 10 - }, - "id": 9, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "1,2.3" - } - ], - "title": "Panel Title", - "type": "timeseries" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 0, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 15, - "w": 8, - "x": 8, - "y": 17 - }, - "id": 11, - "maxDataPoints": 100, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "title": "Panel Title", - "type": "timeseries" + "type": "dashboard" } - ], - "schemaVersion": 37, - "tags": ["gdev", "panel-tests", "graph-ng"], - "templating": { - "list": [] + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 339, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 32, + "w": 4, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,2.3" + } + ], + "title": "Panel Title", + "type": "timeseries" }, - "time": { - "from": "now-6h", - "to": "now" + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 32, + "w": 4, + "x": 4, + "y": 0 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,2.3" + } + ], + "title": "Panel Title", + "type": "timeseries" }, - "timepicker": {}, - "timezone": "", - "title": "Zero Decimals Y Ticks", - "uid": "kGvJCmGVz", - "version": 7, - "weekStart": "" - } + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 17, + "w": 4, + "x": 8, + "y": 0 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,2.3" + } + ], + "title": "Panel Title", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 17, + "w": 4, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,2.3" + } + ], + "title": "Panel Title", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 4, + "x": 16, + "y": 0 + }, + "id": 7, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,2.3" + } + ], + "title": "Panel Title", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 4, + "x": 20, + "y": 0 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,2.3" + } + ], + "title": "Panel Title", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 22, + "w": 4, + "x": 16, + "y": 10 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,2.3" + } + ], + "title": "Panel Title", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 22, + "w": 4, + "x": 20, + "y": 10 + }, + "id": 9, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,2.3" + } + ], + "title": "Panel Title", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 15, + "w": 8, + "x": 8, + "y": 17 + }, + "id": 11, + "maxDataPoints": 100, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "title": "Panel Title", + "type": "timeseries" + } + ], + "schemaVersion": 37, + "tags": ["gdev", "panel-tests", "graph-ng"], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Zero Decimals Y Ticks", + "uid": "kGvJCmGVz", + "version": 7, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-yaxis-ticks.json b/devenv/dev-dashboards/panel-timeseries/timeseries-yaxis-ticks.json index 5cf44cae03f..a877bcc5342 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-yaxis-ticks.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-yaxis-ticks.json @@ -28,10 +28,7 @@ { "asDropdown": true, "icon": "external link", - "tags": [ - "gdev", - "graph-ng" - ], + "tags": ["gdev", "graph-ng"], "title": "Graph Tests", "type": "dashboards" } @@ -39,7 +36,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -118,8 +117,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -130,7 +128,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -209,8 +209,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -221,7 +220,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -300,8 +301,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -312,7 +312,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -391,8 +393,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -403,7 +404,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -482,8 +485,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -494,7 +496,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -573,8 +577,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -585,7 +588,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "", "fieldConfig": { "defaults": { @@ -665,8 +670,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -677,7 +681,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "", "fieldConfig": { "defaults": { @@ -757,8 +763,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -769,7 +774,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -848,8 +855,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -860,7 +866,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -935,8 +943,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -947,7 +954,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1022,8 +1031,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1034,7 +1042,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "description": "", "fieldConfig": { "defaults": { @@ -1110,8 +1120,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1122,7 +1131,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1199,8 +1210,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1211,7 +1221,9 @@ "type": "timeseries" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1288,8 +1300,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_metric_values", @@ -1302,11 +1313,7 @@ ], "refresh": "", "schemaVersion": 38, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, @@ -1315,18 +1322,7 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "", "title": "Panel Tests - Graph NG - Y axis ticks", diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries.json b/devenv/dev-dashboards/panel-timeseries/timeseries.json index 38185603968..14d824a3bcd 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries.json @@ -2040,7 +2040,9 @@ "type": "row" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -2177,7 +2179,9 @@ "type": "timeseries" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -2328,7 +2332,9 @@ "type": "timeseries" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -2478,7 +2484,9 @@ "type": "timeseries" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -2956,7 +2964,9 @@ "type": "timeseries" }, { - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { diff --git a/devenv/dev-dashboards/panel-trend/trend_example.json b/devenv/dev-dashboards/panel-trend/trend_example.json index 72d9b9b7566..9961b07fc92 100644 --- a/devenv/dev-dashboards/panel-trend/trend_example.json +++ b/devenv/dev-dashboards/panel-trend/trend_example.json @@ -22,7 +22,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -145,8 +147,7 @@ { "csvContent": "Speed (RPM),Torque (NM),Power (kW)\n0,,\n500,,\n800,180,20\n1500,215,40\n2000,227,50\n2500,230,62\n3000,233,75\n3500,236,86\n4000,234,92\n4500,230,100\n5000,220,107\n5500,210,110\n6000,178,106\n6500,120,92\n7000,,\n", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -158,12 +159,7 @@ ], "refresh": "", "schemaVersion": 38, - "tags": [ - "gdev", - "panel-tests", - "graph-ng", - "trend" - ], + "tags": ["gdev", "panel-tests", "graph-ng", "trend"], "templating": { "list": [] }, @@ -177,4 +173,4 @@ "uid": "b36b5576-2e3d-4b0c-8dce-e79514d99345", "version": 4, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-xychart/xychart-demo.json b/devenv/dev-dashboards/panel-xychart/xychart-demo.json index bad99f227cf..f43dc37ba36 100644 --- a/devenv/dev-dashboards/panel-xychart/xychart-demo.json +++ b/devenv/dev-dashboards/panel-xychart/xychart-demo.json @@ -29,8 +29,7 @@ "panels": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -165,8 +164,7 @@ { "csvFileName": "automobiles.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -177,9 +175,7 @@ { "id": "partitionByValues", "options": { - "fields": [ - "Origin" - ] + "fields": ["Origin"] } } ], @@ -187,8 +183,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -282,9 +277,7 @@ "showLegend": true }, "mapping": "auto", - "series": [ - {} - ], + "series": [{}], "tooltip": { "hideZeros": false, "mode": "single", @@ -296,8 +289,7 @@ { "csvFileName": "weight_height.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -308,9 +300,7 @@ { "id": "partitionByValues", "options": { - "fields": [ - "Gender" - ] + "fields": ["Gender"] } } ], @@ -318,8 +308,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "description": "", "fieldConfig": { @@ -407,8 +396,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"meta\": {\n \"executedQueryString\": \"import \\\"influxdata/influxdb/sample\\\"\\nimport \\\"influxdata/influxdb/schema\\\"\\n\\nsample.data(set: \\\"airSensor\\\")\\n |> limit(n: 10)\\n |> group(columns: [\\\"sensor_id\\\"])\\n |> schema.fieldsAsCols()\\n\",\n \"typeVersion\": [\n 0,\n 0\n ]\n },\n \"fields\": [\n {\n \"config\": {},\n \"name\": \"_time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0100\"\n },\n \"name\": \"co\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0100\"\n },\n \"name\": \"humidity\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0100\"\n },\n \"name\": \"temperature\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1686898151000,\n 1686898161000,\n 1686898171000,\n 1686898181000,\n 1686898191000,\n 1686898201000,\n 1686898211000,\n 1686898221000,\n 1686898231000,\n 1686898241000\n ],\n [\n 0.4860747509084685,\n 0.4790778553981873,\n 0.4597786615711249,\n 0.4478751241705323,\n 0.44020548182152397,\n 0.4569020188814074,\n 0.4655250429581913,\n 0.4819032762634117,\n 0.491365303224968,\n 0.5092239049148886\n ],\n [\n 35.084960222673146,\n 35.089101898649055,\n 35.130020139289115,\n 35.10251705413486,\n 35.08184755996438,\n 35.04582600108574,\n 35.09077388700681,\n 35.04096375315356,\n 35.05647864027338,\n 35.091800720894916\n ],\n [\n 71.2187151336704,\n 71.24617135003214,\n 71.21726829714834,\n 71.26528218716341,\n 71.26084702358875,\n 71.24054378677393,\n 71.27884802991244,\n 71.29783163616926,\n 71.33230999794793,\n 71.34975514559837\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"config\": {},\n \"name\": \"_time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0101\"\n },\n \"name\": \"co\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0101\"\n },\n \"name\": \"humidity\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0101\"\n },\n \"name\": \"temperature\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1686898151000,\n 1686898161000,\n 1686898171000,\n 1686898181000,\n 1686898191000,\n 1686898201000,\n 1686898211000,\n 1686898221000,\n 1686898231000,\n 1686898241000\n ],\n [\n 0.4964171323208575,\n 0.48257922637952133,\n 0.46567087322576145,\n 0.4467650568596856,\n 0.4417772514767169,\n 0.4341379534638706,\n 0.439345038257859,\n 0.43452737707188627,\n 0.42417500678639164,\n 0.40704613738954887\n ],\n [\n 34.92662088456207,\n 34.91464944732493,\n 34.95985887959429,\n 34.929238294894844,\n 34.954103486412336,\n 34.98895514808448,\n 35.03476240219413,\n 35.028863365125844,\n 35.03717014192905,\n 35.00775919996651\n ],\n [\n 71.83521495327129,\n 71.83370684393908,\n 71.83712160725877,\n 71.88299650060345,\n 71.90526594972503,\n 71.8631768515712,\n 71.85577028152356,\n 71.89245169322045,\n 71.93606971457449,\n 71.96164771829956\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"config\": {},\n \"name\": \"_time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0102\"\n },\n \"name\": \"co\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0102\"\n },\n \"name\": \"humidity\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0102\"\n },\n \"name\": \"temperature\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1686898151000,\n 1686898161000,\n 1686898171000,\n 1686898181000,\n 1686898191000,\n 1686898201000,\n 1686898211000,\n 1686898221000,\n 1686898231000,\n 1686898241000\n ],\n [\n 0.4870365157212326,\n 0.5032215395360725,\n 0.5035259485542879,\n 0.4841798164121083,\n 0.483812619615984,\n 0.4882993499867786,\n 0.4719009580435705,\n 0.4700689455810135,\n 0.48112413053169706,\n 0.4691106107162724\n ],\n [\n 34.86359615237462,\n 34.84629630959152,\n 34.81771460191974,\n 34.854640808896036,\n 34.86699022367547,\n 34.864319179513096,\n 34.86915527122888,\n 34.89889649251399,\n 34.86576388906259,\n 34.88622805723735\n ],\n [\n 72.03972207916735,\n 72.05566134520713,\n 72.08473708469143,\n 72.07306942754916,\n 72.0427409958616,\n 72.04536459775873,\n 72.09400368933838,\n 72.14293243585941,\n 72.18840859469728,\n 72.15524663568557\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"config\": {},\n \"name\": \"_time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0103\"\n },\n \"name\": \"co\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0103\"\n },\n \"name\": \"humidity\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0103\"\n },\n \"name\": \"temperature\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1686898151000,\n 1686898161000,\n 1686898171000,\n 1686898181000,\n 1686898191000,\n 1686898201000,\n 1686898211000,\n 1686898221000,\n 1686898231000,\n 1686898241000\n ],\n [\n 0.3979338437168368,\n 0.4117117830425588,\n 0.4000376537804249,\n 0.40114553332960723,\n 0.3909759394807085,\n 0.38213452854680874,\n 0.37339826793170855,\n 0.3624713623472977,\n 0.35640734768856297,\n 0.35690557816119645\n ],\n [\n 35.16192242281515,\n 35.19891757080395,\n 35.23754373785834,\n 35.25270355198698,\n 35.29525947947623,\n 35.272026086051184,\n 35.275233467451635,\n 35.23834593104291,\n 35.25233833634368,\n 35.22053598631417\n ],\n [\n 71.29169927438586,\n 71.32114142326272,\n 71.33632903748085,\n 71.3064635464553,\n 71.26436580075855,\n 71.30431517798449,\n 71.28861822950174,\n 71.26778760430453,\n 71.23481860950403,\n 71.23084180913762\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"config\": {},\n \"name\": \"_time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0200\"\n },\n \"name\": \"co\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0200\"\n },\n \"name\": \"humidity\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0200\"\n },\n \"name\": \"temperature\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1686898151000,\n 1686898161000,\n 1686898171000,\n 1686898181000,\n 1686898191000,\n 1686898201000,\n 1686898211000,\n 1686898221000,\n 1686898231000,\n 1686898241000\n ],\n [\n 0.5129015632374951,\n 0.552968955740271,\n 0.5690444135565038,\n 0.6050221760178951,\n 0.5943904374498042,\n 0.6153588301241533,\n 0.6164375823908576,\n 0.6059635952981327,\n 0.6470283318343141,\n 0.6861075098169984\n ],\n [\n 35.75385592664215,\n 35.753218714107504,\n 35.72547059379115,\n 35.74553237372676,\n 35.73378268235891,\n 35.747560005048086,\n 35.769867599816735,\n 35.73929899563808,\n 35.705317880681875,\n 35.65611547721327\n ],\n [\n 73.64806558624832,\n 73.65728412124716,\n 73.68805520135102,\n 73.65185281162863,\n 73.63499402146681,\n 73.68359308763364,\n 73.64682180062367,\n 73.63298265031713,\n 73.59096788790947,\n 73.6381949597034\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"config\": {},\n \"name\": \"_time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0201\"\n },\n \"name\": \"co\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0201\"\n },\n \"name\": \"humidity\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0201\"\n },\n \"name\": \"temperature\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1686898151000,\n 1686898161000,\n 1686898171000,\n 1686898181000,\n 1686898191000,\n 1686898201000,\n 1686898211000,\n 1686898221000,\n 1686898231000,\n 1686898241000\n ],\n [\n 0.5082489903097206,\n 0.525490999229553,\n 0.5300688563597754,\n 0.5351282770519872,\n 0.533437724470923,\n 0.5164188260958164,\n 0.5134188770545406,\n 0.4949993424337248,\n 0.4960387472164697,\n 0.5046934441184395\n ],\n [\n 35.24972613768055,\n 35.238916979727335,\n 35.28758958750148,\n 35.26413172906637,\n 35.2875488141577,\n 35.32420268624064,\n 35.2932945023372,\n 35.277959228995584,\n 35.27901195680498,\n 35.27056468599647\n ],\n [\n 73.99618150289902,\n 74.01973867729899,\n 73.97488048626532,\n 73.97027021897547,\n 73.96055098802299,\n 73.94544160099603,\n 73.91010608315078,\n 73.9594600253564,\n 73.93323000030807,\n 73.94265737589377\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"config\": {},\n \"name\": \"_time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0202\"\n },\n \"name\": \"co\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0202\"\n },\n \"name\": \"humidity\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0202\"\n },\n \"name\": \"temperature\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1686898151000,\n 1686898161000,\n 1686898171000,\n 1686898181000,\n 1686898191000,\n 1686898201000,\n 1686898211000,\n 1686898221000,\n 1686898231000,\n 1686898241000\n ],\n [\n 0.4843506884938821,\n 0.48132272563110234,\n 0.4738268718199932,\n 0.4929629619836042,\n 0.4730642763470896,\n 0.4654986284178103,\n 0.47939137148137106,\n 0.4729232244284411,\n 0.48941836624955776,\n 0.49438537058971027\n ],\n [\n 35.6843507637763,\n 35.67052290561625,\n 35.651191124511904,\n 35.682694567957775,\n 35.71754463951193,\n 35.73271359197846,\n 35.76201128140823,\n 35.72031962293351,\n 35.76508898680512,\n 35.77376488207177\n ],\n [\n 75.28536533620796,\n 75.3203884403274,\n 75.32915092826639,\n 75.3260291876276,\n 75.29613126188146,\n 75.31098782530198,\n 75.27434784939884,\n 75.30929861509146,\n 75.32818662869892,\n 75.33650169518009\n ]\n ]\n }\n },\n {\n \"schema\": {\n \"refId\": \"A\",\n \"fields\": [\n {\n \"config\": {},\n \"name\": \"_time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0203\"\n },\n \"name\": \"co\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0203\"\n },\n \"name\": \"humidity\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n },\n {\n \"config\": {},\n \"labels\": {\n \"sensor_id\": \"TLM0203\"\n },\n \"name\": \"temperature\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n }\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1686898151000,\n 1686898161000,\n 1686898171000,\n 1686898181000,\n 1686898191000,\n 1686898201000,\n 1686898211000,\n 1686898221000,\n 1686898231000,\n 1686898241000\n ],\n [\n 0.39373421338928505,\n 0.40929905142175416,\n 0.39727569840202215,\n 0.415834035946844,\n 0.413865826090914,\n 0.4271278288285897,\n 0.435277474574255,\n 0.4480042029285831,\n 0.462641109361364,\n 0.4566678920783633\n ],\n [\n 35.86322585633077,\n 35.88732568460068,\n 35.87553827435961,\n 35.84063967239316,\n 35.813642046057005,\n 35.8569165461967,\n 35.80924651587166,\n 35.80599199551315,\n 35.75906423980926,\n 35.79948361256034\n ],\n [\n 74.78112365229704,\n 74.73821283157658,\n 74.73019922701285,\n 74.73280967321202,\n 74.74885460260536,\n 74.70880911705714,\n 74.73346687605624,\n 74.77682413662681,\n 74.80562351134131,\n 74.82881664528719\n ]\n ]\n }\n }\n]", "refId": "A", @@ -420,8 +408,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -523,8 +510,7 @@ { "csvFileName": "flight_info_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -535,8 +521,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -671,8 +656,7 @@ { "csvFileName": "automobiles.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -683,9 +667,7 @@ { "id": "partitionByValues", "options": { - "fields": [ - "Origin" - ] + "fields": ["Origin"] } } ], @@ -693,8 +675,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -796,8 +777,7 @@ { "csvFileName": "flight_info_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -808,8 +788,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -917,8 +896,7 @@ { "csvFileName": "flight_info_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -929,8 +907,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1028,8 +1005,7 @@ { "csvFileName": "flight_info_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -1040,8 +1016,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1137,8 +1112,7 @@ { "csvContent": "X,Y\n725.1,435.6\n734.1,497.2\n714.3,527.7\n683.5,548.7\n601.8,594.0\n598.5,621.7\n573.9,644.7\n525.7,695.7\n477.2,732.8\n411.8,755.3\n353.6,758.3\n422.6,736.5\n455.3,724.1\n479.2,699.2\n474.0,673.8\n434.5,662.1\n362.2,679.8\n311.2,698.8\n260.1,728.9\n213.4,771.1\n176.2,818.0\n211.2,742.6\n253.9,707.9\n309.9,668.8\n374.7,643.2\n322.8,629.9\n277.1,607.1\n237.0,616.8\n188.9,613.9\n143.0,594.1\n101.8,566.4\n178.1,590.2\n222.2,575.9\n187.9,549.1\n161.5,517.5\n128.6,506.8\n97.3,488.3\n62.4,436.0\n99.6,473.8\n138.3,477.0\n125.0,396.7\n95.6,359.2\n83.6,322.1\n81.0,289.7\n104.0,343.8\n129.3,358.4\n151.2,291.1\n124.0,242.6\n126.3,170.2\n133.7,212.8\n148.4,243.3\n167.9,262.7\n209.1,205.7\n230.1,150.3\n231.4,120.1\n316.0,120.1\n400.6,120.1\n485.2,120.1\n569.8,120.1\n569.3,166.4\n553.0,205.5\n489.2,265.7\n422.2,309.1\n353.7,343.1\n328.2,386.3\n321.6,432.6\n334.1,473.1\n357.6,500.3\n389.9,508.5\n418.8,479.9\n447.9,413.3\n480.0,379.0\n521.6,354.2\n583.9,351.6\n549.7,357.7\n571.6,376.0\n517.1,380.8\n550.3,393.2\n504.3,402.3\n489.5,425.8\n527.5,425.8\n472.7,457.2\n447.1,523.8\n538.6,435.7\n598.4,403.7\n697.8,349.1\n645.3,390.4\n712.3,373.8\n586.0,424.1\n526.9,463.3\n469.5,538.0\n540.6,477.5\n531.2,528.4\n598.6,460.1\n594.5,509.0\n651.2,460.1\n649.9,502.6\n699.4,446.1\n707.6,477.1\n722.0,442.9", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -1149,8 +1123,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1206,10 +1179,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 10, - 15 - ], + "dash": [10, 15], "fill": "dash" } } @@ -1292,9 +1262,7 @@ "showLegend": true }, "mapping": "auto", - "series": [ - {} - ], + "series": [{}], "tooltip": { "hideZeros": false, "mode": "single", @@ -1307,8 +1275,7 @@ "alias": "", "csvContent": "x,cos(x)\n-7.5,3.4663531783502584\n-7.45,3.9308257356494076\n-7.4,4.385473275743903\n-7.35,4.829159416559378\n-7.3,5.260775173811053\n-7.25,5.679241732886949\n-7.2,6.083513145322545\n-7.15,6.472578943127236\n-7.1,6.845466664428066\n-7.05,7.201244284117942\n-7,7.539022543433046\n-6.95,7.857957172636611\n-6.9,8.157251001253568\n-6.85,8.436155950581597\n-6.8,8.693974903498253\n-6.75,8.930063446890767\n-6.7,9.143831482353194\n-6.65,9.334744701125118\n-6.6,9.502325919585296\n-6.55,9.64615627196218\n-6.5,9.765876257280235\n-6.45,9.861186637925126\n-6.4,9.931849187581927\n-6.35,9.97768728667684\n-6.3,9.998586363834152\n-6.25,9.994494182244994\n-6.2,9.965420970232175\n-6.15,9.91143939568469\n-6.1,9.832684384425844\n-6.05,9.729352782968974\n-6,9.601702866503661\n-5.95,9.450053693342275\n-5.9,9.27478430744036\n-5.85,9.076332790984132\n-5.8,8.85519516941319\n-5.75,8.611924171615208\n-5.7,8.347127848391597\n-5.65,8.061468052647157\n-5.6,7.755658785102496\n-5.55,7.430464409664099\n-5.5,7.0866977429126\n-5.45,6.725218022484659\n-5.4,6.346928759426347\n-5.35,5.952775479886061\n-5.3,5.543743361791607\n-5.25,5.120854772418407\n-5.2,4.685166713003771\n-5.15,4.237768176794282\n-5.1,3.7797774271298024\n-5.05,3.3123392023675367\n-5,2.8366218546322624\n-4.95,2.353814429544512\n-4.9,1.8651236942257576\n-4.85,1.371771121009073\n-4.8,0.874989834394464\n-4.75,0.37602152887976553\n-4.7,-0.1238866346289056\n-4.65,-0.6234851460699166\n-4.6,-1.1215252693505486\n-4.55,-1.616762163536865\n-4.5,-2.107957994307797\n-4.45,-2.593885027896261\n-4.4,-3.0733286997841933\n-4.35,-3.5450906504813195\n-4.3,-4.007991720799755\n-4.25,-4.460874899137928\n-4.2,-4.902608213406994\n-4.15,-5.332087560371543\n-4.1,-5.748239465332691\n-4.05,-6.150023765255744\n-4,-6.536436208636119\n-3.95,-6.906510965605075\n-3.9,-7.259323042001402\n-3.85,-7.593990591375079\n-3.8,-7.909677119144169\n-3.75,-8.205593573395607\n-3.7,-8.48100031710408\n-3.65,-8.73520897683938\n-3.6,-8.96758416334147\n-3.55,-9.177545059662759\n-3.5,-9.364566872907963\n-3.45,-9.528182145943047\n-3.4,-9.66798192579461\n-3.35,-9.78361678581934\n-3.3,-9.87479769908865\n-3.25,-9.941296760805463\n-3.2,-9.982947757947532\n-3.15,-9.99964658471342\n-3.1,-9.991351502732794\n-3.05,-9.958083245390611\n-3,-9.899924966004454\n-2.95,-9.81702202998454\n-2.9,-9.709581651495906\n-2.85,-9.577872375530903\n-2.8,-9.42222340668658\n-2.75,-9.243023786324635\n-2.7,-9.040721420170613\n-2.65,-8.815821958782859\n-2.6,-8.568887533689473\n-2.55,-8.30053535235222\n-2.5,-8.011436155469337\n-2.45,-7.702312540473074\n-2.4,-7.373937155412454\n-2.35,-7.027130767735539\n-2.3,-6.66276021279824\n-2.25,-6.281736227227391\n-2.2,-5.885011172553458\n-2.15,-5.473576654802709\n-2.1,-5.048461045998575\n-2.05,-4.610726913767127\n-2,-4.161468365471424\n-1.95,-3.7018083135128688\n-1.9,-3.2328956686350336\n-1.85,-2.7559024682451296\n-1.8,-2.272020946930871\n-1.75,-1.7824605564949207\n-1.7,-1.2884449429552465\n-1.65,-0.7912088880673386\n-1.6,-0.29199522301288816\n-1.55,0.20794827803092428\n-1.5,0.7073720166770291\n-1.45,1.2050276936736661\n-1.4,1.6996714290024104\n-1.35,2.1900668709304147\n-1.3,2.6749882862458736\n-1.25,3.1532236239526865\n-1.2,3.623577544766736\n-1.15,4.084874408841574\n-1.1,4.5359612142557735\n-1.05,4.97571047891727\n-1,5.403023058681398\n-0.95,5.8168308946388345\n-0.9,6.216099682706644\n-0.85,6.599831458849822\n-0.8,6.967067093471654\n-0.75,7.316888688738209\n-0.7,7.648421872844885\n-0.65,7.960837985490558\n-0.6,8.253356149096783\n-0.55,8.525245220595057\n-0.5,8.775825618903728\n-0.45,9.004471023526769\n-0.4,9.210609940028851\n-0.35,9.393727128473788\n-0.3,9.55336489125606\n-0.25,9.689124217106448\n-0.2,9.800665778412416\n-0.15,9.887710779360422\n-0.1,9.950041652780257\n-0.05,9.987502603949663\n0,10\n0.05,9.987502603949663\n0.1,9.950041652780257\n0.15,9.887710779360422\n0.2,9.800665778412416\n0.25,9.689124217106448\n0.3,9.55336489125606\n0.35,9.393727128473788\n0.4,9.210609940028851\n0.45,9.004471023526769\n0.5,8.775825618903728\n0.55,8.525245220595057\n0.6,8.253356149096783\n0.65,7.960837985490558\n0.7,7.648421872844885\n0.75,7.316888688738209\n0.8,6.967067093471654\n0.85,6.599831458849822\n0.9,6.216099682706644\n0.95,5.8168308946388345\n1,5.403023058681398\n1.05,4.97571047891727\n1.1,4.5359612142557735\n1.15,4.084874408841574\n1.2,3.623577544766736\n1.25,3.1532236239526865\n1.3,2.6749882862458736\n1.35,2.1900668709304147\n1.4,1.6996714290024104\n1.45,1.2050276936736661\n1.5,0.7073720166770291\n1.55,0.20794827803092428\n1.6,-0.29199522301288816\n1.65,-0.7912088880673386\n1.7,-1.2884449429552465\n1.75,-1.7824605564949207\n1.8,-2.272020946930871\n1.85,-2.7559024682451296\n1.9,-3.2328956686350336\n1.95,-3.7018083135128688\n2,-4.161468365471424\n2.05,-4.610726913767127\n2.1,-5.048461045998575\n2.15,-5.473576654802709\n2.2,-5.885011172553458\n2.25,-6.281736227227391\n2.3,-6.66276021279824\n2.35,-7.027130767735539\n2.4,-7.373937155412454\n2.45,-7.702312540473074\n2.5,-8.011436155469337\n2.55,-8.30053535235222\n2.6,-8.568887533689473\n2.65,-8.815821958782859\n2.7,-9.040721420170613\n2.75,-9.243023786324635\n2.8,-9.42222340668658\n2.85,-9.577872375530903\n2.9,-9.709581651495906\n2.95,-9.81702202998454\n3,-9.899924966004454\n3.05,-9.958083245390611\n3.1,-9.991351502732794\n3.15,-9.99964658471342\n3.2,-9.982947757947532\n3.25,-9.941296760805463\n3.3,-9.87479769908865\n3.35,-9.78361678581934\n3.4,-9.66798192579461\n3.45,-9.528182145943047\n3.5,-9.364566872907963\n3.55,-9.177545059662759\n3.6,-8.96758416334147\n3.65,-8.73520897683938\n3.7,-8.48100031710408\n3.75,-8.205593573395607\n3.8,-7.909677119144169\n3.85,-7.593990591375079\n3.9,-7.259323042001402\n3.95,-6.906510965605075\n4,-6.536436208636119\n4.05,-6.150023765255744\n4.1,-5.748239465332691\n4.15,-5.332087560371543\n4.2,-4.902608213406994\n4.25,-4.460874899137928\n4.3,-4.007991720799755\n4.35,-3.5450906504813195\n4.4,-3.0733286997841933\n4.45,-2.593885027896261\n4.5,-2.107957994307797\n4.55,-1.616762163536865\n4.6,-1.1215252693505486\n4.65,-0.6234851460699166\n4.7,-0.1238866346289056\n4.75,0.37602152887976553\n4.8,0.874989834394464\n4.85,1.371771121009073\n4.9,1.8651236942257576\n4.95,2.353814429544512\n5,2.8366218546322624\n5.05,3.3123392023675367\n5.1,3.7797774271298024\n5.15,4.237768176794282\n5.2,4.685166713003771\n5.25,5.120854772418407\n5.3,5.543743361791607\n5.35,5.952775479886061\n5.4,6.346928759426347\n5.45,6.725218022484659\n5.5,7.0866977429126\n5.55,7.430464409664099\n5.6,7.755658785102496\n5.65,8.061468052647157\n5.7,8.347127848391597\n5.75,8.611924171615208\n5.8,8.85519516941319\n5.85,9.076332790984132\n5.9,9.27478430744036\n5.95,9.450053693342275\n6,9.601702866503661\n6.05,9.729352782968974\n6.1,9.832684384425844\n6.15,9.91143939568469\n6.2,9.965420970232175\n6.25,9.994494182244994\n6.3,9.998586363834152\n6.35,9.97768728667684\n6.4,9.931849187581927\n6.45,9.861186637925126\n6.5,9.765876257280235\n6.55,9.64615627196218\n6.6,9.502325919585296\n6.65,9.334744701125118\n6.7,9.143831482353194\n6.75,8.930063446890767\n6.8,8.693974903498253\n6.85,8.436155950581597\n6.9,8.157251001253568\n6.95,7.857957172636611\n7,7.539022543433046\n7.05,7.201244284117942\n7.1,6.845466664428066\n7.15,6.472578943127236\n7.2,6.083513145322545\n7.25,5.679241732886949\n7.3,5.260775173811053\n7.35,4.829159416559378\n7.4,4.385473275743903\n7.45,3.9308257356494076", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -1316,8 +1283,7 @@ { "csvContent": "x2,x^2\n-7.5,56.25\n-7.45,55.502500000000005\n-7.4,54.760000000000005\n-7.35,54.022499999999994\n-7.3,53.29\n-7.25,52.5625\n-7.2,51.84\n-7.15,51.1225\n-7.1,50.41\n-7.05,49.7025\n-7,49\n-6.95,48.3025\n-6.9,47.61000000000001\n-6.85,46.92249999999999\n-6.8,46.239999999999995\n-6.75,45.5625\n-6.7,44.89\n-6.65,44.222500000000004\n-6.6,43.559999999999995\n-6.55,42.902499999999996\n-6.5,42.25\n-6.45,41.6025\n-6.4,40.96000000000001\n-6.35,40.3225\n-6.3,39.69\n-6.25,39.0625\n-6.2,38.440000000000005\n-6.15,37.822500000000005\n-6.1,37.209999999999994\n-6.05,36.6025\n-6,36\n-5.95,35.4025\n-5.9,34.81\n-5.85,34.2225\n-5.8,33.64\n-5.75,33.0625\n-5.7,32.49\n-5.65,31.922500000000003\n-5.6,31.359999999999996\n-5.55,30.8025\n-5.5,30.25\n-5.45,29.7025\n-5.4,29.160000000000004\n-5.35,28.622499999999995\n-5.3,28.09\n-5.25,27.5625\n-5.2,27.040000000000003\n-5.15,26.522500000000004\n-5.1,26.009999999999998\n-5.05,25.502499999999998\n-5,25\n-4.95,24.5025\n-4.9,24.010000000000005\n-4.85,23.522499999999997\n-4.8,23.04\n-4.75,22.5625\n-4.7,22.090000000000003\n-4.65,21.622500000000002\n-4.6,21.159999999999997\n-4.55,20.702499999999997\n-4.5,20.25\n-4.45,19.802500000000002\n-4.4,19.360000000000003\n-4.35,18.922499999999996\n-4.3,18.49\n-4.25,18.0625\n-4.2,17.64\n-4.15,17.222500000000004\n-4.1,16.81\n-4.05,16.4025\n-4,16\n-3.95,15.602500000000001\n-3.9,15.209999999999999\n-3.85,14.822500000000002\n-3.8,14.44\n-3.75,14.0625\n-3.7,13.690000000000001\n-3.65,13.3225\n-3.6,12.96\n-3.55,12.6025\n-3.5,12.25\n-3.45,11.902500000000002\n-3.4,11.559999999999999\n-3.35,11.2225\n-3.3,10.889999999999999\n-3.25,10.5625\n-3.2,10.240000000000002\n-3.15,9.9225\n-3.1,9.610000000000001\n-3.05,9.302499999999998\n-3,9\n-2.95,8.7025\n-2.9,8.41\n-2.85,8.1225\n-2.8,7.839999999999999\n-2.75,7.5625\n-2.7,7.290000000000001\n-2.65,7.0225\n-2.6,6.760000000000001\n-2.55,6.5024999999999995\n-2.5,6.25\n-2.45,6.002500000000001\n-2.4,5.76\n-2.35,5.522500000000001\n-2.3,5.289999999999999\n-2.25,5.0625\n-2.2,4.840000000000001\n-2.15,4.6225\n-2.1,4.41\n-2.05,4.2025\n-2,4\n-1.95,3.8024999999999998\n-1.9,3.61\n-1.85,3.4225000000000003\n-1.8,3.24\n-1.75,3.0625\n-1.7,2.8899999999999997\n-1.65,2.7224999999999997\n-1.6,2.5600000000000005\n-1.55,2.4025000000000003\n-1.5,2.25\n-1.45,2.1025\n-1.4,1.9599999999999997\n-1.35,1.8225000000000002\n-1.3,1.6900000000000002\n-1.25,1.5625\n-1.2,1.44\n-1.15,1.3224999999999998\n-1.1,1.2100000000000002\n-1.05,1.1025\n-1,1\n-0.95,0.9025\n-0.9,0.81\n-0.85,0.7224999999999999\n-0.8,0.6400000000000001\n-0.75,0.5625\n-0.7,0.48999999999999994\n-0.65,0.42250000000000004\n-0.6,0.36\n-0.55,0.30250000000000005\n-0.5,0.25\n-0.45,0.2025\n-0.4,0.16000000000000003\n-0.35,0.12249999999999998\n-0.3,0.09\n-0.25,0.0625\n-0.2,0.04000000000000001\n-0.15,0.0225\n-0.1,0.010000000000000002\n-0.05,0.0025000000000000005\n0,0\n0.05,0.0025000000000000005\n0.1,0.010000000000000002\n0.15,0.0225\n0.2,0.04000000000000001\n0.25,0.0625\n0.3,0.09\n0.35,0.12249999999999998\n0.4,0.16000000000000003\n0.45,0.2025\n0.5,0.25\n0.55,0.30250000000000005\n0.6,0.36\n0.65,0.42250000000000004\n0.7,0.48999999999999994\n0.75,0.5625\n0.8,0.6400000000000001\n0.85,0.7224999999999999\n0.9,0.81\n0.95,0.9025\n1,1\n1.05,1.1025\n1.1,1.2100000000000002\n1.15,1.3224999999999998\n1.2,1.44\n1.25,1.5625\n1.3,1.6900000000000002\n1.35,1.8225000000000002\n1.4,1.9599999999999997\n1.45,2.1025\n1.5,2.25\n1.55,2.4025000000000003\n1.6,2.5600000000000005\n1.65,2.7224999999999997\n1.7,2.8899999999999997\n1.75,3.0625\n1.8,3.24\n1.85,3.4225000000000003\n1.9,3.61\n1.95,3.8024999999999998\n2,4\n2.05,4.2025\n2.1,4.41\n2.15,4.6225\n2.2,4.840000000000001\n2.25,5.0625\n2.3,5.289999999999999\n2.35,5.522500000000001\n2.4,5.76\n2.45,6.002500000000001\n2.5,6.25\n2.55,6.5024999999999995\n2.6,6.760000000000001\n2.65,7.0225\n2.7,7.290000000000001\n2.75,7.5625\n2.8,7.839999999999999\n2.85,8.1225\n2.9,8.41\n2.95,8.7025\n3,9\n3.05,9.302499999999998\n3.1,9.610000000000001\n3.15,9.9225\n3.2,10.240000000000002\n3.25,10.5625\n3.3,10.889999999999999\n3.35,11.2225\n3.4,11.559999999999999\n3.45,11.902500000000002\n3.5,12.25\n3.55,12.6025\n3.6,12.96\n3.65,13.3225\n3.7,13.690000000000001\n3.75,14.0625\n3.8,14.44\n3.85,14.822500000000002\n3.9,15.209999999999999\n3.95,15.602500000000001\n4,16\n4.05,16.4025\n4.1,16.81\n4.15,17.222500000000004\n4.2,17.64\n4.25,18.0625\n4.3,18.49\n4.35,18.922499999999996\n4.4,19.360000000000003\n4.45,19.802500000000002\n4.5,20.25\n4.55,20.702499999999997\n4.6,21.159999999999997\n4.65,21.622500000000002\n4.7,22.090000000000003\n4.75,22.5625\n4.8,23.04\n4.85,23.522499999999997\n4.9,24.010000000000005\n4.95,24.5025\n5,25\n5.05,25.502499999999998\n5.1,26.009999999999998\n5.15,26.522500000000004\n5.2,27.040000000000003\n5.25,27.5625\n5.3,28.09\n5.35,28.622499999999995\n5.4,29.160000000000004\n5.45,29.7025\n5.5,30.25\n5.55,30.8025\n5.6,31.359999999999996\n5.65,31.922500000000003\n5.7,32.49\n5.75,33.0625\n5.8,33.64\n5.85,34.2225\n5.9,34.81\n5.95,35.4025\n6,36\n6.05,36.6025\n6.1,37.209999999999994\n6.15,37.822500000000005\n6.2,38.440000000000005\n6.25,39.0625\n6.3,39.69\n6.35,40.3225\n6.4,40.96000000000001\n6.45,41.6025\n6.5,42.25\n6.55,42.902499999999996\n6.6,43.559999999999995\n6.65,44.222500000000004\n6.7,44.89\n6.75,45.5625\n6.8,46.239999999999995\n6.85,46.92249999999999\n6.9,47.61000000000001\n6.95,48.3025\n7,49\n7.05,49.7025\n7.1,50.41\n7.15,51.1225\n7.2,51.84\n7.25,52.5625\n7.3,53.29\n7.35,54.022499999999994\n7.4,54.760000000000005\n7.45,55.502500000000005", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_content" @@ -1325,8 +1291,7 @@ { "csvContent": "x3,sqrt(x)\n0,0\n0.05,2.23606797749979\n0.1,3.1622776601683795\n0.15,3.872983346207417\n0.2,4.47213595499958\n0.25,5\n0.3,5.47722557505166\n0.35,5.916079783099616\n0.4,6.324555320336759\n0.45,6.708203932499369\n0.5,7.0710678118654755\n0.55,7.416198487095663\n0.6,7.745966692414834\n0.65,8.062257748298551\n0.7,8.366600265340756\n0.75,8.660254037844386\n0.8,8.94427190999916\n0.85,9.219544457292887\n0.9,9.486832980505138\n0.95,9.746794344808963\n1,10\n1.05,10.2469507659596\n1.1,10.488088481701517\n1.15,10.723805294763608\n1.2,10.95445115010332\n1.25,11.180339887498949\n1.3,11.401754250991381\n1.35,11.618950038622252\n1.4,11.832159566199232\n1.45,12.041594578792296\n1.5,12.24744871391589\n1.55,12.449899597988733\n1.6,12.649110640673518\n1.65,12.84523257866513\n1.7,13.038404810405297\n1.75,13.228756555322953\n1.8,13.416407864998739\n1.85,13.601470508735442\n1.9,13.784048752090222\n1.95,13.96424004376894\n2,14.142135623730951\n2.05,14.317821063276352\n2.1,14.49137674618944\n2.15,14.66287829861518\n2.2,14.832396974191326\n2.25,15\n2.3,15.1657508881031\n2.35,15.329709716755893\n2.4,15.491933384829668\n2.45,15.652475842498529\n2.5,15.811388300841898\n2.55,15.968719422671311\n2.6,16.124515496597102\n2.65,16.278820596099706\n2.7,16.431676725154986\n2.75,16.583123951776997\n2.8,16.73320053068151\n2.85,16.881943016134134\n2.9,17.0293863659264\n2.95,17.175564037317667\n3,17.32050807568877\n3.05,17.46424919657298\n3.1,17.60681686165901\n3.15,17.74823934929885\n3.2,17.88854381999832\n3.25,18.027756377319946\n3.3,18.16590212458495\n3.35,18.303005217723125\n3.4,18.439088914585774\n3.45,18.57417562100671\n3.5,18.708286933869708\n3.55,18.84144368141677\n3.6,18.973665961010276\n3.65,19.1049731745428\n3.7,19.235384061671347\n3.75,19.364916731037084\n3.8,19.493588689617926\n3.85,19.621416870348586\n3.9,19.748417658131498\n3.95,19.87460691435179\n4,20\n4.05,20.124611797498105\n4.1,20.248456731316583\n4.15,20.37154878746336\n4.2,20.4939015319192\n4.25,20.615528128088304\n4.3,20.73644135332772\n4.35,20.85665361461421\n4.4,20.976176963403034\n4.45,21.095023109728984\n4.5,21.213203435596423\n4.55,21.330729007701542\n4.6,21.447610589527216\n4.65,21.563858652847827\n4.7,21.6794833886788\n4.75,21.79449471770337\n4.8,21.90890230020664\n4.85,22.022715545545243\n4.9,22.135943621178654\n4.95,22.24859546128699\n5,22.360679774997898\n5.05,22.47220505424423\n5.1,22.58317958127243\n5.15,22.693611435820436\n5.2,22.803508501982762\n5.25,22.9128784747792\n5.3,23.021728866442675\n5.35,23.130067012440755\n5.4,23.237900077244504\n5.45,23.345235059857504\n5.5,23.45207879911715\n5.55,23.55843797877949\n5.6,23.664319132398465\n5.65,23.769728648009426\n5.7,23.874672772626646\n5.75,23.979157616563597\n5.8,24.08318915758459\n5.85,24.186773244895647\n5.9,24.289915602982237\n5.95,24.392621835300936\n6,24.49489742783178\n6.05,24.596747752497684\n6.1,24.698178070456937\n6.15,24.79919353527449\n6.2,24.899799195977465\n6.25,25\n6.3,25.099800796022265\n6.35,25.199206336708304\n6.4,25.298221281347036\n6.45,25.39685019840059\n6.5,25.495097567963924\n6.55,25.592967784139454\n6.6,25.69046515733026\n6.65,25.787593916455258\n6.7,25.88435821108957\n6.75,25.98076211353316\n6.8,26.076809620810593\n6.85,26.1725046566048\n6.9,26.267851073127396\n6.95,26.362852652928133\n7,26.457513110645905\n7.05,26.551836094703507\n7.1,26.645825188948457\n7.15,26.739483914241873\n7.2,26.832815729997478\n7.25,26.92582403567252\n7.3,27.018512172212592\n7.35,27.11088342345192\n7.4,27.202941017470884\n7.45,27.294688127912362", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "csv_content" @@ -1334,8 +1299,7 @@ { "csvContent": "x4,-sqrt(x)\n0,0\n0.05,-2.23606797749979\n0.1,-3.1622776601683795\n0.15,-3.872983346207417\n0.2,-4.47213595499958\n0.25,-5\n0.3,-5.47722557505166\n0.35,-5.916079783099616\n0.4,-6.324555320336759\n0.45,-6.708203932499369\n0.5,-7.0710678118654755\n0.55,-7.416198487095663\n0.6,-7.745966692414834\n0.65,-8.062257748298551\n0.7,-8.366600265340756\n0.75,-8.660254037844386\n0.8,-8.94427190999916\n0.85,-9.219544457292887\n0.9,-9.486832980505138\n0.95,-9.746794344808963\n1,-10\n1.05,-10.2469507659596\n1.1,-10.488088481701517\n1.15,-10.723805294763608\n1.2,-10.95445115010332\n1.25,-11.180339887498949\n1.3,-11.401754250991381\n1.35,-11.618950038622252\n1.4,-11.832159566199232\n1.45,-12.041594578792296\n1.5,-12.24744871391589\n1.55,-12.449899597988733\n1.6,-12.649110640673518\n1.65,-12.84523257866513\n1.7,-13.038404810405297\n1.75,-13.228756555322953\n1.8,-13.416407864998739\n1.85,-13.601470508735442\n1.9,-13.784048752090222\n1.95,-13.96424004376894\n2,-14.142135623730951\n2.05,-14.317821063276352\n2.1,-14.49137674618944\n2.15,-14.66287829861518\n2.2,-14.832396974191326\n2.25,-15\n2.3,-15.1657508881031\n2.35,-15.329709716755893\n2.4,-15.491933384829668\n2.45,-15.652475842498529\n2.5,-15.811388300841898\n2.55,-15.968719422671311\n2.6,-16.124515496597102\n2.65,-16.278820596099706\n2.7,-16.431676725154986\n2.75,-16.583123951776997\n2.8,-16.73320053068151\n2.85,-16.881943016134134\n2.9,-17.0293863659264\n2.95,-17.175564037317667\n3,-17.32050807568877\n3.05,-17.46424919657298\n3.1,-17.60681686165901\n3.15,-17.74823934929885\n3.2,-17.88854381999832\n3.25,-18.027756377319946\n3.3,-18.16590212458495\n3.35,-18.303005217723125\n3.4,-18.439088914585774\n3.45,-18.57417562100671\n3.5,-18.708286933869708\n3.55,-18.84144368141677\n3.6,-18.973665961010276\n3.65,-19.1049731745428\n3.7,-19.235384061671347\n3.75,-19.364916731037084\n3.8,-19.493588689617926\n3.85,-19.621416870348586\n3.9,-19.748417658131498\n3.95,-19.87460691435179\n4,-20\n4.05,-20.124611797498105\n4.1,-20.248456731316583\n4.15,-20.37154878746336\n4.2,-20.4939015319192\n4.25,-20.615528128088304\n4.3,-20.73644135332772\n4.35,-20.85665361461421\n4.4,-20.976176963403034\n4.45,-21.095023109728984\n4.5,-21.213203435596423\n4.55,-21.330729007701542\n4.6,-21.447610589527216\n4.65,-21.563858652847827\n4.7,-21.6794833886788\n4.75,-21.79449471770337\n4.8,-21.90890230020664\n4.85,-22.022715545545243\n4.9,-22.135943621178654\n4.95,-22.24859546128699\n5,-22.360679774997898\n5.05,-22.47220505424423\n5.1,-22.58317958127243\n5.15,-22.693611435820436\n5.2,-22.803508501982762\n5.25,-22.9128784747792\n5.3,-23.021728866442675\n5.35,-23.130067012440755\n5.4,-23.237900077244504\n5.45,-23.345235059857504\n5.5,-23.45207879911715\n5.55,-23.55843797877949\n5.6,-23.664319132398465\n5.65,-23.769728648009426\n5.7,-23.874672772626646\n5.75,-23.979157616563597\n5.8,-24.08318915758459\n5.85,-24.186773244895647\n5.9,-24.289915602982237\n5.95,-24.392621835300936\n6,-24.49489742783178\n6.05,-24.596747752497684\n6.1,-24.698178070456937\n6.15,-24.79919353527449\n6.2,-24.899799195977465\n6.25,-25\n6.3,-25.099800796022265\n6.35,-25.199206336708304\n6.4,-25.298221281347036\n6.45,-25.39685019840059\n6.5,-25.495097567963924\n6.55,-25.592967784139454\n6.6,-25.69046515733026\n6.65,-25.787593916455258\n6.7,-25.88435821108957\n6.75,-25.98076211353316\n6.8,-26.076809620810593\n6.85,-26.1725046566048\n6.9,-26.267851073127396\n6.95,-26.362852652928133\n7,-26.457513110645905\n7.05,-26.551836094703507\n7.1,-26.645825188948457\n7.15,-26.739483914241873\n7.2,-26.832815729997478\n7.25,-26.92582403567252\n7.3,-27.018512172212592\n7.35,-27.11088342345192\n7.4,-27.202941017470884\n7.45,-27.294688127912362", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "csv_content" @@ -1346,8 +1310,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1460,12 +1423,7 @@ "preload": false, "refresh": "", "schemaVersion": 41, - "tags": [ - "gdev", - "panel-tests", - "graph-ng", - "demo" - ], + "tags": ["gdev", "panel-tests", "graph-ng", "demo"], "templating": { "list": [] }, @@ -1478,4 +1436,4 @@ "title": "Panel Tests - XY Chart Demo", "uid": "fdn48fmz8f94wc", "version": 1 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-xychart/xychart-migrations.json b/devenv/dev-dashboards/panel-xychart/xychart-migrations.json index 326c32087b9..1399509f0e2 100644 --- a/devenv/dev-dashboards/panel-xychart/xychart-migrations.json +++ b/devenv/dev-dashboards/panel-xychart/xychart-migrations.json @@ -28,7 +28,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -97,8 +99,7 @@ { "csvContent": "X,Y\n725.1,435.6\n734.1,497.2\n714.3,527.7\n683.5,548.7\n601.8,594.0\n598.5,621.7\n573.9,644.7\n525.7,695.7\n477.2,732.8\n411.8,755.3\n353.6,758.3\n422.6,736.5\n455.3,724.1\n479.2,699.2\n474.0,673.8\n434.5,662.1\n362.2,679.8\n311.2,698.8\n260.1,728.9\n213.4,771.1\n176.2,818.0\n211.2,742.6\n253.9,707.9\n309.9,668.8\n374.7,643.2\n322.8,629.9\n277.1,607.1\n237.0,616.8\n188.9,613.9\n143.0,594.1\n101.8,566.4\n178.1,590.2\n222.2,575.9\n187.9,549.1\n161.5,517.5\n128.6,506.8\n97.3,488.3\n62.4,436.0\n99.6,473.8\n138.3,477.0\n125.0,396.7\n95.6,359.2\n83.6,322.1\n81.0,289.7\n104.0,343.8\n129.3,358.4\n151.2,291.1\n124.0,242.6\n126.3,170.2\n133.7,212.8\n148.4,243.3\n167.9,262.7\n209.1,205.7\n230.1,150.3\n231.4,120.1\n316.0,120.1\n400.6,120.1\n485.2,120.1\n569.8,120.1\n569.3,166.4\n553.0,205.5\n489.2,265.7\n422.2,309.1\n353.7,343.1\n328.2,386.3\n321.6,432.6\n334.1,473.1\n357.6,500.3\n389.9,508.5\n418.8,479.9\n447.9,413.3\n480.0,379.0\n521.6,354.2\n583.9,351.6\n549.7,357.7\n571.6,376.0\n517.1,380.8\n550.3,393.2\n504.3,402.3\n489.5,425.8\n527.5,425.8\n472.7,457.2\n447.1,523.8\n538.6,435.7\n598.4,403.7\n697.8,349.1\n645.3,390.4\n712.3,373.8\n586.0,424.1\n526.9,463.3\n469.5,538.0\n540.6,477.5\n531.2,528.4\n598.6,460.1\n594.5,509.0\n651.2,460.1\n649.9,502.6\n699.4,446.1\n707.6,477.1\n722.0,442.9", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -108,7 +109,9 @@ "type": "xychart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -234,8 +237,7 @@ { "csvFileName": "weight_height.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -246,16 +248,16 @@ { "id": "partitionByValues", "options": { - "fields": [ - "Gender" - ] + "fields": ["Gender"] } } ], "type": "xychart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -307,10 +309,7 @@ { "id": "custom.lineStyle", "value": { - "dash": [ - 10, - 15 - ], + "dash": [10, 15], "fill": "dash" } } @@ -412,8 +411,7 @@ "alias": "", "csvContent": "x,cos(x)\n-7.5,3.4663531783502584\n-7.45,3.9308257356494076\n-7.4,4.385473275743903\n-7.35,4.829159416559378\n-7.3,5.260775173811053\n-7.25,5.679241732886949\n-7.2,6.083513145322545\n-7.15,6.472578943127236\n-7.1,6.845466664428066\n-7.05,7.201244284117942\n-7,7.539022543433046\n-6.95,7.857957172636611\n-6.9,8.157251001253568\n-6.85,8.436155950581597\n-6.8,8.693974903498253\n-6.75,8.930063446890767\n-6.7,9.143831482353194\n-6.65,9.334744701125118\n-6.6,9.502325919585296\n-6.55,9.64615627196218\n-6.5,9.765876257280235\n-6.45,9.861186637925126\n-6.4,9.931849187581927\n-6.35,9.97768728667684\n-6.3,9.998586363834152\n-6.25,9.994494182244994\n-6.2,9.965420970232175\n-6.15,9.91143939568469\n-6.1,9.832684384425844\n-6.05,9.729352782968974\n-6,9.601702866503661\n-5.95,9.450053693342275\n-5.9,9.27478430744036\n-5.85,9.076332790984132\n-5.8,8.85519516941319\n-5.75,8.611924171615208\n-5.7,8.347127848391597\n-5.65,8.061468052647157\n-5.6,7.755658785102496\n-5.55,7.430464409664099\n-5.5,7.0866977429126\n-5.45,6.725218022484659\n-5.4,6.346928759426347\n-5.35,5.952775479886061\n-5.3,5.543743361791607\n-5.25,5.120854772418407\n-5.2,4.685166713003771\n-5.15,4.237768176794282\n-5.1,3.7797774271298024\n-5.05,3.3123392023675367\n-5,2.8366218546322624\n-4.95,2.353814429544512\n-4.9,1.8651236942257576\n-4.85,1.371771121009073\n-4.8,0.874989834394464\n-4.75,0.37602152887976553\n-4.7,-0.1238866346289056\n-4.65,-0.6234851460699166\n-4.6,-1.1215252693505486\n-4.55,-1.616762163536865\n-4.5,-2.107957994307797\n-4.45,-2.593885027896261\n-4.4,-3.0733286997841933\n-4.35,-3.5450906504813195\n-4.3,-4.007991720799755\n-4.25,-4.460874899137928\n-4.2,-4.902608213406994\n-4.15,-5.332087560371543\n-4.1,-5.748239465332691\n-4.05,-6.150023765255744\n-4,-6.536436208636119\n-3.95,-6.906510965605075\n-3.9,-7.259323042001402\n-3.85,-7.593990591375079\n-3.8,-7.909677119144169\n-3.75,-8.205593573395607\n-3.7,-8.48100031710408\n-3.65,-8.73520897683938\n-3.6,-8.96758416334147\n-3.55,-9.177545059662759\n-3.5,-9.364566872907963\n-3.45,-9.528182145943047\n-3.4,-9.66798192579461\n-3.35,-9.78361678581934\n-3.3,-9.87479769908865\n-3.25,-9.941296760805463\n-3.2,-9.982947757947532\n-3.15,-9.99964658471342\n-3.1,-9.991351502732794\n-3.05,-9.958083245390611\n-3,-9.899924966004454\n-2.95,-9.81702202998454\n-2.9,-9.709581651495906\n-2.85,-9.577872375530903\n-2.8,-9.42222340668658\n-2.75,-9.243023786324635\n-2.7,-9.040721420170613\n-2.65,-8.815821958782859\n-2.6,-8.568887533689473\n-2.55,-8.30053535235222\n-2.5,-8.011436155469337\n-2.45,-7.702312540473074\n-2.4,-7.373937155412454\n-2.35,-7.027130767735539\n-2.3,-6.66276021279824\n-2.25,-6.281736227227391\n-2.2,-5.885011172553458\n-2.15,-5.473576654802709\n-2.1,-5.048461045998575\n-2.05,-4.610726913767127\n-2,-4.161468365471424\n-1.95,-3.7018083135128688\n-1.9,-3.2328956686350336\n-1.85,-2.7559024682451296\n-1.8,-2.272020946930871\n-1.75,-1.7824605564949207\n-1.7,-1.2884449429552465\n-1.65,-0.7912088880673386\n-1.6,-0.29199522301288816\n-1.55,0.20794827803092428\n-1.5,0.7073720166770291\n-1.45,1.2050276936736661\n-1.4,1.6996714290024104\n-1.35,2.1900668709304147\n-1.3,2.6749882862458736\n-1.25,3.1532236239526865\n-1.2,3.623577544766736\n-1.15,4.084874408841574\n-1.1,4.5359612142557735\n-1.05,4.97571047891727\n-1,5.403023058681398\n-0.95,5.8168308946388345\n-0.9,6.216099682706644\n-0.85,6.599831458849822\n-0.8,6.967067093471654\n-0.75,7.316888688738209\n-0.7,7.648421872844885\n-0.65,7.960837985490558\n-0.6,8.253356149096783\n-0.55,8.525245220595057\n-0.5,8.775825618903728\n-0.45,9.004471023526769\n-0.4,9.210609940028851\n-0.35,9.393727128473788\n-0.3,9.55336489125606\n-0.25,9.689124217106448\n-0.2,9.800665778412416\n-0.15,9.887710779360422\n-0.1,9.950041652780257\n-0.05,9.987502603949663\n0,10\n0.05,9.987502603949663\n0.1,9.950041652780257\n0.15,9.887710779360422\n0.2,9.800665778412416\n0.25,9.689124217106448\n0.3,9.55336489125606\n0.35,9.393727128473788\n0.4,9.210609940028851\n0.45,9.004471023526769\n0.5,8.775825618903728\n0.55,8.525245220595057\n0.6,8.253356149096783\n0.65,7.960837985490558\n0.7,7.648421872844885\n0.75,7.316888688738209\n0.8,6.967067093471654\n0.85,6.599831458849822\n0.9,6.216099682706644\n0.95,5.8168308946388345\n1,5.403023058681398\n1.05,4.97571047891727\n1.1,4.5359612142557735\n1.15,4.084874408841574\n1.2,3.623577544766736\n1.25,3.1532236239526865\n1.3,2.6749882862458736\n1.35,2.1900668709304147\n1.4,1.6996714290024104\n1.45,1.2050276936736661\n1.5,0.7073720166770291\n1.55,0.20794827803092428\n1.6,-0.29199522301288816\n1.65,-0.7912088880673386\n1.7,-1.2884449429552465\n1.75,-1.7824605564949207\n1.8,-2.272020946930871\n1.85,-2.7559024682451296\n1.9,-3.2328956686350336\n1.95,-3.7018083135128688\n2,-4.161468365471424\n2.05,-4.610726913767127\n2.1,-5.048461045998575\n2.15,-5.473576654802709\n2.2,-5.885011172553458\n2.25,-6.281736227227391\n2.3,-6.66276021279824\n2.35,-7.027130767735539\n2.4,-7.373937155412454\n2.45,-7.702312540473074\n2.5,-8.011436155469337\n2.55,-8.30053535235222\n2.6,-8.568887533689473\n2.65,-8.815821958782859\n2.7,-9.040721420170613\n2.75,-9.243023786324635\n2.8,-9.42222340668658\n2.85,-9.577872375530903\n2.9,-9.709581651495906\n2.95,-9.81702202998454\n3,-9.899924966004454\n3.05,-9.958083245390611\n3.1,-9.991351502732794\n3.15,-9.99964658471342\n3.2,-9.982947757947532\n3.25,-9.941296760805463\n3.3,-9.87479769908865\n3.35,-9.78361678581934\n3.4,-9.66798192579461\n3.45,-9.528182145943047\n3.5,-9.364566872907963\n3.55,-9.177545059662759\n3.6,-8.96758416334147\n3.65,-8.73520897683938\n3.7,-8.48100031710408\n3.75,-8.205593573395607\n3.8,-7.909677119144169\n3.85,-7.593990591375079\n3.9,-7.259323042001402\n3.95,-6.906510965605075\n4,-6.536436208636119\n4.05,-6.150023765255744\n4.1,-5.748239465332691\n4.15,-5.332087560371543\n4.2,-4.902608213406994\n4.25,-4.460874899137928\n4.3,-4.007991720799755\n4.35,-3.5450906504813195\n4.4,-3.0733286997841933\n4.45,-2.593885027896261\n4.5,-2.107957994307797\n4.55,-1.616762163536865\n4.6,-1.1215252693505486\n4.65,-0.6234851460699166\n4.7,-0.1238866346289056\n4.75,0.37602152887976553\n4.8,0.874989834394464\n4.85,1.371771121009073\n4.9,1.8651236942257576\n4.95,2.353814429544512\n5,2.8366218546322624\n5.05,3.3123392023675367\n5.1,3.7797774271298024\n5.15,4.237768176794282\n5.2,4.685166713003771\n5.25,5.120854772418407\n5.3,5.543743361791607\n5.35,5.952775479886061\n5.4,6.346928759426347\n5.45,6.725218022484659\n5.5,7.0866977429126\n5.55,7.430464409664099\n5.6,7.755658785102496\n5.65,8.061468052647157\n5.7,8.347127848391597\n5.75,8.611924171615208\n5.8,8.85519516941319\n5.85,9.076332790984132\n5.9,9.27478430744036\n5.95,9.450053693342275\n6,9.601702866503661\n6.05,9.729352782968974\n6.1,9.832684384425844\n6.15,9.91143939568469\n6.2,9.965420970232175\n6.25,9.994494182244994\n6.3,9.998586363834152\n6.35,9.97768728667684\n6.4,9.931849187581927\n6.45,9.861186637925126\n6.5,9.765876257280235\n6.55,9.64615627196218\n6.6,9.502325919585296\n6.65,9.334744701125118\n6.7,9.143831482353194\n6.75,8.930063446890767\n6.8,8.693974903498253\n6.85,8.436155950581597\n6.9,8.157251001253568\n6.95,7.857957172636611\n7,7.539022543433046\n7.05,7.201244284117942\n7.1,6.845466664428066\n7.15,6.472578943127236\n7.2,6.083513145322545\n7.25,5.679241732886949\n7.3,5.260775173811053\n7.35,4.829159416559378\n7.4,4.385473275743903\n7.45,3.9308257356494076", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -421,8 +419,7 @@ { "csvContent": "x2,x^2\n-7.5,56.25\n-7.45,55.502500000000005\n-7.4,54.760000000000005\n-7.35,54.022499999999994\n-7.3,53.29\n-7.25,52.5625\n-7.2,51.84\n-7.15,51.1225\n-7.1,50.41\n-7.05,49.7025\n-7,49\n-6.95,48.3025\n-6.9,47.61000000000001\n-6.85,46.92249999999999\n-6.8,46.239999999999995\n-6.75,45.5625\n-6.7,44.89\n-6.65,44.222500000000004\n-6.6,43.559999999999995\n-6.55,42.902499999999996\n-6.5,42.25\n-6.45,41.6025\n-6.4,40.96000000000001\n-6.35,40.3225\n-6.3,39.69\n-6.25,39.0625\n-6.2,38.440000000000005\n-6.15,37.822500000000005\n-6.1,37.209999999999994\n-6.05,36.6025\n-6,36\n-5.95,35.4025\n-5.9,34.81\n-5.85,34.2225\n-5.8,33.64\n-5.75,33.0625\n-5.7,32.49\n-5.65,31.922500000000003\n-5.6,31.359999999999996\n-5.55,30.8025\n-5.5,30.25\n-5.45,29.7025\n-5.4,29.160000000000004\n-5.35,28.622499999999995\n-5.3,28.09\n-5.25,27.5625\n-5.2,27.040000000000003\n-5.15,26.522500000000004\n-5.1,26.009999999999998\n-5.05,25.502499999999998\n-5,25\n-4.95,24.5025\n-4.9,24.010000000000005\n-4.85,23.522499999999997\n-4.8,23.04\n-4.75,22.5625\n-4.7,22.090000000000003\n-4.65,21.622500000000002\n-4.6,21.159999999999997\n-4.55,20.702499999999997\n-4.5,20.25\n-4.45,19.802500000000002\n-4.4,19.360000000000003\n-4.35,18.922499999999996\n-4.3,18.49\n-4.25,18.0625\n-4.2,17.64\n-4.15,17.222500000000004\n-4.1,16.81\n-4.05,16.4025\n-4,16\n-3.95,15.602500000000001\n-3.9,15.209999999999999\n-3.85,14.822500000000002\n-3.8,14.44\n-3.75,14.0625\n-3.7,13.690000000000001\n-3.65,13.3225\n-3.6,12.96\n-3.55,12.6025\n-3.5,12.25\n-3.45,11.902500000000002\n-3.4,11.559999999999999\n-3.35,11.2225\n-3.3,10.889999999999999\n-3.25,10.5625\n-3.2,10.240000000000002\n-3.15,9.9225\n-3.1,9.610000000000001\n-3.05,9.302499999999998\n-3,9\n-2.95,8.7025\n-2.9,8.41\n-2.85,8.1225\n-2.8,7.839999999999999\n-2.75,7.5625\n-2.7,7.290000000000001\n-2.65,7.0225\n-2.6,6.760000000000001\n-2.55,6.5024999999999995\n-2.5,6.25\n-2.45,6.002500000000001\n-2.4,5.76\n-2.35,5.522500000000001\n-2.3,5.289999999999999\n-2.25,5.0625\n-2.2,4.840000000000001\n-2.15,4.6225\n-2.1,4.41\n-2.05,4.2025\n-2,4\n-1.95,3.8024999999999998\n-1.9,3.61\n-1.85,3.4225000000000003\n-1.8,3.24\n-1.75,3.0625\n-1.7,2.8899999999999997\n-1.65,2.7224999999999997\n-1.6,2.5600000000000005\n-1.55,2.4025000000000003\n-1.5,2.25\n-1.45,2.1025\n-1.4,1.9599999999999997\n-1.35,1.8225000000000002\n-1.3,1.6900000000000002\n-1.25,1.5625\n-1.2,1.44\n-1.15,1.3224999999999998\n-1.1,1.2100000000000002\n-1.05,1.1025\n-1,1\n-0.95,0.9025\n-0.9,0.81\n-0.85,0.7224999999999999\n-0.8,0.6400000000000001\n-0.75,0.5625\n-0.7,0.48999999999999994\n-0.65,0.42250000000000004\n-0.6,0.36\n-0.55,0.30250000000000005\n-0.5,0.25\n-0.45,0.2025\n-0.4,0.16000000000000003\n-0.35,0.12249999999999998\n-0.3,0.09\n-0.25,0.0625\n-0.2,0.04000000000000001\n-0.15,0.0225\n-0.1,0.010000000000000002\n-0.05,0.0025000000000000005\n0,0\n0.05,0.0025000000000000005\n0.1,0.010000000000000002\n0.15,0.0225\n0.2,0.04000000000000001\n0.25,0.0625\n0.3,0.09\n0.35,0.12249999999999998\n0.4,0.16000000000000003\n0.45,0.2025\n0.5,0.25\n0.55,0.30250000000000005\n0.6,0.36\n0.65,0.42250000000000004\n0.7,0.48999999999999994\n0.75,0.5625\n0.8,0.6400000000000001\n0.85,0.7224999999999999\n0.9,0.81\n0.95,0.9025\n1,1\n1.05,1.1025\n1.1,1.2100000000000002\n1.15,1.3224999999999998\n1.2,1.44\n1.25,1.5625\n1.3,1.6900000000000002\n1.35,1.8225000000000002\n1.4,1.9599999999999997\n1.45,2.1025\n1.5,2.25\n1.55,2.4025000000000003\n1.6,2.5600000000000005\n1.65,2.7224999999999997\n1.7,2.8899999999999997\n1.75,3.0625\n1.8,3.24\n1.85,3.4225000000000003\n1.9,3.61\n1.95,3.8024999999999998\n2,4\n2.05,4.2025\n2.1,4.41\n2.15,4.6225\n2.2,4.840000000000001\n2.25,5.0625\n2.3,5.289999999999999\n2.35,5.522500000000001\n2.4,5.76\n2.45,6.002500000000001\n2.5,6.25\n2.55,6.5024999999999995\n2.6,6.760000000000001\n2.65,7.0225\n2.7,7.290000000000001\n2.75,7.5625\n2.8,7.839999999999999\n2.85,8.1225\n2.9,8.41\n2.95,8.7025\n3,9\n3.05,9.302499999999998\n3.1,9.610000000000001\n3.15,9.9225\n3.2,10.240000000000002\n3.25,10.5625\n3.3,10.889999999999999\n3.35,11.2225\n3.4,11.559999999999999\n3.45,11.902500000000002\n3.5,12.25\n3.55,12.6025\n3.6,12.96\n3.65,13.3225\n3.7,13.690000000000001\n3.75,14.0625\n3.8,14.44\n3.85,14.822500000000002\n3.9,15.209999999999999\n3.95,15.602500000000001\n4,16\n4.05,16.4025\n4.1,16.81\n4.15,17.222500000000004\n4.2,17.64\n4.25,18.0625\n4.3,18.49\n4.35,18.922499999999996\n4.4,19.360000000000003\n4.45,19.802500000000002\n4.5,20.25\n4.55,20.702499999999997\n4.6,21.159999999999997\n4.65,21.622500000000002\n4.7,22.090000000000003\n4.75,22.5625\n4.8,23.04\n4.85,23.522499999999997\n4.9,24.010000000000005\n4.95,24.5025\n5,25\n5.05,25.502499999999998\n5.1,26.009999999999998\n5.15,26.522500000000004\n5.2,27.040000000000003\n5.25,27.5625\n5.3,28.09\n5.35,28.622499999999995\n5.4,29.160000000000004\n5.45,29.7025\n5.5,30.25\n5.55,30.8025\n5.6,31.359999999999996\n5.65,31.922500000000003\n5.7,32.49\n5.75,33.0625\n5.8,33.64\n5.85,34.2225\n5.9,34.81\n5.95,35.4025\n6,36\n6.05,36.6025\n6.1,37.209999999999994\n6.15,37.822500000000005\n6.2,38.440000000000005\n6.25,39.0625\n6.3,39.69\n6.35,40.3225\n6.4,40.96000000000001\n6.45,41.6025\n6.5,42.25\n6.55,42.902499999999996\n6.6,43.559999999999995\n6.65,44.222500000000004\n6.7,44.89\n6.75,45.5625\n6.8,46.239999999999995\n6.85,46.92249999999999\n6.9,47.61000000000001\n6.95,48.3025\n7,49\n7.05,49.7025\n7.1,50.41\n7.15,51.1225\n7.2,51.84\n7.25,52.5625\n7.3,53.29\n7.35,54.022499999999994\n7.4,54.760000000000005\n7.45,55.502500000000005", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "B", "scenarioId": "csv_content" @@ -430,8 +427,7 @@ { "csvContent": "x3,sqrt(x)\n0,0\n0.05,2.23606797749979\n0.1,3.1622776601683795\n0.15,3.872983346207417\n0.2,4.47213595499958\n0.25,5\n0.3,5.47722557505166\n0.35,5.916079783099616\n0.4,6.324555320336759\n0.45,6.708203932499369\n0.5,7.0710678118654755\n0.55,7.416198487095663\n0.6,7.745966692414834\n0.65,8.062257748298551\n0.7,8.366600265340756\n0.75,8.660254037844386\n0.8,8.94427190999916\n0.85,9.219544457292887\n0.9,9.486832980505138\n0.95,9.746794344808963\n1,10\n1.05,10.2469507659596\n1.1,10.488088481701517\n1.15,10.723805294763608\n1.2,10.95445115010332\n1.25,11.180339887498949\n1.3,11.401754250991381\n1.35,11.618950038622252\n1.4,11.832159566199232\n1.45,12.041594578792296\n1.5,12.24744871391589\n1.55,12.449899597988733\n1.6,12.649110640673518\n1.65,12.84523257866513\n1.7,13.038404810405297\n1.75,13.228756555322953\n1.8,13.416407864998739\n1.85,13.601470508735442\n1.9,13.784048752090222\n1.95,13.96424004376894\n2,14.142135623730951\n2.05,14.317821063276352\n2.1,14.49137674618944\n2.15,14.66287829861518\n2.2,14.832396974191326\n2.25,15\n2.3,15.1657508881031\n2.35,15.329709716755893\n2.4,15.491933384829668\n2.45,15.652475842498529\n2.5,15.811388300841898\n2.55,15.968719422671311\n2.6,16.124515496597102\n2.65,16.278820596099706\n2.7,16.431676725154986\n2.75,16.583123951776997\n2.8,16.73320053068151\n2.85,16.881943016134134\n2.9,17.0293863659264\n2.95,17.175564037317667\n3,17.32050807568877\n3.05,17.46424919657298\n3.1,17.60681686165901\n3.15,17.74823934929885\n3.2,17.88854381999832\n3.25,18.027756377319946\n3.3,18.16590212458495\n3.35,18.303005217723125\n3.4,18.439088914585774\n3.45,18.57417562100671\n3.5,18.708286933869708\n3.55,18.84144368141677\n3.6,18.973665961010276\n3.65,19.1049731745428\n3.7,19.235384061671347\n3.75,19.364916731037084\n3.8,19.493588689617926\n3.85,19.621416870348586\n3.9,19.748417658131498\n3.95,19.87460691435179\n4,20\n4.05,20.124611797498105\n4.1,20.248456731316583\n4.15,20.37154878746336\n4.2,20.4939015319192\n4.25,20.615528128088304\n4.3,20.73644135332772\n4.35,20.85665361461421\n4.4,20.976176963403034\n4.45,21.095023109728984\n4.5,21.213203435596423\n4.55,21.330729007701542\n4.6,21.447610589527216\n4.65,21.563858652847827\n4.7,21.6794833886788\n4.75,21.79449471770337\n4.8,21.90890230020664\n4.85,22.022715545545243\n4.9,22.135943621178654\n4.95,22.24859546128699\n5,22.360679774997898\n5.05,22.47220505424423\n5.1,22.58317958127243\n5.15,22.693611435820436\n5.2,22.803508501982762\n5.25,22.9128784747792\n5.3,23.021728866442675\n5.35,23.130067012440755\n5.4,23.237900077244504\n5.45,23.345235059857504\n5.5,23.45207879911715\n5.55,23.55843797877949\n5.6,23.664319132398465\n5.65,23.769728648009426\n5.7,23.874672772626646\n5.75,23.979157616563597\n5.8,24.08318915758459\n5.85,24.186773244895647\n5.9,24.289915602982237\n5.95,24.392621835300936\n6,24.49489742783178\n6.05,24.596747752497684\n6.1,24.698178070456937\n6.15,24.79919353527449\n6.2,24.899799195977465\n6.25,25\n6.3,25.099800796022265\n6.35,25.199206336708304\n6.4,25.298221281347036\n6.45,25.39685019840059\n6.5,25.495097567963924\n6.55,25.592967784139454\n6.6,25.69046515733026\n6.65,25.787593916455258\n6.7,25.88435821108957\n6.75,25.98076211353316\n6.8,26.076809620810593\n6.85,26.1725046566048\n6.9,26.267851073127396\n6.95,26.362852652928133\n7,26.457513110645905\n7.05,26.551836094703507\n7.1,26.645825188948457\n7.15,26.739483914241873\n7.2,26.832815729997478\n7.25,26.92582403567252\n7.3,27.018512172212592\n7.35,27.11088342345192\n7.4,27.202941017470884\n7.45,27.294688127912362", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "C", "scenarioId": "csv_content" @@ -439,8 +435,7 @@ { "csvContent": "x4,-sqrt(x)\n0,0\n0.05,-2.23606797749979\n0.1,-3.1622776601683795\n0.15,-3.872983346207417\n0.2,-4.47213595499958\n0.25,-5\n0.3,-5.47722557505166\n0.35,-5.916079783099616\n0.4,-6.324555320336759\n0.45,-6.708203932499369\n0.5,-7.0710678118654755\n0.55,-7.416198487095663\n0.6,-7.745966692414834\n0.65,-8.062257748298551\n0.7,-8.366600265340756\n0.75,-8.660254037844386\n0.8,-8.94427190999916\n0.85,-9.219544457292887\n0.9,-9.486832980505138\n0.95,-9.746794344808963\n1,-10\n1.05,-10.2469507659596\n1.1,-10.488088481701517\n1.15,-10.723805294763608\n1.2,-10.95445115010332\n1.25,-11.180339887498949\n1.3,-11.401754250991381\n1.35,-11.618950038622252\n1.4,-11.832159566199232\n1.45,-12.041594578792296\n1.5,-12.24744871391589\n1.55,-12.449899597988733\n1.6,-12.649110640673518\n1.65,-12.84523257866513\n1.7,-13.038404810405297\n1.75,-13.228756555322953\n1.8,-13.416407864998739\n1.85,-13.601470508735442\n1.9,-13.784048752090222\n1.95,-13.96424004376894\n2,-14.142135623730951\n2.05,-14.317821063276352\n2.1,-14.49137674618944\n2.15,-14.66287829861518\n2.2,-14.832396974191326\n2.25,-15\n2.3,-15.1657508881031\n2.35,-15.329709716755893\n2.4,-15.491933384829668\n2.45,-15.652475842498529\n2.5,-15.811388300841898\n2.55,-15.968719422671311\n2.6,-16.124515496597102\n2.65,-16.278820596099706\n2.7,-16.431676725154986\n2.75,-16.583123951776997\n2.8,-16.73320053068151\n2.85,-16.881943016134134\n2.9,-17.0293863659264\n2.95,-17.175564037317667\n3,-17.32050807568877\n3.05,-17.46424919657298\n3.1,-17.60681686165901\n3.15,-17.74823934929885\n3.2,-17.88854381999832\n3.25,-18.027756377319946\n3.3,-18.16590212458495\n3.35,-18.303005217723125\n3.4,-18.439088914585774\n3.45,-18.57417562100671\n3.5,-18.708286933869708\n3.55,-18.84144368141677\n3.6,-18.973665961010276\n3.65,-19.1049731745428\n3.7,-19.235384061671347\n3.75,-19.364916731037084\n3.8,-19.493588689617926\n3.85,-19.621416870348586\n3.9,-19.748417658131498\n3.95,-19.87460691435179\n4,-20\n4.05,-20.124611797498105\n4.1,-20.248456731316583\n4.15,-20.37154878746336\n4.2,-20.4939015319192\n4.25,-20.615528128088304\n4.3,-20.73644135332772\n4.35,-20.85665361461421\n4.4,-20.976176963403034\n4.45,-21.095023109728984\n4.5,-21.213203435596423\n4.55,-21.330729007701542\n4.6,-21.447610589527216\n4.65,-21.563858652847827\n4.7,-21.6794833886788\n4.75,-21.79449471770337\n4.8,-21.90890230020664\n4.85,-22.022715545545243\n4.9,-22.135943621178654\n4.95,-22.24859546128699\n5,-22.360679774997898\n5.05,-22.47220505424423\n5.1,-22.58317958127243\n5.15,-22.693611435820436\n5.2,-22.803508501982762\n5.25,-22.9128784747792\n5.3,-23.021728866442675\n5.35,-23.130067012440755\n5.4,-23.237900077244504\n5.45,-23.345235059857504\n5.5,-23.45207879911715\n5.55,-23.55843797877949\n5.6,-23.664319132398465\n5.65,-23.769728648009426\n5.7,-23.874672772626646\n5.75,-23.979157616563597\n5.8,-24.08318915758459\n5.85,-24.186773244895647\n5.9,-24.289915602982237\n5.95,-24.392621835300936\n6,-24.49489742783178\n6.05,-24.596747752497684\n6.1,-24.698178070456937\n6.15,-24.79919353527449\n6.2,-24.899799195977465\n6.25,-25\n6.3,-25.099800796022265\n6.35,-25.199206336708304\n6.4,-25.298221281347036\n6.45,-25.39685019840059\n6.5,-25.495097567963924\n6.55,-25.592967784139454\n6.6,-25.69046515733026\n6.65,-25.787593916455258\n6.7,-25.88435821108957\n6.75,-25.98076211353316\n6.8,-26.076809620810593\n6.85,-26.1725046566048\n6.9,-26.267851073127396\n6.95,-26.362852652928133\n7,-26.457513110645905\n7.05,-26.551836094703507\n7.1,-26.645825188948457\n7.15,-26.739483914241873\n7.2,-26.832815729997478\n7.25,-26.92582403567252\n7.3,-27.018512172212592\n7.35,-27.11088342345192\n7.4,-27.202941017470884\n7.45,-27.294688127912362", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "D", "scenarioId": "csv_content" @@ -450,7 +445,9 @@ "type": "xychart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "gridPos": { "h": 7, "w": 3, @@ -471,7 +468,9 @@ "type": "text" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -558,8 +557,7 @@ { "csvFileName": "flight_info_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -569,7 +567,9 @@ "type": "xychart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -702,8 +702,7 @@ { "csvFileName": "automobiles.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -714,16 +713,16 @@ { "id": "partitionByValues", "options": { - "fields": [ - "Origin" - ] + "fields": ["Origin"] } } ], "type": "xychart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -856,8 +855,7 @@ { "csvFileName": "automobiles.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -868,9 +866,7 @@ { "id": "partitionByValues", "options": { - "fields": [ - "Origin" - ] + "fields": ["Origin"] } } ], @@ -932,9 +928,7 @@ "id": 11, "options": { "dims": { - "exclude": [ - "co TLM0100" - ], + "exclude": ["co TLM0100"], "x": "humidity TLM0100" }, "legend": { @@ -969,52 +963,20 @@ "data": { "values": [ [ - 1686898151000, - 1686898161000, - 1686898171000, - 1686898181000, - 1686898191000, - 1686898201000, - 1686898211000, - 1686898221000, - 1686898231000, - 1686898241000 + 1686898151000, 1686898161000, 1686898171000, 1686898181000, 1686898191000, 1686898201000, + 1686898211000, 1686898221000, 1686898231000, 1686898241000 ], [ - 0.4860747509084685, - 0.4790778553981873, - 0.4597786615711249, - 0.4478751241705323, - 0.44020548182152397, - 0.4569020188814074, - 0.4655250429581913, - 0.4819032762634117, - 0.491365303224968, - 0.5092239049148886 + 0.4860747509084685, 0.4790778553981873, 0.4597786615711249, 0.4478751241705323, 0.44020548182152397, + 0.4569020188814074, 0.4655250429581913, 0.4819032762634117, 0.491365303224968, 0.5092239049148886 ], [ - 35.084960222673146, - 35.089101898649055, - 35.130020139289115, - 35.10251705413486, - 35.08184755996438, - 35.04582600108574, - 35.09077388700681, - 35.04096375315356, - 35.05647864027338, - 35.091800720894916 + 35.084960222673146, 35.089101898649055, 35.130020139289115, 35.10251705413486, 35.08184755996438, + 35.04582600108574, 35.09077388700681, 35.04096375315356, 35.05647864027338, 35.091800720894916 ], [ - 71.2187151336704, - 71.24617135003214, - 71.21726829714834, - 71.26528218716341, - 71.26084702358875, - 71.24054378677393, - 71.27884802991244, - 71.29783163616926, - 71.33230999794793, - 71.34975514559837 + 71.2187151336704, 71.24617135003214, 71.21726829714834, 71.26528218716341, 71.26084702358875, + 71.24054378677393, 71.27884802991244, 71.29783163616926, 71.33230999794793, 71.34975514559837 ] ] }, @@ -1068,10 +1030,7 @@ ], "meta": { "executedQueryString": "import \"influxdata/influxdb/sample\"\nimport \"influxdata/influxdb/schema\"\n\nsample.data(set: \"airSensor\")\n |> limit(n: 10)\n |> group(columns: [\"sensor_id\"])\n |> schema.fieldsAsCols()\n", - "typeVersion": [ - 0, - 0 - ] + "typeVersion": [0, 0] }, "refId": "A" } @@ -1080,52 +1039,21 @@ "data": { "values": [ [ - 1686898151000, - 1686898161000, - 1686898171000, - 1686898181000, - 1686898191000, - 1686898201000, - 1686898211000, - 1686898221000, - 1686898231000, - 1686898241000 + 1686898151000, 1686898161000, 1686898171000, 1686898181000, 1686898191000, 1686898201000, + 1686898211000, 1686898221000, 1686898231000, 1686898241000 ], [ - 0.4964171323208575, - 0.48257922637952133, - 0.46567087322576145, - 0.4467650568596856, - 0.4417772514767169, - 0.4341379534638706, - 0.439345038257859, - 0.43452737707188627, - 0.42417500678639164, + 0.4964171323208575, 0.48257922637952133, 0.46567087322576145, 0.4467650568596856, + 0.4417772514767169, 0.4341379534638706, 0.439345038257859, 0.43452737707188627, 0.42417500678639164, 0.40704613738954887 ], [ - 34.92662088456207, - 34.91464944732493, - 34.95985887959429, - 34.929238294894844, - 34.954103486412336, - 34.98895514808448, - 35.03476240219413, - 35.028863365125844, - 35.03717014192905, - 35.00775919996651 + 34.92662088456207, 34.91464944732493, 34.95985887959429, 34.929238294894844, 34.954103486412336, + 34.98895514808448, 35.03476240219413, 35.028863365125844, 35.03717014192905, 35.00775919996651 ], [ - 71.83521495327129, - 71.83370684393908, - 71.83712160725877, - 71.88299650060345, - 71.90526594972503, - 71.8631768515712, - 71.85577028152356, - 71.89245169322045, - 71.93606971457449, - 71.96164771829956 + 71.83521495327129, 71.83370684393908, 71.83712160725877, 71.88299650060345, 71.90526594972503, + 71.8631768515712, 71.85577028152356, 71.89245169322045, 71.93606971457449, 71.96164771829956 ] ] }, @@ -1184,52 +1112,20 @@ "data": { "values": [ [ - 1686898151000, - 1686898161000, - 1686898171000, - 1686898181000, - 1686898191000, - 1686898201000, - 1686898211000, - 1686898221000, - 1686898231000, - 1686898241000 + 1686898151000, 1686898161000, 1686898171000, 1686898181000, 1686898191000, 1686898201000, + 1686898211000, 1686898221000, 1686898231000, 1686898241000 ], [ - 0.4870365157212326, - 0.5032215395360725, - 0.5035259485542879, - 0.4841798164121083, - 0.483812619615984, - 0.4882993499867786, - 0.4719009580435705, - 0.4700689455810135, - 0.48112413053169706, - 0.4691106107162724 + 0.4870365157212326, 0.5032215395360725, 0.5035259485542879, 0.4841798164121083, 0.483812619615984, + 0.4882993499867786, 0.4719009580435705, 0.4700689455810135, 0.48112413053169706, 0.4691106107162724 ], [ - 34.86359615237462, - 34.84629630959152, - 34.81771460191974, - 34.854640808896036, - 34.86699022367547, - 34.864319179513096, - 34.86915527122888, - 34.89889649251399, - 34.86576388906259, - 34.88622805723735 + 34.86359615237462, 34.84629630959152, 34.81771460191974, 34.854640808896036, 34.86699022367547, + 34.864319179513096, 34.86915527122888, 34.89889649251399, 34.86576388906259, 34.88622805723735 ], [ - 72.03972207916735, - 72.05566134520713, - 72.08473708469143, - 72.07306942754916, - 72.0427409958616, - 72.04536459775873, - 72.09400368933838, - 72.14293243585941, - 72.18840859469728, - 72.15524663568557 + 72.03972207916735, 72.05566134520713, 72.08473708469143, 72.07306942754916, 72.0427409958616, + 72.04536459775873, 72.09400368933838, 72.14293243585941, 72.18840859469728, 72.15524663568557 ] ] }, @@ -1288,52 +1184,21 @@ "data": { "values": [ [ - 1686898151000, - 1686898161000, - 1686898171000, - 1686898181000, - 1686898191000, - 1686898201000, - 1686898211000, - 1686898221000, - 1686898231000, - 1686898241000 + 1686898151000, 1686898161000, 1686898171000, 1686898181000, 1686898191000, 1686898201000, + 1686898211000, 1686898221000, 1686898231000, 1686898241000 ], [ - 0.3979338437168368, - 0.4117117830425588, - 0.4000376537804249, - 0.40114553332960723, - 0.3909759394807085, - 0.38213452854680874, - 0.37339826793170855, - 0.3624713623472977, - 0.35640734768856297, + 0.3979338437168368, 0.4117117830425588, 0.4000376537804249, 0.40114553332960723, 0.3909759394807085, + 0.38213452854680874, 0.37339826793170855, 0.3624713623472977, 0.35640734768856297, 0.35690557816119645 ], [ - 35.16192242281515, - 35.19891757080395, - 35.23754373785834, - 35.25270355198698, - 35.29525947947623, - 35.272026086051184, - 35.275233467451635, - 35.23834593104291, - 35.25233833634368, - 35.22053598631417 + 35.16192242281515, 35.19891757080395, 35.23754373785834, 35.25270355198698, 35.29525947947623, + 35.272026086051184, 35.275233467451635, 35.23834593104291, 35.25233833634368, 35.22053598631417 ], [ - 71.29169927438586, - 71.32114142326272, - 71.33632903748085, - 71.3064635464553, - 71.26436580075855, - 71.30431517798449, - 71.28861822950174, - 71.26778760430453, - 71.23481860950403, - 71.23084180913762 + 71.29169927438586, 71.32114142326272, 71.33632903748085, 71.3064635464553, 71.26436580075855, + 71.30431517798449, 71.28861822950174, 71.26778760430453, 71.23481860950403, 71.23084180913762 ] ] }, @@ -1392,52 +1257,20 @@ "data": { "values": [ [ - 1686898151000, - 1686898161000, - 1686898171000, - 1686898181000, - 1686898191000, - 1686898201000, - 1686898211000, - 1686898221000, - 1686898231000, - 1686898241000 + 1686898151000, 1686898161000, 1686898171000, 1686898181000, 1686898191000, 1686898201000, + 1686898211000, 1686898221000, 1686898231000, 1686898241000 ], [ - 0.5129015632374951, - 0.552968955740271, - 0.5690444135565038, - 0.6050221760178951, - 0.5943904374498042, - 0.6153588301241533, - 0.6164375823908576, - 0.6059635952981327, - 0.6470283318343141, - 0.6861075098169984 + 0.5129015632374951, 0.552968955740271, 0.5690444135565038, 0.6050221760178951, 0.5943904374498042, + 0.6153588301241533, 0.6164375823908576, 0.6059635952981327, 0.6470283318343141, 0.6861075098169984 ], [ - 35.75385592664215, - 35.753218714107504, - 35.72547059379115, - 35.74553237372676, - 35.73378268235891, - 35.747560005048086, - 35.769867599816735, - 35.73929899563808, - 35.705317880681875, - 35.65611547721327 + 35.75385592664215, 35.753218714107504, 35.72547059379115, 35.74553237372676, 35.73378268235891, + 35.747560005048086, 35.769867599816735, 35.73929899563808, 35.705317880681875, 35.65611547721327 ], [ - 73.64806558624832, - 73.65728412124716, - 73.68805520135102, - 73.65185281162863, - 73.63499402146681, - 73.68359308763364, - 73.64682180062367, - 73.63298265031713, - 73.59096788790947, - 73.6381949597034 + 73.64806558624832, 73.65728412124716, 73.68805520135102, 73.65185281162863, 73.63499402146681, + 73.68359308763364, 73.64682180062367, 73.63298265031713, 73.59096788790947, 73.6381949597034 ] ] }, @@ -1496,52 +1329,20 @@ "data": { "values": [ [ - 1686898151000, - 1686898161000, - 1686898171000, - 1686898181000, - 1686898191000, - 1686898201000, - 1686898211000, - 1686898221000, - 1686898231000, - 1686898241000 + 1686898151000, 1686898161000, 1686898171000, 1686898181000, 1686898191000, 1686898201000, + 1686898211000, 1686898221000, 1686898231000, 1686898241000 ], [ - 0.5082489903097206, - 0.525490999229553, - 0.5300688563597754, - 0.5351282770519872, - 0.533437724470923, - 0.5164188260958164, - 0.5134188770545406, - 0.4949993424337248, - 0.4960387472164697, - 0.5046934441184395 + 0.5082489903097206, 0.525490999229553, 0.5300688563597754, 0.5351282770519872, 0.533437724470923, + 0.5164188260958164, 0.5134188770545406, 0.4949993424337248, 0.4960387472164697, 0.5046934441184395 ], [ - 35.24972613768055, - 35.238916979727335, - 35.28758958750148, - 35.26413172906637, - 35.2875488141577, - 35.32420268624064, - 35.2932945023372, - 35.277959228995584, - 35.27901195680498, - 35.27056468599647 + 35.24972613768055, 35.238916979727335, 35.28758958750148, 35.26413172906637, 35.2875488141577, + 35.32420268624064, 35.2932945023372, 35.277959228995584, 35.27901195680498, 35.27056468599647 ], [ - 73.99618150289902, - 74.01973867729899, - 73.97488048626532, - 73.97027021897547, - 73.96055098802299, - 73.94544160099603, - 73.91010608315078, - 73.9594600253564, - 73.93323000030807, - 73.94265737589377 + 73.99618150289902, 74.01973867729899, 73.97488048626532, 73.97027021897547, 73.96055098802299, + 73.94544160099603, 73.91010608315078, 73.9594600253564, 73.93323000030807, 73.94265737589377 ] ] }, @@ -1600,52 +1401,21 @@ "data": { "values": [ [ - 1686898151000, - 1686898161000, - 1686898171000, - 1686898181000, - 1686898191000, - 1686898201000, - 1686898211000, - 1686898221000, - 1686898231000, - 1686898241000 + 1686898151000, 1686898161000, 1686898171000, 1686898181000, 1686898191000, 1686898201000, + 1686898211000, 1686898221000, 1686898231000, 1686898241000 ], [ - 0.4843506884938821, - 0.48132272563110234, - 0.4738268718199932, - 0.4929629619836042, - 0.4730642763470896, - 0.4654986284178103, - 0.47939137148137106, - 0.4729232244284411, - 0.48941836624955776, + 0.4843506884938821, 0.48132272563110234, 0.4738268718199932, 0.4929629619836042, 0.4730642763470896, + 0.4654986284178103, 0.47939137148137106, 0.4729232244284411, 0.48941836624955776, 0.49438537058971027 ], [ - 35.6843507637763, - 35.67052290561625, - 35.651191124511904, - 35.682694567957775, - 35.71754463951193, - 35.73271359197846, - 35.76201128140823, - 35.72031962293351, - 35.76508898680512, - 35.77376488207177 + 35.6843507637763, 35.67052290561625, 35.651191124511904, 35.682694567957775, 35.71754463951193, + 35.73271359197846, 35.76201128140823, 35.72031962293351, 35.76508898680512, 35.77376488207177 ], [ - 75.28536533620796, - 75.3203884403274, - 75.32915092826639, - 75.3260291876276, - 75.29613126188146, - 75.31098782530198, - 75.27434784939884, - 75.30929861509146, - 75.32818662869892, - 75.33650169518009 + 75.28536533620796, 75.3203884403274, 75.32915092826639, 75.3260291876276, 75.29613126188146, + 75.31098782530198, 75.27434784939884, 75.30929861509146, 75.32818662869892, 75.33650169518009 ] ] }, @@ -1704,52 +1474,20 @@ "data": { "values": [ [ - 1686898151000, - 1686898161000, - 1686898171000, - 1686898181000, - 1686898191000, - 1686898201000, - 1686898211000, - 1686898221000, - 1686898231000, - 1686898241000 + 1686898151000, 1686898161000, 1686898171000, 1686898181000, 1686898191000, 1686898201000, + 1686898211000, 1686898221000, 1686898231000, 1686898241000 ], [ - 0.39373421338928505, - 0.40929905142175416, - 0.39727569840202215, - 0.415834035946844, - 0.413865826090914, - 0.4271278288285897, - 0.435277474574255, - 0.4480042029285831, - 0.462641109361364, - 0.4566678920783633 + 0.39373421338928505, 0.40929905142175416, 0.39727569840202215, 0.415834035946844, 0.413865826090914, + 0.4271278288285897, 0.435277474574255, 0.4480042029285831, 0.462641109361364, 0.4566678920783633 ], [ - 35.86322585633077, - 35.88732568460068, - 35.87553827435961, - 35.84063967239316, - 35.813642046057005, - 35.8569165461967, - 35.80924651587166, - 35.80599199551315, - 35.75906423980926, - 35.79948361256034 + 35.86322585633077, 35.88732568460068, 35.87553827435961, 35.84063967239316, 35.813642046057005, + 35.8569165461967, 35.80924651587166, 35.80599199551315, 35.75906423980926, 35.79948361256034 ], [ - 74.78112365229704, - 74.73821283157658, - 74.73019922701285, - 74.73280967321202, - 74.74885460260536, - 74.70880911705714, - 74.73346687605624, - 74.77682413662681, - 74.80562351134131, - 74.82881664528719 + 74.78112365229704, 74.73821283157658, 74.73019922701285, 74.73280967321202, 74.74885460260536, + 74.70880911705714, 74.73346687605624, 74.77682413662681, 74.80562351134131, 74.82881664528719 ] ] }, @@ -1811,7 +1549,9 @@ "type": "xychart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1898,8 +1638,7 @@ { "csvFileName": "flight_info_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -1909,7 +1648,9 @@ "type": "xychart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -1996,8 +1737,7 @@ { "csvFileName": "flight_info_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -2007,7 +1747,9 @@ "type": "xychart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -2100,8 +1842,7 @@ { "csvFileName": "flight_info_by_state.csv", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_file" @@ -2113,11 +1854,7 @@ ], "refresh": "", "schemaVersion": 39, - "tags": [ - "gdev", - "panel-tests", - "graph-ng" - ], + "tags": ["gdev", "panel-tests", "graph-ng"], "templating": { "list": [] }, @@ -2131,4 +1868,4 @@ "uid": "YObbMr44k", "version": 1, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-xychart/xychart-tooltip-color-test.json b/devenv/dev-dashboards/panel-xychart/xychart-tooltip-color-test.json index e92699d02e3..b0ae2a9d76b 100644 --- a/devenv/dev-dashboards/panel-xychart/xychart-tooltip-color-test.json +++ b/devenv/dev-dashboards/panel-xychart/xychart-tooltip-color-test.json @@ -100,8 +100,7 @@ { "csvContent": "x,y,z\n1,2,3\n3,4,5\n5,6,7", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "${DS_GDEV-TESTDATA}" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -189,8 +188,7 @@ { "csvContent": "x,y,z\n1,2,3\n3,4,5\n5,6,7", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "${DS_GDEV-TESTDATA}" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -278,8 +276,7 @@ { "csvContent": "x,y,z\n1,2,3\n3,4,5\n5,6,7", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "${DS_GDEV-TESTDATA}" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -374,8 +371,7 @@ { "csvContent": "x,y,z\n1,2,3\n3,4,5\n5,6,7", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "${DS_GDEV-TESTDATA}" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -470,8 +466,7 @@ { "csvContent": "x,y,z\n1,2,3\n3,4,5\n5,6,7", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "${DS_GDEV-TESTDATA}" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -566,8 +561,7 @@ { "csvContent": "x,y,z\n1,2,3\n3,4,5\n5,6,7", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "${DS_GDEV-TESTDATA}" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -577,7 +571,9 @@ "type": "xychart" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -654,8 +650,7 @@ { "csvContent": "x,y,c\n0,0,0\n50,50,25\n100,100,50", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -681,4 +676,4 @@ "uid": "cb67db43-dd72-4ada-a313-53f46c20adcc", "version": 1, "weekStart": "" -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/scenarios/relative_time_zone_support.json b/devenv/dev-dashboards/scenarios/relative_time_zone_support.json index 5fcf0e10597..e50ababea25 100644 --- a/devenv/dev-dashboards/scenarios/relative_time_zone_support.json +++ b/devenv/dev-dashboards/scenarios/relative_time_zone_support.json @@ -24,8 +24,7 @@ "panels": [ { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -68,9 +67,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -79,8 +76,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -92,8 +88,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -136,9 +131,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -147,8 +140,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", diff --git a/devenv/dev-dashboards/scenarios/slow_queries_and_annotations.json b/devenv/dev-dashboards/scenarios/slow_queries_and_annotations.json index 8966137b55e..a62b9452a65 100644 --- a/devenv/dev-dashboards/scenarios/slow_queries_and_annotations.json +++ b/devenv/dev-dashboards/scenarios/slow_queries_and_annotations.json @@ -34,7 +34,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 7, @@ -118,7 +120,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 7, @@ -202,7 +206,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 7, @@ -286,7 +292,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 7, @@ -370,7 +378,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 7, @@ -454,7 +464,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 5, @@ -538,7 +550,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 5, @@ -622,7 +636,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 5, @@ -706,7 +722,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 5, @@ -790,7 +808,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 5, @@ -874,7 +894,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 5, @@ -958,7 +980,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 6, @@ -1042,7 +1066,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "fill": 1, "gridPos": { "h": 6, diff --git a/devenv/dev-dashboards/scenarios/time_zone_support.json b/devenv/dev-dashboards/scenarios/time_zone_support.json index cc1f81ee221..23b3fc020f7 100644 --- a/devenv/dev-dashboards/scenarios/time_zone_support.json +++ b/devenv/dev-dashboards/scenarios/time_zone_support.json @@ -23,7 +23,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fieldConfig": { @@ -121,7 +123,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fieldConfig": { @@ -219,7 +223,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fieldConfig": { @@ -328,7 +334,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fieldConfig": { @@ -448,7 +456,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "editable": true, "error": false, "fieldConfig": { @@ -561,7 +571,9 @@ "bars": false, "dashLength": 10, "dashes": false, - "datasource": "gdev-testdata", + "datasource": { + "type": "grafana-testdata-datasource" + }, "decimals": 3, "fieldConfig": { "defaults": { diff --git a/devenv/dev-dashboards/transforms/config-from-query.json b/devenv/dev-dashboards/transforms/config-from-query.json index cb65f966667..c572e80c438 100644 --- a/devenv/dev-dashboards/transforms/config-from-query.json +++ b/devenv/dev-dashboards/transforms/config-from-query.json @@ -29,8 +29,7 @@ "panels": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -109,8 +108,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "max": 100, @@ -123,8 +121,7 @@ "alias": "", "csvContent": "min,max,threshold1\n1000,1000,8000\n0,100,80\n\n", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "config", "scenarioId": "csv_content" @@ -144,8 +141,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -203,9 +199,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -215,8 +209,7 @@ { "csvContent": "Name, Value, SensorA, MyUnit, MyColor\nGoogle, 10, 50, km/h, blue\nGoogle, 100, 100,km/h, orange\n", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "A", @@ -252,8 +245,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -312,9 +304,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -324,8 +314,7 @@ { "csvContent": "ID, DisplayText\n21412312312, Homer\n12421412413, Simpsons \n12321312313, Bart", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "A", @@ -356,8 +345,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -416,9 +404,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -428,8 +414,7 @@ { "csvContent": "Value, Color\nOK, blue\nPretty bad, red\nYay it's green, green\nSomething is off, orange\nNo idea, #88AA00\nAm I purple?, purple", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "A", @@ -464,8 +449,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -508,9 +492,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -520,8 +502,7 @@ { "csvContent": "ID, Value\n21412312312, 100\n12421412413, 20\n12321312313, 10", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "A", @@ -552,8 +533,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -633,8 +613,7 @@ { "csvContent": "ID, Value\nA21412312312, 100\nA12421412413, 20\nA12321312313, 10\n", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "data", @@ -643,8 +622,7 @@ { "csvContent": "ID, DisplayText\nA21412312312, Homer\nA12421412413, Marge \nA12321312313, Bart", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "mappings", @@ -679,9 +657,7 @@ }, { "datasource": { - "default": true, - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -757,8 +733,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"meta\": {\n \"typeVersion\": [\n 0,\n 0\n ],\n \"custom\": {\n \"customStat\": 10\n }\n },\n \"fields\": [\n {\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n },\n \"config\": {\n \"interval\": 300000\n }\n },\n {\n \"name\": \"A-series\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"labels\": {},\n \"config\": {}\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1732120345536,\n 1732120645536,\n 1732120945536,\n 1732121245536,\n 1732121545536,\n 1732121845536,\n 1732122145536,\n 1732122445536,\n 1732122745536,\n 1732123045536,\n 1732123345536,\n 1732123645536,\n 1732123945536,\n 1732124245536,\n 1732124545536,\n 1732124845536,\n 1732125145536,\n 1732125445536,\n 1732125745536,\n 1732126045536,\n 1732126345536,\n 1732126645536,\n 1732126945536,\n 1732127245536,\n 1732127545536,\n 1732127845536,\n 1732128145536,\n 1732128445536,\n 1732128745536,\n 1732129045536,\n 1732129345536,\n 1732129645536,\n 1732129945536,\n 1732130245536,\n 1732130545536,\n 1732130845536,\n 1732131145536,\n 1732131445536,\n 1732131745536,\n 1732132045536,\n 1732132345536,\n 1732132645536,\n 1732132945536,\n 1732133245536,\n 1732133545536,\n 1732133845536,\n 1732134145536,\n 1732134445536,\n 1732134745536,\n 1732135045536,\n 1732135345536,\n 1732135645536,\n 1732135945536,\n 1732136245536,\n 1732136545536,\n 1732136845536,\n 1732137145536,\n 1732137445536,\n 1732137745536,\n 1732138045536,\n 1732138345536,\n 1732138645536,\n 1732138945536,\n 1732139245536,\n 1732139545536,\n 1732139845536,\n 1732140145536,\n 1732140445536,\n 1732140745536,\n 1732141045536,\n 1732141345536,\n 1732141645536\n ],\n [\n 36.67835770082578,\n 35.674537924065,\n 8.339763723800829,\n 16.313291374141446,\n 66.05915891584247,\n 55.975417240601566,\n 33.75563648171818,\n 10.561077849025175,\n 20.31936089572975,\n 26.11219409670694,\n 57.542750561307564,\n 67.10954340535248,\n 82.95323961635275,\n 100.9691805551439,\n 59.829706792214644,\n 94.58723331927925,\n 89.3082374466047,\n 58.69065135820439,\n 97.144192150251,\n 139.99199318295675,\n 157.9473973408396,\n 177.94452058033198,\n 188.84065573954362,\n 154.3930906887033,\n 130.14406878049226,\n 116.65818233680316,\n 100.96041794526472,\n 144.65142921584447,\n 175.75178611497054,\n 203.55271609883386,\n 238.4931714915047,\n 253.38754249911452,\n 271.1735238723396,\n 258.54418620287515,\n 260.8463123020904,\n 216.10614084307323,\n 253.30389406688175,\n 249.37108721413884,\n 243.7226799137106,\n 216.74579233434042,\n 262.50043010512826,\n 238.71564300219498,\n 218.3552317737898,\n 195.6154411937393,\n 154.1987522722987,\n 124.00066408416897,\n 146.6474694384778,\n 101.68405646311294,\n 104.5791139459948,\n 85.39428966503652,\n 78.45166775446714,\n 56.285707917841535,\n 36.22861441808941,\n 35.098428846082555,\n 68.67835646605371,\n 101.67142528391042,\n 151.04038339587296,\n 114.77414457402928,\n 72.65341528313934,\n 113.42643748928826,\n 151.09282092262364,\n 163.24422498859587,\n 183.86606816236363,\n 230.24678524811478,\n 205.94887669562561,\n 211.24387656976373,\n 217.26738326873522,\n 214.66898480692646,\n 206.95531499977153,\n 194.19724584765092,\n 146.16071387746757,\n 188.30193538777615\n ]\n ]\n }\n }\n]", "refId": "A", @@ -790,10 +765,7 @@ ], "refresh": "", "schemaVersion": 40, - "tags": [ - "gdev", - "transform" - ], + "tags": ["gdev", "transform"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/transforms/extract-json-paths.json b/devenv/dev-dashboards/transforms/extract-json-paths.json index a9141cc7f4d..337ae2c8fbd 100644 --- a/devenv/dev-dashboards/transforms/extract-json-paths.json +++ b/devenv/dev-dashboards/transforms/extract-json-paths.json @@ -14,13 +14,7 @@ "target": { "limit": 100, "matchAny": false, - "tags": [ - "gdev", - "transform", - "transformations", - "extract", - "json" - ], + "tags": ["gdev", "transform", "transformations", "extract", "json"], "type": "dashboard" }, "type": "dashboard" @@ -66,8 +60,7 @@ } ], "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "pluginVersion": "9.4.0-pre", "fieldConfig": { @@ -100,9 +93,7 @@ "showHeader": true, "footer": { "show": false, - "reducer": [ - "sum" - ], + "reducer": ["sum"], "countRows": false, "fields": "" } @@ -110,8 +101,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[{\"schema\":{\"refId\":\"A\",\"meta\":{\"channel\":\"ds/bHGPS1h4z/1s/test\",\"transformations\":[\"extractFields\",\"extractFields\",\"extractFields\"]},\"fields\":[{\"name\":\"Time\",\"type\":\"time\",\"config\":{\"custom\":{\"align\":\"auto\",\"displayMode\":\"auto\",\"inspect\":false},\"color\":{\"mode\":\"thresholds\"},\"thresholds\":{\"mode\":\"absolute\",\"steps\":[{\"color\":\"green\",\"value\":null},{\"color\":\"red\",\"value\":80}]}}},{\"name\":\"Value\",\"type\":\"other\",\"config\":{\"custom\":{\"align\":\"auto\",\"displayMode\":\"auto\",\"inspect\":false},\"color\":{\"mode\":\"thresholds\"},\"mappings\":[],\"thresholds\":{\"mode\":\"absolute\",\"steps\":[{\"color\":\"green\",\"value\":null},{\"color\":\"red\",\"value\":80}]}}}]},\"data\":{\"values\":[[1673543683471,1673543689063,1673543695050],[[\"2023-01-12T17:14:44.419Z\",62,141,79,29,79,-29,29,{\"testdata\":{\"source1\":{\"value1\":9,\"value2\":18},\"source2\":[[0,1,2,3,4,5,6,7,8,9],[7,11,13,17,19,23,27,29]]}}],[\"2023-01-12T17:14:50.050Z\",62,143,81,29,81,-29,29,{\"testdata\":{\"source1\":{\"value1\":10,\"value2\":20},\"source2\":[[1,2,3,4,5,6,7,8,9,10],[11,13,17,19,23,27,29,31]]}}],[\"2023-01-12T17:14:55.050Z\",61,146,80,22,85,-28,28,{\"testdata\":{\"source1\":{\"value1\":11,\"value2\":22},\"source2\":[[3,4,5,6,7,8,9,10,11,12],[13,17,19,23,27,29,31,37,41]]}}]]]}}]", "refId": "A", @@ -148,8 +138,7 @@ } ], "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "pluginVersion": "9.4.0-pre", "fieldConfig": { @@ -219,8 +208,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[{\"schema\":{\"refId\":\"A\",\"meta\":{\"channel\":\"ds/bHGPS1h4z/1s/test\",\"transformations\":[\"extractFields\",\"extractFields\",\"extractFields\"]},\"fields\":[{\"name\":\"Time\",\"type\":\"time\",\"config\":{\"custom\":{\"align\":\"auto\",\"displayMode\":\"auto\",\"inspect\":false},\"color\":{\"mode\":\"thresholds\"},\"thresholds\":{\"mode\":\"absolute\",\"steps\":[{\"color\":\"green\",\"value\":null},{\"color\":\"red\",\"value\":80}]}}},{\"name\":\"Value\",\"type\":\"other\",\"config\":{\"custom\":{\"align\":\"auto\",\"displayMode\":\"auto\",\"inspect\":false},\"color\":{\"mode\":\"thresholds\"},\"mappings\":[],\"thresholds\":{\"mode\":\"absolute\",\"steps\":[{\"color\":\"green\",\"value\":null},{\"color\":\"red\",\"value\":80}]}}}]},\"data\":{\"values\":[[1673543683471,1673543689063,1673543695050],[[\"2023-01-12T17:14:44.419Z\",62,141,79,29,79,-29,29,{\"testdata\":{\"source1\":{\"value1\":9,\"value2\":18},\"source2\":[[0,1,2,3,4,5,6,7,8,9],[7,11,13,17,19,23,27,29]]}}],[\"2023-01-12T17:14:50.050Z\",62,143,81,29,81,-29,29,{\"testdata\":{\"source1\":{\"value1\":10,\"value2\":20},\"source2\":[[1,2,3,4,5,6,7,8,9,10],[11,13,17,19,23,27,29,31]]}}],[\"2023-01-12T17:14:55.050Z\",61,146,80,22,85,-28,28,{\"testdata\":{\"source1\":{\"value1\":11,\"value2\":22},\"source2\":[[3,4,5,6,7,8,9,10,11,12],[13,17,19,23,27,29,31,37,41]]}}]]]}}]", "refId": "A", @@ -241,8 +229,7 @@ "title": "Raw data", "transformations": [], "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "pluginVersion": "9.4.0-pre", "fieldConfig": { @@ -275,9 +262,7 @@ "showHeader": true, "footer": { "show": false, - "reducer": [ - "sum" - ], + "reducer": ["sum"], "countRows": false, "fields": "" } @@ -285,8 +270,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "gdev-testdata" + "type": "grafana-testdata-datasource" }, "rawFrameContent": "[{\"schema\":{\"refId\":\"A\",\"meta\":{\"channel\":\"ds/bHGPS1h4z/1s/test\",\"transformations\":[\"extractFields\",\"extractFields\",\"extractFields\"]},\"fields\":[{\"name\":\"Time\",\"type\":\"time\",\"config\":{\"custom\":{\"align\":\"auto\",\"displayMode\":\"auto\",\"inspect\":false},\"color\":{\"mode\":\"thresholds\"},\"thresholds\":{\"mode\":\"absolute\",\"steps\":[{\"color\":\"green\",\"value\":null},{\"color\":\"red\",\"value\":80}]}}},{\"name\":\"Value\",\"type\":\"other\",\"config\":{\"custom\":{\"align\":\"auto\",\"displayMode\":\"auto\",\"inspect\":false},\"color\":{\"mode\":\"thresholds\"},\"mappings\":[],\"thresholds\":{\"mode\":\"absolute\",\"steps\":[{\"color\":\"green\",\"value\":null},{\"color\":\"red\",\"value\":80}]}}}]},\"data\":{\"values\":[[1673543683471,1673543689063,1673543695050],[[\"2023-01-12T17:14:44.419Z\",62,141,79,29,79,-29,29,{\"testdata\":{\"source1\":{\"value1\":9,\"value2\":18},\"source2\":[[0,1,2,3,4,5,6,7,8,9],[7,11,13,17,19,23,27,29]]}}],[\"2023-01-12T17:14:50.050Z\",62,143,81,29,81,-29,29,{\"testdata\":{\"source1\":{\"value1\":10,\"value2\":20},\"source2\":[[1,2,3,4,5,6,7,8,9,10],[11,13,17,19,23,27,29,31]]}}],[\"2023-01-12T17:14:55.050Z\",61,146,80,22,85,-28,28,{\"testdata\":{\"source1\":{\"value1\":11,\"value2\":22},\"source2\":[[3,4,5,6,7,8,9,10,11,12],[13,17,19,23,27,29,31,37,41]]}}]]]}}]", "refId": "A", @@ -298,10 +282,7 @@ ], "revision": 1, "schemaVersion": 37, - "tags": [ - "gdev", - "transform" - ], + "tags": ["gdev", "transform"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/transforms/filter.json b/devenv/dev-dashboards/transforms/filter.json index e06a0520a14..d1d38914f03 100644 --- a/devenv/dev-dashboards/transforms/filter.json +++ b/devenv/dev-dashboards/transforms/filter.json @@ -1,170 +1,158 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 1394, - "links": [], - "liveNow": false, - "panels": [ + "annotations": { + "list": [ { + "builtIn": 1, "datasource": { - "uid": "PD8C576611E62080A", - "type": "testdata" + "type": "grafana", + "uid": "-- Grafana --" }, - "fieldConfig": { - "defaults": { - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "color": { - "mode": "thresholds" - } - }, - "overrides": [] + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 0 - }, - "id": 2, - "targets": [ - { - "scenarioId": "csv_content", - "refId": "A", - "datasource": { - "uid": "PD8C576611E62080A", - "type": "testdata" - }, - "csvContent": "AAA\n1\n2\n3\n4" - }, - { - "scenarioId": "csv_content", - "refId": "B", - "datasource": { - "uid": "PD8C576611E62080A", - "type": "testdata" - }, - "csvContent": "BBB\n1\n2\n3\n4\n", - "hide": false - } - ], - "title": "Transformer query filters", - "type": "table", - "transformations": [ - { - "id": "reduce", - "options": { - "reducers": [ - "min" - ], - "mode": "reduceFields", - "includeTimeField": false - }, - "filter": { - "id": "byRefId", - "options": "A" - } - }, - { - "id": "reduce", - "options": { - "reducers": [ - "max" - ], - "mode": "reduceFields", - "includeTimeField": false - }, - "filter": { - "id": "byRefId", - "options": "B" - } - }, - { - "id": "concatenate", - "options": {} - }, - { - "id": "organize", - "options": { - "excludeByName": {}, - "indexByName": {}, - "renameByName": { - "AAA": "Min from Query A", - "BBB": "Max from Query B" - } - } - } - ], - "options": { - "showHeader": true, - "footer": { - "show": false, - "reducer": [ - "sum" - ], - "countRows": false, - "fields": "" - }, - "frameIndex": 0 - }, - "pluginVersion": "9.4.0-pre" + "type": "dashboard" } - ], - "schemaVersion": 37, - "tags": [ - "gdev", - "transform" - ], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Transforms - Filters", - "uid": "fGWBVW4k" - } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1394, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "color": { + "mode": "thresholds" + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "targets": [ + { + "scenarioId": "csv_content", + "refId": "A", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "csvContent": "AAA\n1\n2\n3\n4" + }, + { + "scenarioId": "csv_content", + "refId": "B", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "csvContent": "BBB\n1\n2\n3\n4\n", + "hide": false + } + ], + "title": "Transformer query filters", + "type": "table", + "transformations": [ + { + "id": "reduce", + "options": { + "reducers": ["min"], + "mode": "reduceFields", + "includeTimeField": false + }, + "filter": { + "id": "byRefId", + "options": "A" + } + }, + { + "id": "reduce", + "options": { + "reducers": ["max"], + "mode": "reduceFields", + "includeTimeField": false + }, + "filter": { + "id": "byRefId", + "options": "B" + } + }, + { + "id": "concatenate", + "options": {} + }, + { + "id": "organize", + "options": { + "excludeByName": {}, + "indexByName": {}, + "renameByName": { + "AAA": "Min from Query A", + "BBB": "Max from Query B" + } + } + } + ], + "options": { + "showHeader": true, + "footer": { + "show": false, + "reducer": ["sum"], + "countRows": false, + "fields": "" + }, + "frameIndex": 0 + }, + "pluginVersion": "9.4.0-pre" + } + ], + "schemaVersion": 37, + "tags": ["gdev", "transform"], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Transforms - Filters", + "uid": "fGWBVW4k" +} diff --git a/devenv/dev-dashboards/transforms/join-by-field.json b/devenv/dev-dashboards/transforms/join-by-field.json index 2c254fc929e..f1a98a4b8d8 100644 --- a/devenv/dev-dashboards/transforms/join-by-field.json +++ b/devenv/dev-dashboards/transforms/join-by-field.json @@ -42,7 +42,9 @@ "type": "row" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -116,8 +118,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk", @@ -168,9 +169,7 @@ "options": { "footer": { "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -230,9 +229,7 @@ "options": { "footer": { "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -271,7 +268,9 @@ "type": "row" }, { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -308,9 +307,7 @@ "options": { "footer": { "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "frameIndex": 0, @@ -321,8 +318,7 @@ { "csvContent": "OrderID,CustomerID,Time\n100,A,10000\n101,B,20000\n102,C,30000", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "Orders", "scenarioId": "csv_content" @@ -330,8 +326,7 @@ { "csvContent": "CustomerID,Name,Country\nA,Customer A,USA\nB,Customer B,Germany\nC,Customer C,Spain\nD,Customer D,Canada", "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "refId": "Customers", @@ -383,9 +378,7 @@ "options": { "footer": { "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "frameIndex": 1, @@ -472,9 +465,7 @@ "options": { "footer": { "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "frameIndex": 0, @@ -570,9 +561,7 @@ "options": { "footer": { "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "frameIndex": 0, @@ -604,10 +593,7 @@ } ], "schemaVersion": 37, - "tags": [ - "gdev", - "transform" - ], + "tags": ["gdev", "transform"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/transforms/join-by-labels.json b/devenv/dev-dashboards/transforms/join-by-labels.json index 7b546b58c80..0a99497b823 100644 --- a/devenv/dev-dashboards/transforms/join-by-labels.json +++ b/devenv/dev-dashboards/transforms/join-by-labels.json @@ -29,7 +29,9 @@ "liveNow": false, "panels": [ { - "datasource": { "type": "testdata" }, + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -65,9 +67,7 @@ "justifyMode": "auto", "orientation": "auto", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -77,8 +77,7 @@ "targets": [ { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "labels": "site=A,measure=speed,state=CA", "refId": "A", @@ -86,8 +85,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "labels": "site=B,measure=speed,state=OR", @@ -96,8 +94,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "labels": "site=B,measure=temp", @@ -106,8 +103,7 @@ }, { "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "hide": false, "labels": "site=A,measure=temp", @@ -160,9 +156,7 @@ "options": { "footer": { "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "frameIndex": 2, @@ -225,9 +219,7 @@ "options": { "footer": { "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -248,9 +240,7 @@ { "id": "joinByLabels", "options": { - "join": [ - "site" - ], + "join": ["site"], "value": "measure" } } @@ -299,9 +289,7 @@ "options": { "footer": { "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -330,10 +318,7 @@ } ], "schemaVersion": 37, - "tags": [ - "gdev", - "transform" - ], + "tags": ["gdev", "transform"], "templating": { "list": [] }, diff --git a/devenv/dev-dashboards/transforms/regression-analysis.json b/devenv/dev-dashboards/transforms/regression-analysis.json index f9330ff55cf..dc48d3fd498 100644 --- a/devenv/dev-dashboards/transforms/regression-analysis.json +++ b/devenv/dev-dashboards/transforms/regression-analysis.json @@ -24,8 +24,7 @@ "panels": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -106,8 +105,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" @@ -132,8 +130,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -214,8 +211,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "random_walk" @@ -239,8 +235,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -322,8 +317,7 @@ { "csvContent": "time, val\n2023-11-20 12:09:00, 1\n2023-11-20 12:09:02, 2\n2023-11-20 12:09:03, 3\n2023-11-20 12:09:04, 4\n2023-11-20 12:09:05, 5\n2023-11-20 12:09:06, 6\n2023-11-20 12:09:07, 2\n2023-11-20 12:09:08, 3\n2023-11-20 12:09:09, 4\n2023-11-20 12:09:10, 1\n2023-11-20 12:09:11, 2\n2023-11-20 12:09:12, 3\n2023-11-20 12:09:13, 4", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -368,8 +362,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -451,8 +444,7 @@ { "csvContent": "time, val\n2023-11-20 12:09:00, 1\n2023-11-20 12:09:02, 2\n2023-11-20 12:09:03, 3\n2023-11-20 12:09:04, 4\n2023-11-20 12:09:05, null\n2023-11-20 12:09:06, 6\n2023-11-20 12:09:07, 2\n2023-11-20 12:09:08, null\n2023-11-20 12:09:09, 4\n2023-11-20 12:09:10, 1\n2023-11-20 12:09:11, 2\n2023-11-20 12:09:12, 3\n2023-11-20 12:09:13, 4", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -498,8 +490,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -618,8 +609,7 @@ { "csvContent": "x,y\n1,4\n2,1\n3,2\n4,-2\n5,6\n3,2\n1,7\n3,9\n6,3\n5,-3\n2,-2\n7,15", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -676,8 +666,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -715,9 +704,7 @@ "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { - "calcs": [ - "lastNotNull" - ], + "calcs": ["lastNotNull"], "fields": "", "values": false }, @@ -756,8 +743,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -864,8 +850,7 @@ { "csvContent": "x, val\n6,2\n8,1\n10,5\n15,1\n22,10\n", "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "csv_content" @@ -909,8 +894,7 @@ }, { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "fieldConfig": { "defaults": { @@ -1028,8 +1012,7 @@ "targets": [ { "datasource": { - "type": "grafana-testdata-datasource", - "uid": "PD8C576611E62080A" + "type": "grafana-testdata-datasource" }, "refId": "A", "scenarioId": "usa", @@ -1072,10 +1055,7 @@ "preload": false, "refresh": "", "schemaVersion": 41, - "tags": [ - "gdev", - "transform" - ], + "tags": ["gdev", "transform"], "templating": { "list": [] }, @@ -1088,4 +1068,4 @@ "title": "Transforms - Regression analysis", "uid": "d2d2bb99-42e4-44b8-b93e-3ad1aae31c6b", "version": 1 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/transforms/reuse.json b/devenv/dev-dashboards/transforms/reuse.json index 8a59840c9a8..f207ab6c9fc 100644 --- a/devenv/dev-dashboards/transforms/reuse.json +++ b/devenv/dev-dashboards/transforms/reuse.json @@ -1,538 +1,525 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 1394, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" }, - "gridPos": { - "h": 3, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 9, - "options": { - "content": "Dashboard queries allow re-using the same results from one panel in another panel context.\n\nThis dashboard shows a single panel that makes a real query and applies transformations. The other panels, all use the same results rather than make their own query requests.", - "mode": "markdown" - }, - "pluginVersion": "9.2.0-pre", - "type": "text" - }, - { - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 18, - "w": 7, - "x": 0, - "y": 3 - }, - "id": 2, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "9.2.0-pre", - "targets": [ - { - "csvFileName": "flight_info_by_state.csv", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "A", - "scenarioId": "csv_file" - }, - { - "csvFileName": "population_by_state.csv", - "datasource": { - "type": "testdata", - "uid": "PD8C576611E62080A" - }, - "refId": "B", - "scenarioId": "csv_file" - } - ], - "title": "Raw data -- with outer join", - "transformations": [ - { - "id": "seriesToColumns", - "options": { - "byField": "State", - "mode": "outer" - } - }, - { - "id": "organize", - "options": { - "excludeByName": { - "1980 population_by_state.csv": true, - "2000 population_by_state.csv": true, - "DestLocation flight_info_by_state.csv": true, - "Lat flight_info_by_state.csv": true, - "Lng flight_info_by_state.csv": true, - "Price flight_info_by_state.csv": true - }, - "indexByName": {}, - "renameByName": { - "2020 population_by_state.csv": "2020 population", - "Count flight_info_by_state.csv": "Flight count", - "Price flight_info_by_state.csv": "" - } - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 11, - "x": 7, - "y": 3 - }, - "id": 4, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "9.2.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A" - } - ], - "title": "Reused data (without transform)", - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 18, - "y": 3 - }, - "id": 5, - "options": { - "basemap": { - "config": {}, - "name": "Layer 0", - "type": "default" - }, - "controls": { - "mouseWheelZoom": true, - "showAttribution": true, - "showDebug": false, - "showMeasure": false, - "showScale": false, - "showZoom": true - }, - "layers": [ - { - "config": { - "showLegend": true, - "style": { - "color": { - "fixed": "dark-green" - }, - "opacity": 0.4, - "rotation": { - "fixed": 0, - "max": 360, - "min": -360, - "mode": "mod" - }, - "size": { - "field": "Flight count", - "fixed": 5, - "max": 15, - "min": 2 - }, - "symbol": { - "fixed": "img/icons/marker/circle.svg", - "mode": "fixed" - }, - "textConfig": { - "fontSize": 12, - "offsetX": 0, - "offsetY": 0, - "textAlign": "center", - "textBaseline": "middle" - } - } - }, - "location": { - "gazetteer": "public/gazetteer/usa-states.json", - "lookup": "State", - "mode": "lookup" - }, - "name": "Flight count", - "tooltip": true, - "type": "markers" - } - ], - "tooltip": { - "mode": "details" - }, - "view": { - "id": "coords", - "lat": 35.70008, - "lon": -93.558296, - "zoom": 3.09 - } - }, - "pluginVersion": "9.2.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A", - "withTransforms": true - } - ], - "title": "Reused data (without transform)", - "type": "geomap" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 11, - "x": 7, - "y": 12 - }, - "id": 6, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "9.2.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A", - "withTransforms": true - } - ], - "title": "Reused data (with transform)", - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 18, - "y": 12 - }, - "id": 7, - "options": { - "basemap": { - "config": {}, - "name": "Layer 0", - "type": "default" - }, - "controls": { - "mouseWheelZoom": true, - "showAttribution": true, - "showDebug": false, - "showMeasure": false, - "showScale": false, - "showZoom": true - }, - "layers": [ - { - "config": { - "showLegend": true, - "style": { - "color": { - "fixed": "dark-green" - }, - "opacity": 0.4, - "rotation": { - "fixed": 0, - "max": 360, - "min": -360, - "mode": "mod" - }, - "size": { - "field": "2020 population", - "fixed": 5, - "max": 15, - "min": 2 - }, - "symbol": { - "fixed": "img/icons/marker/circle.svg", - "mode": "fixed" - }, - "textConfig": { - "fontSize": 12, - "offsetX": 0, - "offsetY": 0, - "textAlign": "center", - "textBaseline": "middle" - } - } - }, - "location": { - "gazetteer": "public/gazetteer/usa-states.json", - "lookup": "State", - "mode": "lookup" - }, - "name": "2022 Population", - "tooltip": true, - "type": "markers" - } - ], - "tooltip": { - "mode": "details" - }, - "view": { - "id": "coords", - "lat": 35.70008, - "lon": -93.558296, - "zoom": 3.09 - } - }, - "pluginVersion": "9.2.0-pre", - "targets": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "panelId": 2, - "refId": "A", - "withTransforms": true - } - ], - "title": "Reused data (with transform)", - "type": "geomap" + "type": "dashboard" } - ], - "schemaVersion": 37, - "tags": [ - "gdev", - "transform" - ], - "templating": { - "list": [] + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1394, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 9, + "options": { + "content": "Dashboard queries allow re-using the same results from one panel in another panel context.\n\nThis dashboard shows a single panel that makes a real query and applies transformations. The other panels, all use the same results rather than make their own query requests.", + "mode": "markdown" + }, + "pluginVersion": "9.2.0-pre", + "type": "text" }, - "time": { - "from": "now-6h", - "to": "now" + { + "datasource": { + "type": "grafana-testdata-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 18, + "w": 7, + "x": 0, + "y": 3 + }, + "id": 2, + "options": { + "footer": { + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.2.0-pre", + "targets": [ + { + "csvFileName": "flight_info_by_state.csv", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "A", + "scenarioId": "csv_file" + }, + { + "csvFileName": "population_by_state.csv", + "datasource": { + "type": "grafana-testdata-datasource" + }, + "refId": "B", + "scenarioId": "csv_file" + } + ], + "title": "Raw data -- with outer join", + "transformations": [ + { + "id": "seriesToColumns", + "options": { + "byField": "State", + "mode": "outer" + } + }, + { + "id": "organize", + "options": { + "excludeByName": { + "1980 population_by_state.csv": true, + "2000 population_by_state.csv": true, + "DestLocation flight_info_by_state.csv": true, + "Lat flight_info_by_state.csv": true, + "Lng flight_info_by_state.csv": true, + "Price flight_info_by_state.csv": true + }, + "indexByName": {}, + "renameByName": { + "2020 population_by_state.csv": "2020 population", + "Count flight_info_by_state.csv": "Flight count", + "Price flight_info_by_state.csv": "" + } + } + } + ], + "type": "table" }, - "timepicker": {}, - "timezone": "", - "title": "Transforms - Reuse dashboard queries", - "uid": "fYGWTVW4k" - } + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 11, + "x": 7, + "y": 3 + }, + "id": 4, + "options": { + "footer": { + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.2.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "title": "Reused data (without transform)", + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 18, + "y": 3 + }, + "id": 5, + "options": { + "basemap": { + "config": {}, + "name": "Layer 0", + "type": "default" + }, + "controls": { + "mouseWheelZoom": true, + "showAttribution": true, + "showDebug": false, + "showMeasure": false, + "showScale": false, + "showZoom": true + }, + "layers": [ + { + "config": { + "showLegend": true, + "style": { + "color": { + "fixed": "dark-green" + }, + "opacity": 0.4, + "rotation": { + "fixed": 0, + "max": 360, + "min": -360, + "mode": "mod" + }, + "size": { + "field": "Flight count", + "fixed": 5, + "max": 15, + "min": 2 + }, + "symbol": { + "fixed": "img/icons/marker/circle.svg", + "mode": "fixed" + }, + "textConfig": { + "fontSize": 12, + "offsetX": 0, + "offsetY": 0, + "textAlign": "center", + "textBaseline": "middle" + } + } + }, + "location": { + "gazetteer": "public/gazetteer/usa-states.json", + "lookup": "State", + "mode": "lookup" + }, + "name": "Flight count", + "tooltip": true, + "type": "markers" + } + ], + "tooltip": { + "mode": "details" + }, + "view": { + "id": "coords", + "lat": 35.70008, + "lon": -93.558296, + "zoom": 3.09 + } + }, + "pluginVersion": "9.2.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A", + "withTransforms": true + } + ], + "title": "Reused data (without transform)", + "type": "geomap" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 11, + "x": 7, + "y": 12 + }, + "id": 6, + "options": { + "footer": { + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.2.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A", + "withTransforms": true + } + ], + "title": "Reused data (with transform)", + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 18, + "y": 12 + }, + "id": 7, + "options": { + "basemap": { + "config": {}, + "name": "Layer 0", + "type": "default" + }, + "controls": { + "mouseWheelZoom": true, + "showAttribution": true, + "showDebug": false, + "showMeasure": false, + "showScale": false, + "showZoom": true + }, + "layers": [ + { + "config": { + "showLegend": true, + "style": { + "color": { + "fixed": "dark-green" + }, + "opacity": 0.4, + "rotation": { + "fixed": 0, + "max": 360, + "min": -360, + "mode": "mod" + }, + "size": { + "field": "2020 population", + "fixed": 5, + "max": 15, + "min": 2 + }, + "symbol": { + "fixed": "img/icons/marker/circle.svg", + "mode": "fixed" + }, + "textConfig": { + "fontSize": 12, + "offsetX": 0, + "offsetY": 0, + "textAlign": "center", + "textBaseline": "middle" + } + } + }, + "location": { + "gazetteer": "public/gazetteer/usa-states.json", + "lookup": "State", + "mode": "lookup" + }, + "name": "2022 Population", + "tooltip": true, + "type": "markers" + } + ], + "tooltip": { + "mode": "details" + }, + "view": { + "id": "coords", + "lat": 35.70008, + "lon": -93.558296, + "zoom": 3.09 + } + }, + "pluginVersion": "9.2.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A", + "withTransforms": true + } + ], + "title": "Reused data (with transform)", + "type": "geomap" + } + ], + "schemaVersion": 37, + "tags": ["gdev", "transform"], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Transforms - Reuse dashboard queries", + "uid": "fYGWTVW4k" +} diff --git a/devenv/dev-dashboards/transforms/rows-to-fields.json b/devenv/dev-dashboards/transforms/rows-to-fields.json index 45b8951c082..d04120f95e9 100644 --- a/devenv/dev-dashboards/transforms/rows-to-fields.json +++ b/devenv/dev-dashboards/transforms/rows-to-fields.json @@ -1,611 +1,598 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], "type": "dashboard" - } - ] - }, - "editable": true, - "graphTooltip": 0, - "links": [], - "panels": [ - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "left", - "displayMode": "auto" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 0, - "y": 0 - }, - "id": 8, - "options": { - "showHeader": true - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "panelId": 2, - "refId": "A" - } - ], - "title": "Raw data", - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "left", - "displayMode": "auto" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 82 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Unit" - }, - "properties": [ - { - "id": "custom.width", - "value": 108 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 0 - }, - "id": 7, - "options": { - "showHeader": true, - "sortBy": [] - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "panelId": 3, - "refId": "A" - } - ], - "title": "Raw data", - "type": "table" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 5 - }, - "id": 2, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": {}, - "textMode": "auto" - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "csvContent": "Name,Value,Unit,Color\nTemperature,10,degree,green\nPressure,100,bar,blue\nSpeed,30,km/h,red", - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "Unit and color from data", - "transformations": [ - { - "id": "rowsToFields", - "options": {} - } - ], - "type": "stat" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 5 - }, - "id": 3, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": true, - "showThresholdMarkers": true, - "text": {} - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "csvContent": "Name,Value,Unit,min,max, threshold1\nTemperature,10,degree,0,50,30\nPressure,100,Pa,0,300,200\nSpeed,30,km/h,0,150,110", - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "Min, Max & Thresholds from data", - "transformations": [ - { - "id": "rowsToFields", - "options": {} - } - ], - "type": "gauge" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "left", - "displayMode": "auto" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 0, - "y": 12 - }, - "id": 10, - "options": { - "showHeader": true - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "panelId": 9, - "refId": "A" - } - ], - "title": "Raw data", - "type": "table" - }, - { - "datasource": { - "type": "datasource", - "uid": "-- Dashboard --" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "left", - "displayMode": "auto" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 82 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Unit" - }, - "properties": [ - { - "id": "custom.width", - "value": 108 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 12 - }, - "id": 12, - "options": { - "showHeader": true, - "sortBy": [] - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "panelId": 11, - "refId": "A" - } - ], - "title": "Raw data (Custom mapping)", - "type": "table" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "continuous-GrYlRd" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 17 - }, - "id": 9, - "options": { - "displayMode": "gradient", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showUnfilled": true, - "text": {} - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "csvContent": "Name,Value,Unit,Min,Max\nTemperature,20,degree,0,50\nPressure,150,Pa,0,300\nSpeed,100,km/h,0,110", - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "Min max from data", - "transformations": [ - { - "id": "rowsToFields", - "options": {} - } - ], - "type": "bargauge" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 17 - }, - "id": 11, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": true, - "showThresholdMarkers": true, - "text": {} - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "csvContent": "Name,Value,Type,Quota, Warning\nTemperature,25,degree,50,30\nPressure,100,Pa,300,200\nSpeed,30,km/h,150,130", - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "Custom mapping", - "transformations": [ - { - "id": "rowsToFields", - "options": { - "mappings": [ - { - "configProperty": "unit", - "fieldName": "Type", - "handlerKey": "unit" - }, - { - "configProperty": "max", - "fieldName": "Quota", - "handlerKey": "max" - }, - { - "configProperty": "threshold1", - "fieldName": "Warning", - "handlerKey": "threshold1" - } - ] - } - } - ], - "type": "gauge" - }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 24 - }, - "id": 13, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": {}, - "textMode": "auto" - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "csvContent": "Name, City, Country, Value\nSensorA, Stockholm, Sweden, 20\nSensorB, London, England, 50\nSensorC, New York, USA,100", - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "Extra string fields to labels", - "transformations": [ - { - "id": "rowsToFields", - "options": {} - } - ], - "type": "stat" + "type": "dashboard" } - ], - "refresh": "", - "schemaVersion": 33, - "tags": [ - "gdev", - "transform" - ], - "templating": { - "list": [] + ] + }, + "editable": true, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "left", + "displayMode": "auto" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 8, + "options": { + "showHeader": true + }, + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "panelId": 2, + "refId": "A" + } + ], + "title": "Raw data", + "type": "table" }, - "time": { - "from": "now-6h", - "to": "now" + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "left", + "displayMode": "auto" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.width", + "value": 82 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unit" + }, + "properties": [ + { + "id": "custom.width", + "value": 108 + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 7, + "options": { + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "panelId": 3, + "refId": "A" + } + ], + "title": "Raw data", + "type": "table" }, - "timepicker": {}, - "timezone": "", - "title": "Transforms - Rows to fields", - "uid": "PMtIInink", - "version": 1 - } + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 5 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "csvContent": "Name,Value,Unit,Color\nTemperature,10,degree,green\nPressure,100,bar,blue\nSpeed,30,km/h,red", + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Unit and color from data", + "transformations": [ + { + "id": "rowsToFields", + "options": {} + } + ], + "type": "stat" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 5 + }, + "id": 3, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": true, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "csvContent": "Name,Value,Unit,min,max, threshold1\nTemperature,10,degree,0,50,30\nPressure,100,Pa,0,300,200\nSpeed,30,km/h,0,150,110", + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Min, Max & Thresholds from data", + "transformations": [ + { + "id": "rowsToFields", + "options": {} + } + ], + "type": "gauge" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "left", + "displayMode": "auto" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 12 + }, + "id": 10, + "options": { + "showHeader": true + }, + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "panelId": 9, + "refId": "A" + } + ], + "title": "Raw data", + "type": "table" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "left", + "displayMode": "auto" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.width", + "value": 82 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unit" + }, + "properties": [ + { + "id": "custom.width", + "value": 108 + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 12 + }, + "id": 12, + "options": { + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "panelId": 11, + "refId": "A" + } + ], + "title": "Raw data (Custom mapping)", + "type": "table" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 9, + "options": { + "displayMode": "gradient", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showUnfilled": true, + "text": {} + }, + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "csvContent": "Name,Value,Unit,Min,Max\nTemperature,20,degree,0,50\nPressure,150,Pa,0,300\nSpeed,100,km/h,0,110", + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Min max from data", + "transformations": [ + { + "id": "rowsToFields", + "options": {} + } + ], + "type": "bargauge" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 11, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": true, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "csvContent": "Name,Value,Type,Quota, Warning\nTemperature,25,degree,50,30\nPressure,100,Pa,300,200\nSpeed,30,km/h,150,130", + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Custom mapping", + "transformations": [ + { + "id": "rowsToFields", + "options": { + "mappings": [ + { + "configProperty": "unit", + "fieldName": "Type", + "handlerKey": "unit" + }, + { + "configProperty": "max", + "fieldName": "Quota", + "handlerKey": "max" + }, + { + "configProperty": "threshold1", + "fieldName": "Warning", + "handlerKey": "threshold1" + } + ] + } + } + ], + "type": "gauge" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 13, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "csvContent": "Name, City, Country, Value\nSensorA, Stockholm, Sweden, 20\nSensorB, London, England, 50\nSensorC, New York, USA,100", + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Extra string fields to labels", + "transformations": [ + { + "id": "rowsToFields", + "options": {} + } + ], + "type": "stat" + } + ], + "refresh": "", + "schemaVersion": 33, + "tags": ["gdev", "transform"], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Transforms - Rows to fields", + "uid": "PMtIInink", + "version": 1 +} diff --git a/devenv/docker/blocks/auth/authentik/README.md b/devenv/docker/blocks/auth/authentik/README.md index 7c02d38bb8d..822fe35595b 100644 --- a/devenv/docker/blocks/auth/authentik/README.md +++ b/devenv/docker/blocks/auth/authentik/README.md @@ -24,7 +24,6 @@ The container will expose port `3389` and `6636` as LDAP and LDAPS. The container will expose port `9000` for API and Admin interface. - ## LDAP Setup The following changes are needed at Grafana's configuration file. @@ -90,13 +89,13 @@ signout_redirect_url = http://localhost:9000/application/o/grafana-oidc/end-sess ## Available users and groups -*authentik admin*: +_authentik admin_: - username: akadmin - email: admin@localhost - password: admin -*grafana logins*: +_grafana logins_: - username: authentik-admin - password: grafana diff --git a/devenv/docker/blocks/auth/jwt_proxy/jwks.json b/devenv/docker/blocks/auth/jwt_proxy/jwks.json index 9f79114ba44..d1a938c0928 100644 --- a/devenv/docker/blocks/auth/jwt_proxy/jwks.json +++ b/devenv/docker/blocks/auth/jwt_proxy/jwks.json @@ -1 +1,17 @@ -{"keys":[{"kid":"On2FQuJ8Y-909uJGWQEDkbzG-GRNmMc43HslEgVv_VQ","kty":"RSA","alg":"RS256","use":"sig","n":"qDmQHfTcOQOzmNJbVvtvuS8p_EgmiscP7vA_PZNyKx9O7utyGuoAmJH8e2w8gLIDDWHl5_x8aAIl_-TTPTSiyX8I68ryIdR28ZSe5u4pRdpXCVvJpOefKNIxQCTH7rs4KuRj0HZ2u1mu1Vz5_CeCCoKwKSmheD3u1xTJ8-VxQmdqfGxhuKtnkof7977HWOWy4GLDFqxyYHgihP_MmSeTmXUhVeZI6IOCqHMpF8eFWVGKM6V8rIKf8QO2K_vDJBM_3C933vMY8mqSQXbI3G54x-0myAaQXr4JkxjvUGKg5YC3ZXw7AjfZv_W_fQOG0GYp2hQ0akR4KNKT3XPNmpMVlQ","e":"AQAB","x5c":["MIICnTCCAYUCBgF+u1ir8jANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdncmFmYW5hMB4XDTIyMDIwMjE2NDkxN1oXDTMyMDIwMjE2NTA1N1owEjEQMA4GA1UEAwwHZ3JhZmFuYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKg5kB303DkDs5jSW1b7b7kvKfxIJorHD+7wPz2TcisfTu7rchrqAJiR/HtsPICyAw1h5ef8fGgCJf/k0z00osl/COvK8iHUdvGUnubuKUXaVwlbyaTnnyjSMUAkx+67OCrkY9B2drtZrtVc+fwnggqCsCkpoXg97tcUyfPlcUJnanxsYbirZ5KH+/e+x1jlsuBiwxascmB4IoT/zJknk5l1IVXmSOiDgqhzKRfHhVlRijOlfKyCn/EDtiv7wyQTP9wvd97zGPJqkkF2yNxueMftJsgGkF6+CZMY71BioOWAt2V8OwI32b/1v30DhtBmKdoUNGpEeCjSk91zzZqTFZUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEABlW64QxuREB81VMGsyhj4Q5RykFaVuD5O8YlwUpmVfAVLzb0Drf54Kn4bnpnckKyYV+T+HsN4QXt81UE41xH0Aai2H3vrGH+PJf6aLPCDE+jpMqtN3n6IgImJXJPL8upMfhhWDv4nkM4uynEwWupzmrKi4oJuTETSMktJby4o6//XWnCzCVMoAGFJU4gtjBUzOMLW26zD+yc+BuUtfR3HzItVHSZKQSNSFO0kVS68RgrER8qJw07z3BOJ2bPpPM0PYyEngGMaowz/T6lI32ymGMWYMAnslthS1KAW9xcTBwnrW1nMhe5a0LPxIktys/wJtxIHZLc5sOddGT4xYklLg=="],"x5t":"prs-h1NBqOSJMH-tQWLTqguWets","x5t#S256":"YjK3HobZW8xbNL1IPDgFhCM41UC5c0hG2cxaF6v961Q"}]} \ No newline at end of file +{ + "keys": [ + { + "kid": "On2FQuJ8Y-909uJGWQEDkbzG-GRNmMc43HslEgVv_VQ", + "kty": "RSA", + "alg": "RS256", + "use": "sig", + "n": "qDmQHfTcOQOzmNJbVvtvuS8p_EgmiscP7vA_PZNyKx9O7utyGuoAmJH8e2w8gLIDDWHl5_x8aAIl_-TTPTSiyX8I68ryIdR28ZSe5u4pRdpXCVvJpOefKNIxQCTH7rs4KuRj0HZ2u1mu1Vz5_CeCCoKwKSmheD3u1xTJ8-VxQmdqfGxhuKtnkof7977HWOWy4GLDFqxyYHgihP_MmSeTmXUhVeZI6IOCqHMpF8eFWVGKM6V8rIKf8QO2K_vDJBM_3C933vMY8mqSQXbI3G54x-0myAaQXr4JkxjvUGKg5YC3ZXw7AjfZv_W_fQOG0GYp2hQ0akR4KNKT3XPNmpMVlQ", + "e": "AQAB", + "x5c": [ + "MIICnTCCAYUCBgF+u1ir8jANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdncmFmYW5hMB4XDTIyMDIwMjE2NDkxN1oXDTMyMDIwMjE2NTA1N1owEjEQMA4GA1UEAwwHZ3JhZmFuYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKg5kB303DkDs5jSW1b7b7kvKfxIJorHD+7wPz2TcisfTu7rchrqAJiR/HtsPICyAw1h5ef8fGgCJf/k0z00osl/COvK8iHUdvGUnubuKUXaVwlbyaTnnyjSMUAkx+67OCrkY9B2drtZrtVc+fwnggqCsCkpoXg97tcUyfPlcUJnanxsYbirZ5KH+/e+x1jlsuBiwxascmB4IoT/zJknk5l1IVXmSOiDgqhzKRfHhVlRijOlfKyCn/EDtiv7wyQTP9wvd97zGPJqkkF2yNxueMftJsgGkF6+CZMY71BioOWAt2V8OwI32b/1v30DhtBmKdoUNGpEeCjSk91zzZqTFZUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEABlW64QxuREB81VMGsyhj4Q5RykFaVuD5O8YlwUpmVfAVLzb0Drf54Kn4bnpnckKyYV+T+HsN4QXt81UE41xH0Aai2H3vrGH+PJf6aLPCDE+jpMqtN3n6IgImJXJPL8upMfhhWDv4nkM4uynEwWupzmrKi4oJuTETSMktJby4o6//XWnCzCVMoAGFJU4gtjBUzOMLW26zD+yc+BuUtfR3HzItVHSZKQSNSFO0kVS68RgrER8qJw07z3BOJ2bPpPM0PYyEngGMaowz/T6lI32ymGMWYMAnslthS1KAW9xcTBwnrW1nMhe5a0LPxIktys/wJtxIHZLc5sOddGT4xYklLg==" + ], + "x5t": "prs-h1NBqOSJMH-tQWLTqguWets", + "x5t#S256": "YjK3HobZW8xbNL1IPDgFhCM41UC5c0hG2cxaF6v961Q" + } + ] +} diff --git a/devenv/docker/blocks/auth/jwt_proxy/readme.md b/devenv/docker/blocks/auth/jwt_proxy/readme.md index 823287f54e3..f5b05527f96 100644 --- a/devenv/docker/blocks/auth/jwt_proxy/readme.md +++ b/devenv/docker/blocks/auth/jwt_proxy/readme.md @@ -1,4 +1,5 @@ # JWT PROXY BLOCK + ## Devenv setup jwt auth To launch the block, use the oauth source. Ex: @@ -28,13 +29,14 @@ groups_attribute_path = groups[] allow_assign_grafana_admin = true ``` -Add *env.grafana.local* to /etc/hosts (Mac/Linux) or C:\Windows\System32\drivers\etc\hosts (Windows): +Add _env.grafana.local_ to /etc/hosts (Mac/Linux) or C:\Windows\System32\drivers\etc\hosts (Windows): + ```ini 127.0.0.1 env.grafana.local ::1 env.grafana.local ``` -Access Grafana through: +Access Grafana through: ```sh http://env.grafana.local:8088 @@ -72,11 +74,11 @@ docker-compose exec -T oauthkeycloakdb bash -c "pg_dump -U keycloak keycloak" > ## Connecting to keycloak: -- keycloak admin: http://localhost:8087 -- keycloak admin login: admin:admin -- grafana jwt viewer login: jwt-viewer:grafana -- grafana jwt editor login: jwt-editor:grafana -- grafana jwt admin login: jwt-admin:grafana +- keycloak admin: http://localhost:8087 +- keycloak admin login: admin:admin +- grafana jwt viewer login: jwt-viewer:grafana +- grafana jwt editor login: jwt-editor:grafana +- grafana jwt admin login: jwt-admin:grafana # Troubleshooting @@ -86,13 +88,17 @@ The new arm64 architecture does not build for the latest docker image of keycloa Until then you need to build the docker image locally and then run `devenv`. 1. Remove any lingering keycloak image + ```sh $ docker rmi $(docker images | grep 'keycloak') ``` + 1. Build keycloak image locally + ```sh $ ./docker-build-keycloak-m1-image.sh ``` + 1. Start from beginning of this readme ## Docker for Windows Users @@ -102,12 +108,16 @@ $ ./docker-build-keycloak-m1-image.sh Port forwarding needs to be set up between the WSL 2 VM (which runs Grafana, in my case it is Ubuntu) and the host system. (https://docs.microsoft.com/en-us/windows/wsl/networking) Run the following commands from an elevated PowerShell prompt: + 1. Change the default WSL 2 distribution if necessary + ```powershell wsl --list # Find the default wsl -s Ubuntu # Change the default ``` + 2. Open port 3000 between the Windows host and the WSL 2 VM + ```powershell $hostAddr = '0.0.0.0'; $wslHostAddr = wsl hostname -I; diff --git a/devenv/docker/blocks/auth/oauth/jwks.json b/devenv/docker/blocks/auth/oauth/jwks.json index 9f79114ba44..d1a938c0928 100644 --- a/devenv/docker/blocks/auth/oauth/jwks.json +++ b/devenv/docker/blocks/auth/oauth/jwks.json @@ -1 +1,17 @@ -{"keys":[{"kid":"On2FQuJ8Y-909uJGWQEDkbzG-GRNmMc43HslEgVv_VQ","kty":"RSA","alg":"RS256","use":"sig","n":"qDmQHfTcOQOzmNJbVvtvuS8p_EgmiscP7vA_PZNyKx9O7utyGuoAmJH8e2w8gLIDDWHl5_x8aAIl_-TTPTSiyX8I68ryIdR28ZSe5u4pRdpXCVvJpOefKNIxQCTH7rs4KuRj0HZ2u1mu1Vz5_CeCCoKwKSmheD3u1xTJ8-VxQmdqfGxhuKtnkof7977HWOWy4GLDFqxyYHgihP_MmSeTmXUhVeZI6IOCqHMpF8eFWVGKM6V8rIKf8QO2K_vDJBM_3C933vMY8mqSQXbI3G54x-0myAaQXr4JkxjvUGKg5YC3ZXw7AjfZv_W_fQOG0GYp2hQ0akR4KNKT3XPNmpMVlQ","e":"AQAB","x5c":["MIICnTCCAYUCBgF+u1ir8jANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdncmFmYW5hMB4XDTIyMDIwMjE2NDkxN1oXDTMyMDIwMjE2NTA1N1owEjEQMA4GA1UEAwwHZ3JhZmFuYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKg5kB303DkDs5jSW1b7b7kvKfxIJorHD+7wPz2TcisfTu7rchrqAJiR/HtsPICyAw1h5ef8fGgCJf/k0z00osl/COvK8iHUdvGUnubuKUXaVwlbyaTnnyjSMUAkx+67OCrkY9B2drtZrtVc+fwnggqCsCkpoXg97tcUyfPlcUJnanxsYbirZ5KH+/e+x1jlsuBiwxascmB4IoT/zJknk5l1IVXmSOiDgqhzKRfHhVlRijOlfKyCn/EDtiv7wyQTP9wvd97zGPJqkkF2yNxueMftJsgGkF6+CZMY71BioOWAt2V8OwI32b/1v30DhtBmKdoUNGpEeCjSk91zzZqTFZUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEABlW64QxuREB81VMGsyhj4Q5RykFaVuD5O8YlwUpmVfAVLzb0Drf54Kn4bnpnckKyYV+T+HsN4QXt81UE41xH0Aai2H3vrGH+PJf6aLPCDE+jpMqtN3n6IgImJXJPL8upMfhhWDv4nkM4uynEwWupzmrKi4oJuTETSMktJby4o6//XWnCzCVMoAGFJU4gtjBUzOMLW26zD+yc+BuUtfR3HzItVHSZKQSNSFO0kVS68RgrER8qJw07z3BOJ2bPpPM0PYyEngGMaowz/T6lI32ymGMWYMAnslthS1KAW9xcTBwnrW1nMhe5a0LPxIktys/wJtxIHZLc5sOddGT4xYklLg=="],"x5t":"prs-h1NBqOSJMH-tQWLTqguWets","x5t#S256":"YjK3HobZW8xbNL1IPDgFhCM41UC5c0hG2cxaF6v961Q"}]} \ No newline at end of file +{ + "keys": [ + { + "kid": "On2FQuJ8Y-909uJGWQEDkbzG-GRNmMc43HslEgVv_VQ", + "kty": "RSA", + "alg": "RS256", + "use": "sig", + "n": "qDmQHfTcOQOzmNJbVvtvuS8p_EgmiscP7vA_PZNyKx9O7utyGuoAmJH8e2w8gLIDDWHl5_x8aAIl_-TTPTSiyX8I68ryIdR28ZSe5u4pRdpXCVvJpOefKNIxQCTH7rs4KuRj0HZ2u1mu1Vz5_CeCCoKwKSmheD3u1xTJ8-VxQmdqfGxhuKtnkof7977HWOWy4GLDFqxyYHgihP_MmSeTmXUhVeZI6IOCqHMpF8eFWVGKM6V8rIKf8QO2K_vDJBM_3C933vMY8mqSQXbI3G54x-0myAaQXr4JkxjvUGKg5YC3ZXw7AjfZv_W_fQOG0GYp2hQ0akR4KNKT3XPNmpMVlQ", + "e": "AQAB", + "x5c": [ + "MIICnTCCAYUCBgF+u1ir8jANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdncmFmYW5hMB4XDTIyMDIwMjE2NDkxN1oXDTMyMDIwMjE2NTA1N1owEjEQMA4GA1UEAwwHZ3JhZmFuYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKg5kB303DkDs5jSW1b7b7kvKfxIJorHD+7wPz2TcisfTu7rchrqAJiR/HtsPICyAw1h5ef8fGgCJf/k0z00osl/COvK8iHUdvGUnubuKUXaVwlbyaTnnyjSMUAkx+67OCrkY9B2drtZrtVc+fwnggqCsCkpoXg97tcUyfPlcUJnanxsYbirZ5KH+/e+x1jlsuBiwxascmB4IoT/zJknk5l1IVXmSOiDgqhzKRfHhVlRijOlfKyCn/EDtiv7wyQTP9wvd97zGPJqkkF2yNxueMftJsgGkF6+CZMY71BioOWAt2V8OwI32b/1v30DhtBmKdoUNGpEeCjSk91zzZqTFZUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEABlW64QxuREB81VMGsyhj4Q5RykFaVuD5O8YlwUpmVfAVLzb0Drf54Kn4bnpnckKyYV+T+HsN4QXt81UE41xH0Aai2H3vrGH+PJf6aLPCDE+jpMqtN3n6IgImJXJPL8upMfhhWDv4nkM4uynEwWupzmrKi4oJuTETSMktJby4o6//XWnCzCVMoAGFJU4gtjBUzOMLW26zD+yc+BuUtfR3HzItVHSZKQSNSFO0kVS68RgrER8qJw07z3BOJ2bPpPM0PYyEngGMaowz/T6lI32ymGMWYMAnslthS1KAW9xcTBwnrW1nMhe5a0LPxIktys/wJtxIHZLc5sOddGT4xYklLg==" + ], + "x5t": "prs-h1NBqOSJMH-tQWLTqguWets", + "x5t#S256": "YjK3HobZW8xbNL1IPDgFhCM41UC5c0hG2cxaF6v961Q" + } + ] +} diff --git a/devenv/docker/blocks/auth/oauth/readme.md b/devenv/docker/blocks/auth/oauth/readme.md index cd59c21a846..51fdd7526cc 100644 --- a/devenv/docker/blocks/auth/oauth/readme.md +++ b/devenv/docker/blocks/auth/oauth/readme.md @@ -3,6 +3,7 @@ ## Devenv setup oauth To launch the block, use the oauth source. Ex: + ```bash make devenv sources="auth/oauth" ``` @@ -67,7 +68,6 @@ curl --request POST \ --data password=grafana ``` - Grafana call example: ```sh @@ -112,9 +112,9 @@ docker-compose exec -T oauthkeycloakdb bash -c "pg_dump -U keycloak keycloak" > ## Connecting to keycloak: -- keycloak admin: http://localhost:8087 -- keycloak admin login: admin:admin -- grafana oauth viewer login: oauth-viewer:grafana -- grafana oauth editor login: oauth-editor:grafana -- grafana oauth admin login: oauth-admin:grafana -- grafana oauth server admin login: oauth-grafanaadmin:grafana +- keycloak admin: http://localhost:8087 +- keycloak admin login: admin:admin +- grafana oauth viewer login: oauth-viewer:grafana +- grafana oauth editor login: oauth-editor:grafana +- grafana oauth admin login: oauth-admin:grafana +- grafana oauth server admin login: oauth-grafanaadmin:grafana diff --git a/devenv/docker/blocks/auth/openldap-multiple/README.md b/devenv/docker/blocks/auth/openldap-multiple/README.md index b31939c9bbd..ea3bbb8aea7 100644 --- a/devenv/docker/blocks/auth/openldap-multiple/README.md +++ b/devenv/docker/blocks/auth/openldap-multiple/README.md @@ -30,9 +30,10 @@ enabled = true config_file = ./devenv/docker/blocks/auth/openldap-multiple/ldap_dev.toml ``` -## Available users and groups +## Available users and groups ### Srv1 (dc=srv1-grafana,dc=org) + - admins - ldap-admin-srv1 - editors diff --git a/devenv/docker/blocks/auth/openldap/README.md b/devenv/docker/blocks/auth/openldap/README.md index ee86f0daab4..a06efee58f4 100644 --- a/devenv/docker/blocks/auth/openldap/README.md +++ b/devenv/docker/blocks/auth/openldap/README.md @@ -1,6 +1,6 @@ # OpenLDAP for MacOS Docker Block -This Docker block is an updated version from [OpenLDAP](../openldap/) block. This Docker block uses `osixia/openldap` image. The original Docker block was based of `debian:jessie` which is not available for Apple's ARM chip. +This Docker block is an updated version from [OpenLDAP](../openldap/) block. This Docker block uses `osixia/openldap` image. The original Docker block was based of `debian:jessie` which is not available for Apple's ARM chip. ## Deployment @@ -58,6 +58,7 @@ The default configuration between Grafana and the OpenLDAP container is configur ## Configure LDAP with TLS After the `openldap` container has been deployed, you have to copy the CA from the docker container: + ```bash # get the container ID docker ps @@ -85,7 +86,8 @@ port = 636 use_ssl = true start_tls = false ``` -- To connect with STARTTLS use this config: + +- To connect with STARTTLS use this config: ```ini port = 389 diff --git a/devenv/docker/blocks/auth/prometheus_oauth2_proxy_azure/README.md b/devenv/docker/blocks/auth/prometheus_oauth2_proxy_azure/README.md index e8af6516516..4d9bdc2878c 100644 --- a/devenv/docker/blocks/auth/prometheus_oauth2_proxy_azure/README.md +++ b/devenv/docker/blocks/auth/prometheus_oauth2_proxy_azure/README.md @@ -5,7 +5,7 @@ 1. Make a copy of `oauth2-proxy.example.cfg` and rename it to `oauth2-proxy.cfg` 1. Fill in the required information (`azure client id`, `azure client secret`, `azure tenant id`) 1. Start the containers by executing `make devenv sources="prometheus,auth/prometheus_oauth2_proxy_azure"` -> If you would like to test the login flow from the browser then you need to setup TLS or start a tunnel. I usually use a tunnel (`cloudflared tunnel --url http://localhost:4180`). Do not forget to set the Redirect URIs on Azure's App Registration page + > If you would like to test the login flow from the browser then you need to setup TLS or start a tunnel. I usually use a tunnel (`cloudflared tunnel --url http://localhost:4180`). Do not forget to set the Redirect URIs on Azure's App Registration page ## How to add a new Prometheus datasource with Azure Authentication enabled @@ -15,11 +15,12 @@ 1. Set the URL 1. Enable Azure Authentication 1. Fill in the required fields of the `Azure Authentication` section - 1. Click `Save & test` + 1. Click `Save & test` 1. You should get a "Data source is working" message If you check the logs of OAuth2-proxy, you should see similar lines to this: + ``` 2023-04-19 11:29:40 172.31.0.1:55602 - d96b832a-170a-41eb-a974-6558c5ce4454 - - [2023/04/19 09:29:40] some-random-tunnel-address.trycloudflare.com GET / "/api/v1/status/buildinfo" HTTP/1.1 "Grafana/10.0.0-pre" 200 187 0.016 2023-04-19 11:29:41 172.31.0.1:55602 - db27c56a-ccd6-4cdb-a040-318113781abf - 65ac87f4-931f-4e46-9761-f8bf1ad36b48 [2023/04/19 09:29:41] some-random-tunnel-address.trycloudflare.com POST / "/api/v1/query" HTTP/1.1 "Grafana/10.0.0-pre" 200 103 0.003 -``` \ No newline at end of file +``` diff --git a/devenv/docker/blocks/caddy_tls/README.md b/devenv/docker/blocks/caddy_tls/README.md index 464f076ffcc..00a0a86d68f 100644 --- a/devenv/docker/blocks/caddy_tls/README.md +++ b/devenv/docker/blocks/caddy_tls/README.md @@ -5,7 +5,7 @@ Starts a [Caddy server](https://caddyserver.com/) with TLS configured. ## Setup - Caddy is setup to run on port 2081, so when configuring the webhook receiver in Grafana Alerting you should use the -following the following URL: `https://localhost:2081` + following the following URL: `https://localhost:2081` - Also, Caddy is configured to use a self-signed certificate and to check the client certificate (`require_and_verify` mode) - Caddy is setup to log requests and has debug mode enabled to make it easier to investigate possible issues @@ -15,19 +15,19 @@ If you want to configure a webhook contact point in Grafana Alerting with TLS, y You can find them in `/etc/caddy` directory in the container: -``` shell +```shell docker exec devenv-caddy_tls-1 ls /etc/caddy/ ``` ### CA Certificate -``` shell +```shell docker exec devenv-caddy_tls-1 cat /etc/caddy/ca.pem ``` ### Client certificates -``` shell +```shell docker exec devenv-caddy_tls-1 cat /etc/caddy/client.pem docker exec devenv-caddy_tls-1 cat /etc/caddy/client.key ``` diff --git a/devenv/docker/blocks/collectd/README.md b/devenv/docker/blocks/collectd/README.md index ebd744284d1..d950a4677b2 100644 --- a/devenv/docker/blocks/collectd/README.md +++ b/devenv/docker/blocks/collectd/README.md @@ -1,5 +1,4 @@ -collectd-write-graphite -======================= +# collectd-write-graphite Basic collectd-based server monitoring. Sends stats to Graphite. @@ -14,8 +13,7 @@ Collectd metrics: - Network interface - Swap -Environment variables ---------------------- +## Environment variables - `HOST_NAME` - Will be sent to Graphite diff --git a/devenv/docker/blocks/loki-promtail/README.md b/devenv/docker/blocks/loki-promtail/README.md index ef92ddbd193..9bd79ad7f0d 100644 --- a/devenv/docker/blocks/loki-promtail/README.md +++ b/devenv/docker/blocks/loki-promtail/README.md @@ -1,10 +1,11 @@ NB: This will not work properly on MacOS. The loglines of grafana.log are ingested at the start of this devenv and you won't get any more logs are the Docker service is started. By default this block is setup to scrape logs from Grafana. If you need to log some service from the docker-compse you can add: + ``` # For this to work you need to install the logging driver see https://github.com/grafana/loki/tree/master/cmd/docker-driver#plugin-installation logging: driver: loki options: loki-url: "http://loki:3100/loki/api/v1/push" -``` \ No newline at end of file +``` diff --git a/devenv/docker/blocks/maildev/README.md b/devenv/docker/blocks/maildev/README.md index 6ad77fc4935..77019d6cd85 100644 --- a/devenv/docker/blocks/maildev/README.md +++ b/devenv/docker/blocks/maildev/README.md @@ -1 +1 @@ -This block starts a test SMTP server on port 1025 and UI on port 12080 \ No newline at end of file +This block starts a test SMTP server on port 1025 and UI on port 12080 diff --git a/devenv/docker/blocks/mqtt/README.md b/devenv/docker/blocks/mqtt/README.md index 6724fa17666..f7dd0ff95a2 100644 --- a/devenv/docker/blocks/mqtt/README.md +++ b/devenv/docker/blocks/mqtt/README.md @@ -5,7 +5,7 @@ Starts a [NanoMQ MQTT broker](https://nanomq.io/docs/en/latest/). ## Authentication The broker is configured to use a simple username/password authentication. -See [./nanomq_pwd.conf](./nanomq_pwd.conf) for the default credentials. +See [./nanomq_pwd.conf](./nanomq_pwd.conf) for the default credentials. ## TLS Certificates @@ -13,19 +13,19 @@ If you want to configure an MQTT contact point in Grafana Alerting with TLS, you You can find them in `/etc/certs` directory in the container: -``` shell +```shell docker exec devenv-mqtt-1 ls /etc/certs/ ``` ### CA Certificate -``` shell +```shell docker exec devenv-mqtt-1 cat /etc/certs/ca.pem ``` ### Client certificates -``` shell +```shell docker exec devenv-mqtt-1 cat /etc/certs/client.pem docker exec devenv-mqtt-1 cat /etc/certs/client.key ``` diff --git a/devenv/docker/blocks/mssql_arm64/README.md b/devenv/docker/blocks/mssql_arm64/README.md index 83c63a63fe8..c45f007caf5 100644 --- a/devenv/docker/blocks/mssql_arm64/README.md +++ b/devenv/docker/blocks/mssql_arm64/README.md @@ -6,7 +6,8 @@ The `setup` files cannot be used to create a custom `grafana` db/user since `sql (https://docs.microsoft.com/en-us/azure/azure-sql-edge/connect) You can connect the Grafana MSSQL datasource to this instance by using the following credentials: - * Host: `localhost` - * Database: `master` - * User: `sa` - * Password: `Password!` or whatever is set in `docker-compose.yaml` for env var `MSSQL_SA_PASSWORD` \ No newline at end of file + +- Host: `localhost` +- Database: `master` +- User: `sa` +- Password: `Password!` or whatever is set in `docker-compose.yaml` for env var `MSSQL_SA_PASSWORD` diff --git a/devenv/docker/blocks/self-instrumentation/readme.md b/devenv/docker/blocks/self-instrumentation/readme.md index 76ef72d1ed4..07fc5856cf6 100644 --- a/devenv/docker/blocks/self-instrumentation/readme.md +++ b/devenv/docker/blocks/self-instrumentation/readme.md @@ -28,4 +28,4 @@ To collect profiles with pyroscope, you need to run Grafana with the following e export GF_DIAGNOSTICS_PROFILING_ENABLED=true export GF_DIAGNOSTICS_PROFILING_ADDR=0.0.0.0 make run -`````` +``` diff --git a/devenv/docker/blocks/sensugo/notes.md b/devenv/docker/blocks/sensugo/notes.md index f6f0b7e74b8..cfedc43da4a 100644 --- a/devenv/docker/blocks/sensugo/notes.md +++ b/devenv/docker/blocks/sensugo/notes.md @@ -24,7 +24,6 @@ The output should look similar to this: Created: /api/core/v2/apikeys/0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d ``` - ## Configuring the notification channel ### Backend URL @@ -36,4 +35,3 @@ The Backend URL is the API port (8080) forwarded to the container, it should be The `0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d` in the output above is the API Key to use in configuring the Sensu Go notification channel. - diff --git a/devenv/docker/blocks/tempo/README.md b/devenv/docker/blocks/tempo/README.md index 39d586dd5c8..1829b514bf7 100644 --- a/devenv/docker/blocks/tempo/README.md +++ b/devenv/docker/blocks/tempo/README.md @@ -1,4 +1,5 @@ This devenv docker-compose.yaml will allow you to; + - search traces - view traces - upload/download trace JSON files @@ -6,6 +7,7 @@ This devenv docker-compose.yaml will allow you to; - search traces via Loki To send traces from grafana use this configuration; + ``` [tracing.opentelemetry.otlp] # otlp destination (ex localhost:4317) diff --git a/devenv/docker/ha-test-unified-alerting/README.md b/devenv/docker/ha-test-unified-alerting/README.md index 48400d91abc..631498866c7 100644 --- a/devenv/docker/ha-test-unified-alerting/README.md +++ b/devenv/docker/ha-test-unified-alerting/README.md @@ -52,15 +52,20 @@ $ docker-compose up -d ``` Browse + - http://grafana.loc/ - http://prometheus.loc/ - ## Test alerting ### Create contact points + TBD + ### Create alerts + TBD + ### Create silences + TBD diff --git a/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/alerts/overview.json b/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/alerts/overview.json index 0357c3d10f1..822052ac4ab 100644 --- a/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/alerts/overview.json +++ b/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/alerts/overview.json @@ -140,21 +140,10 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "", "title": "Overview", "uid": "xHy7-hAik", "version": 6 -} \ No newline at end of file +} diff --git a/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/mysql/overview.json b/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/mysql/overview.json index 2bf789366cc..204c8b392d6 100644 --- a/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/mysql/overview.json +++ b/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/mysql/overview.json @@ -10,9 +10,7 @@ "limit": 100, "name": "PMM Annotations", "showIn": 0, - "tags": [ - "pmm_annotation" - ], + "tags": ["pmm_annotation"], "type": "tags" }, { @@ -24,9 +22,7 @@ "limit": 100, "name": "Annotations & Alerts", "showIn": 0, - "tags": [ - - ], + "tags": [], "type": "dashboard" } ] @@ -41,9 +37,7 @@ "icon": "dashboard", "includeVars": true, "keepTime": true, - "tags": [ - "QAN" - ], + "tags": ["QAN"], "targetBlank": false, "title": "Query Analytics", "type": "link", @@ -53,9 +47,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "OS" - ], + "tags": ["OS"], "targetBlank": false, "title": "OS", "type": "dashboards" @@ -64,9 +56,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "MySQL" - ], + "tags": ["MySQL"], "targetBlank": false, "title": "MySQL", "type": "dashboards" @@ -75,9 +65,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "MongoDB" - ], + "tags": ["MongoDB"], "targetBlank": false, "title": "MongoDB", "type": "dashboards" @@ -86,9 +74,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "PostgreSQL" - ], + "tags": ["PostgreSQL"], "targetBlank": false, "title": "PostgreSQL", "type": "dashboards" @@ -97,9 +83,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "HA" - ], + "tags": ["HA"], "targetBlank": false, "title": "HA", "type": "dashboards" @@ -108,9 +92,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "Cloud" - ], + "tags": ["Cloud"], "targetBlank": false, "title": "Cloud", "type": "dashboards" @@ -119,9 +101,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "Insight" - ], + "tags": ["Insight"], "targetBlank": false, "title": "Insight", "type": "dashboards" @@ -130,9 +110,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "PMM" - ], + "tags": ["PMM"], "targetBlank": false, "title": "PMM", "type": "dashboards" @@ -148,9 +126,7 @@ "y": 0 }, "id": 382, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "", "type": "row" @@ -159,11 +135,7 @@ "cacheTimeout": null, "colorBackground": false, "colorValue": true, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], + "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], "datasource": "Prometheus", "decimals": 1, "description": "**MySQL Uptime**\n\nThe amount of time since the last restart of the MySQL server process.", @@ -186,9 +158,7 @@ "height": "125px", "id": 12, "interval": "$interval", - "links": [ - - ], + "links": [], "mappingType": 1, "mappingTypes": [ { @@ -224,12 +194,8 @@ "targets": [ { "calculatedInterval": "10m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_uptime{instance=\"$host\"}", "format": "time_series", "interval": "5m", @@ -245,20 +211,14 @@ "transparent": false, "type": "singlestat", "valueFontSize": "80%", - "valueMaps": [ - - ], + "valueMaps": [], "valueName": "current" }, { "cacheTimeout": null, "colorBackground": false, "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], + "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], "datasource": "Prometheus", "decimals": 2, "description": "**Current QPS**\n\nBased on the queries reported by MySQL's ``SHOW STATUS`` command, it is the number of statements executed by the server within the last second. This variable includes statements executed within stored programs, unlike the Questions variable. It does not count \n``COM_PING`` or ``COM_STATISTICS`` commands.", @@ -324,12 +284,8 @@ "targets": [ { "calculatedInterval": "10m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_queries{instance=\"$host\"}[$interval]) or irate(mysql_global_status_queries{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -345,20 +301,14 @@ "transparent": false, "type": "singlestat", "valueFontSize": "80%", - "valueMaps": [ - - ], + "valueMaps": [], "valueName": "current" }, { "cacheTimeout": null, "colorBackground": false, "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], + "colors": ["rgba(50, 172, 45, 0.97)", "rgba(237, 129, 40, 0.89)", "rgba(245, 54, 54, 0.9)"], "datasource": "Prometheus", "decimals": 0, "description": "**InnoDB Buffer Pool Size**\n\nInnoDB maintains a storage area called the buffer pool for caching data and indexes in memory. Knowing how the InnoDB buffer pool works, and taking advantage of it to keep frequently accessed data in memory, is one of the most important aspects of MySQL tuning. The goal is to keep the working set in memory. In most cases, this should be between 60%-90% of available memory on a dedicated database host, but depends on many factors.", @@ -424,12 +374,8 @@ "targets": [ { "calculatedInterval": "10m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_innodb_buffer_pool_size{instance=\"$host\"}", "format": "time_series", "interval": "5m", @@ -445,20 +391,14 @@ "transparent": false, "type": "singlestat", "valueFontSize": "80%", - "valueMaps": [ - - ], + "valueMaps": [], "valueName": "current" }, { "cacheTimeout": null, "colorBackground": false, "colorValue": true, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], + "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], "datasource": "Prometheus", "decimals": 0, "description": "**InnoDB Buffer Pool Size % of Total RAM**\n\nInnoDB maintains a storage area called the buffer pool for caching data and indexes in memory. Knowing how the InnoDB buffer pool works, and taking advantage of it to keep frequently accessed data in memory, is one of the most important aspects of MySQL tuning. The goal is to keep the working set in memory. In most cases, this should be between 60%-90% of available memory on a dedicated database host, but depends on many factors.", @@ -527,12 +467,8 @@ "targets": [ { "calculatedInterval": "10m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "(mysql_global_variables_innodb_buffer_pool_size{instance=\"$host\"} * 100) / on (instance) node_memory_MemTotal{instance=\"$host\"}", "format": "time_series", "interval": "5m", @@ -548,9 +484,7 @@ "transparent": false, "type": "singlestat", "valueFontSize": "80%", - "valueMaps": [ - - ], + "valueMaps": [], "valueName": "current" }, { @@ -562,17 +496,13 @@ "y": 3 }, "id": 383, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Connections", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -582,9 +512,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -632,12 +560,8 @@ "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "max(max_over_time(mysql_global_status_threads_connected{instance=\"$host\"}[$interval]) or mysql_global_status_threads_connected{instance=\"$host\"} )", "format": "time_series", "interval": "$interval", @@ -649,12 +573,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_max_used_connections{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -667,12 +587,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_max_connections{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -684,9 +600,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Connections", @@ -702,9 +616,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -730,9 +642,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -742,9 +652,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -767,9 +675,7 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, @@ -798,12 +704,8 @@ "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "max_over_time(mysql_global_status_threads_connected{instance=\"$host\"}[$interval]) or\nmax_over_time(mysql_global_status_threads_connected{instance=\"$host\"}[5m])", "format": "time_series", "hide": false, @@ -816,12 +718,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "max_over_time(mysql_global_status_threads_running{instance=\"$host\"}[$interval]) or\nmax_over_time(mysql_global_status_threads_running{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -841,9 +739,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Client Thread Activity", @@ -859,9 +755,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - "total" - ] + "values": ["total"] }, "yaxes": [ { @@ -895,17 +789,13 @@ "y": 11 }, "id": 384, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Table Locks", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -915,9 +805,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -953,21 +841,15 @@ "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_questions{instance=\"$host\"}[$interval]) or irate(mysql_global_status_questions{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -978,9 +860,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Questions", @@ -996,9 +876,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1022,9 +900,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1034,9 +910,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -1083,12 +957,8 @@ "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_thread_cache_size{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -1100,12 +970,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_threads_cached{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -1117,12 +983,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_threads_created{instance=\"$host\"}[$interval]) or irate(mysql_global_status_threads_created{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1133,9 +995,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Thread Cache", @@ -1152,9 +1012,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1186,17 +1044,13 @@ "y": 19 }, "id": 385, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Temporary Objects", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1205,9 +1059,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -1230,29 +1082,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_created_tmp_tables{instance=\"$host\"}[$interval]) or irate(mysql_global_status_created_tmp_tables{instance=\"$host\"}[5m])", "interval": "$interval", "intervalFactor": 1, @@ -1263,12 +1107,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_created_tmp_disk_tables{instance=\"$host\"}[$interval]) or irate(mysql_global_status_created_tmp_disk_tables{instance=\"$host\"}[5m])", "interval": "$interval", "intervalFactor": 1, @@ -1279,12 +1119,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_created_tmp_files{instance=\"$host\"}[$interval]) or irate(mysql_global_status_created_tmp_files{instance=\"$host\"}[5m])", "interval": "$interval", "intervalFactor": 1, @@ -1294,9 +1130,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Temporary Objects", @@ -1312,9 +1146,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1338,9 +1170,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1350,9 +1180,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -1377,29 +1205,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_select_full_join{instance=\"$host\"}[$interval]) or irate(mysql_global_status_select_full_join{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1411,12 +1231,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_select_full_range_join{instance=\"$host\"}[$interval]) or irate(mysql_global_status_select_full_range_join{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1428,12 +1244,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_select_range{instance=\"$host\"}[$interval]) or irate(mysql_global_status_select_range{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1445,12 +1257,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_select_range_check{instance=\"$host\"}[$interval]) or irate(mysql_global_status_select_range_check{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1462,12 +1270,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_select_scan{instance=\"$host\"}[$interval]) or irate(mysql_global_status_select_scan{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1478,9 +1282,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Select Types", @@ -1496,9 +1298,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1530,17 +1330,13 @@ "y": 27 }, "id": 386, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Sorts", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1550,9 +1346,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -1576,29 +1370,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_sort_rows{instance=\"$host\"}[$interval]) or irate(mysql_global_status_sort_rows{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1610,12 +1396,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_sort_range{instance=\"$host\"}[$interval]) or irate(mysql_global_status_sort_range{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1627,12 +1409,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_sort_merge_passes{instance=\"$host\"}[$interval]) or irate(mysql_global_status_sort_merge_passes{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1644,12 +1422,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_sort_scan{instance=\"$host\"}[$interval]) or irate(mysql_global_status_sort_scan{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1660,9 +1434,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Sorts", @@ -1678,9 +1450,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1704,9 +1474,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1716,9 +1484,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -1740,29 +1506,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_slow_queries{instance=\"$host\"}[$interval]) or irate(mysql_global_status_slow_queries{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1773,9 +1531,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Slow Queries", @@ -1791,9 +1547,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1827,17 +1581,13 @@ "y": 35 }, "id": 387, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Aborted", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1847,9 +1597,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -1871,29 +1619,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_aborted_connects{instance=\"$host\"}[$interval]) or irate(mysql_global_status_aborted_connects{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1905,12 +1645,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_aborted_clients{instance=\"$host\"}[$interval]) or irate(mysql_global_status_aborted_clients{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1922,9 +1658,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Aborted Connections", @@ -1940,9 +1674,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1968,9 +1700,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1980,9 +1710,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -2005,29 +1733,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_table_locks_immediate{instance=\"$host\"}[$interval]) or irate(mysql_global_status_table_locks_immediate{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -2039,12 +1759,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_table_locks_waited{instance=\"$host\"}[$interval]) or irate(mysql_global_status_table_locks_waited{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -2055,9 +1771,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Table Locks", @@ -2073,9 +1787,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2107,17 +1819,13 @@ "y": 43 }, "id": 388, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Network", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -2127,9 +1835,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -2152,29 +1858,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_bytes_received{instance=\"$host\"}[$interval]) or irate(mysql_global_status_bytes_received{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -2186,12 +1884,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_bytes_sent{instance=\"$host\"}[$interval]) or irate(mysql_global_status_bytes_sent{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -2202,9 +1896,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Network Traffic", @@ -2220,9 +1912,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2246,9 +1936,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": true, "dashLength": 10, "dashes": false, @@ -2258,9 +1946,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -2284,29 +1970,21 @@ }, "lines": false, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "increase(mysql_global_status_bytes_received{instance=\"$host\"}[1h])", "format": "time_series", "interval": "1h", @@ -2318,12 +1996,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "increase(mysql_global_status_bytes_sent{instance=\"$host\"}[1h])", "format": "time_series", "interval": "1h", @@ -2334,9 +2008,7 @@ "step": 3600 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": "24h", "timeShift": null, "title": "MySQL Network Usage Hourly", @@ -2352,9 +2024,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2386,17 +2056,13 @@ "y": 51 }, "id": 389, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Memory", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -2406,9 +2072,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -2538,9 +2202,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Internal Memory Overview", @@ -2556,9 +2218,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2592,17 +2252,13 @@ "y": 59 }, "id": 390, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Command, Handlers, Processes", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -2612,9 +2268,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -2651,21 +2305,15 @@ "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "topk(5, rate(mysql_global_status_commands_total{instance=\"$host\"}[$interval])>0) or topk(5, irate(mysql_global_status_commands_total{instance=\"$host\"}[5m])>0)", "format": "time_series", "hide": false, @@ -2677,9 +2325,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Top Command Counters", @@ -2695,9 +2341,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2721,9 +2365,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": true, "dashLength": 10, "dashes": false, @@ -2733,9 +2375,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -2771,21 +2411,15 @@ "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "topk(5, increase(mysql_global_status_commands_total{instance=\"$host\"}[1h])>0)", "format": "time_series", "interval": "1h", @@ -2796,9 +2430,7 @@ "step": 3600 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": "24h", "timeShift": null, "title": "Top Command Counters Hourly", @@ -2814,9 +2446,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2840,9 +2470,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -2852,9 +2480,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -2878,29 +2504,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_handlers_total{instance=\"$host\", handler!~\"commit|rollback|savepoint.*|prepare\"}[$interval]) or irate(mysql_global_status_handlers_total{instance=\"$host\", handler!~\"commit|rollback|savepoint.*|prepare\"}[5m])", "format": "time_series", "interval": "$interval", @@ -2911,9 +2529,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Handlers", @@ -2929,9 +2545,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2955,9 +2569,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -2966,9 +2578,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -2992,29 +2602,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_handlers_total{instance=\"$host\", handler=~\"commit|rollback|savepoint.*|prepare\"}[$interval]) or irate(mysql_global_status_handlers_total{instance=\"$host\", handler=~\"commit|rollback|savepoint.*|prepare\"}[5m])", "interval": "$interval", "intervalFactor": 1, @@ -3024,9 +2626,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Transaction Handlers", @@ -3042,9 +2642,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3068,9 +2666,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -3079,9 +2675,7 @@ "editable": true, "error": false, "fill": 0, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -3105,29 +2699,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_info_schema_threads{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -3138,9 +2724,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Process States", @@ -3156,9 +2740,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3182,9 +2764,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": true, "dashLength": 10, "dashes": false, @@ -3193,9 +2773,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -3219,29 +2797,21 @@ }, "lines": false, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "topk(5, avg_over_time(mysql_info_schema_threads{instance=\"$host\"}[1h]))", "interval": "1h", "intervalFactor": 1, @@ -3251,9 +2821,7 @@ "step": 3600 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": "24h", "timeShift": null, "title": "Top Process States Hourly", @@ -3269,9 +2837,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3303,17 +2869,13 @@ "y": 102 }, "id": 391, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Query Cache", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -3323,9 +2885,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -3348,29 +2908,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_qcache_free_memory{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -3382,12 +2934,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_query_cache_size{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -3398,9 +2946,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Query Cache Memory", @@ -3416,9 +2962,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3442,9 +2986,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -3454,9 +2996,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -3480,29 +3020,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_qcache_hits{instance=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_hits{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -3514,12 +3046,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_qcache_inserts{instance=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_inserts{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -3531,12 +3059,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_qcache_not_cached{instance=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_not_cached{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -3548,12 +3072,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_qcache_lowmem_prunes{instance=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_lowmem_prunes{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -3565,12 +3085,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_qcache_queries_in_cache{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -3581,9 +3097,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Query Cache Activity", @@ -3599,9 +3113,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3633,17 +3145,13 @@ "y": 110 }, "id": 392, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Files and Tables", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -3652,9 +3160,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -3677,29 +3183,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_opened_files{instance=\"$host\"}[$interval]) or irate(mysql_global_status_opened_files{instance=\"$host\"}[5m])", "interval": "$interval", "intervalFactor": 1, @@ -3709,9 +3207,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL File Openings", @@ -3727,9 +3223,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3753,9 +3247,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -3764,9 +3256,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -3789,29 +3279,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_open_files{instance=\"$host\"}", "interval": "$interval", "intervalFactor": 1, @@ -3822,12 +3304,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_open_files_limit{instance=\"$host\"}", "interval": "$interval", "intervalFactor": 1, @@ -3845,9 +3323,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Open Files", @@ -3863,9 +3339,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3897,17 +3371,13 @@ "y": 118 }, "id": 393, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Table Openings", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -3917,9 +3387,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -3966,12 +3434,8 @@ "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_opened_tables{instance=\"$host\"}[$interval]) or irate(mysql_global_status_opened_tables{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -4018,9 +3482,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Table Open Cache Status", @@ -4036,9 +3498,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4062,9 +3522,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -4074,9 +3532,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -4111,21 +3567,15 @@ "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_open_tables{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -4137,12 +3587,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_table_open_cache{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -4153,9 +3599,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Open Tables", @@ -4171,9 +3615,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4205,17 +3647,13 @@ "y": 126 }, "id": 394, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "MySQL Table Definition Cache", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -4225,9 +3663,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -4274,12 +3710,8 @@ "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_open_table_definitions{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -4291,12 +3723,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_table_definition_cache{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -4316,9 +3744,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Table Definition Cache", @@ -4334,9 +3760,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4368,17 +3792,13 @@ "y": 134 }, "id": 395, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "System Charts", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -4387,9 +3807,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -4413,29 +3831,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(node_vmstat_pgpgin{instance=\"$host\"}[$interval]) * 1024 or irate(node_vmstat_pgpgin{instance=\"$host\"}[5m]) * 1024", "format": "time_series", "interval": "$interval", @@ -4448,12 +3858,8 @@ }, { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(node_vmstat_pgpgout{instance=\"$host\"}[$interval]) * 1024 or irate(node_vmstat_pgpgout{instance=\"$host\"}[5m]) * 1024", "format": "time_series", "interval": "$interval", @@ -4465,9 +3871,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "I/O Activity", @@ -4484,9 +3888,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4511,9 +3913,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -4522,9 +3922,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -4549,29 +3947,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "max(node_memory_MemTotal{instance=\"$host\"}) without(job) - \n(max(node_memory_MemFree{instance=\"$host\"}) without(job) + \nmax(node_memory_Buffers{instance=\"$host\"}) without(job) + \n(max(node_memory_Cached{instance=\"$host\",job=~\"rds-enhanced|linux\"}) without (job) or \nmax(node_memory_Cached{instance=\"$host\",job=\"rds-basic\"}) without (job)))", "format": "time_series", "interval": "$interval", @@ -4584,12 +3974,8 @@ }, { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "node_memory_MemFree{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -4602,12 +3988,8 @@ }, { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "node_memory_Buffers{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -4620,12 +4002,8 @@ }, { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "max(node_memory_Cached{instance=~\"$host\",job=~\"rds-enhanced|linux\"}) without (job) or \nmax(node_memory_Cached{instance=~\"$host\",job=~\"rds-basic\"}) without (job)", "format": "time_series", "interval": "$interval", @@ -4637,9 +4015,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Memory Distribution", @@ -4656,9 +4032,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4700,9 +4074,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -4728,9 +4100,7 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, @@ -4759,12 +4129,8 @@ "targets": [ { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "clamp_max(((avg by (mode) ( (clamp_max(rate(node_cpu{instance=\"$host\",mode!=\"idle\"}[$interval]),1)) or (clamp_max(irate(node_cpu{instance=\"$host\",mode!=\"idle\"}[5m]),1)) ))*100 or (avg_over_time(node_cpu_average{instance=~\"$host\", mode!=\"total\", mode!=\"idle\"}[$interval]) or avg_over_time(node_cpu_average{instance=~\"$host\", mode!=\"total\", mode!=\"idle\"}[5m]))),100)", "format": "time_series", "hide": false, @@ -4794,9 +4160,7 @@ "refId": "C" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "CPU Usage / Load", @@ -4812,9 +4176,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4840,9 +4202,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -4851,9 +4211,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -4879,29 +4237,21 @@ }, "lines": false, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 1, "points": true, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "sum((rate(node_disk_read_time_ms{device!~\"dm-.+\", instance=\"$host\"}[$interval]) / rate(node_disk_reads_completed{device!~\"dm-.+\", instance=\"$host\"}[$interval])) or (irate(node_disk_read_time_ms{device!~\"dm-.+\", instance=\"$host\"}[5m]) / irate(node_disk_reads_completed{device!~\"dm-.+\", instance=\"$host\"}[5m]))\nor avg_over_time(aws_rds_read_latency_average{instance=\"$host\"}[$interval]) or avg_over_time(aws_rds_read_latency_average{instance=\"$host\"}[5m]))", "format": "time_series", "interval": "$interval", @@ -4914,12 +4264,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "sum((rate(node_disk_write_time_ms{device!~\"dm-.+\", instance=\"$host\"}[$interval]) / rate(node_disk_writes_completed{device!~\"dm-.+\", instance=\"$host\"}[$interval])) or (irate(node_disk_write_time_ms{device!~\"dm-.+\", instance=\"$host\"}[5m]) / irate(node_disk_writes_completed{device!~\"dm-.+\", instance=\"$host\"}[5m])) or \navg_over_time(aws_rds_write_latency_average{instance=\"$host\"}[$interval]) or avg_over_time(aws_rds_write_latency_average{instance=\"$host\"}[5m]))", "format": "time_series", "interval": "$interval", @@ -4931,9 +4277,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Disk Latency", @@ -4950,9 +4294,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4978,9 +4320,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -4989,9 +4329,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -5016,9 +4354,7 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, @@ -5036,12 +4372,8 @@ "targets": [ { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "sum(rate(node_network_receive_bytes{instance=\"$host\", device!=\"lo\"}[$interval])) or sum(irate(node_network_receive_bytes{instance=\"$host\", device!=\"lo\"}[5m])) or sum(max_over_time(rdsosmetrics_network_rx{instance=\"$host\"}[$interval])) or sum(max_over_time(rdsosmetrics_network_rx{instance=\"$host\"}[5m])) ", "format": "time_series", "interval": "$interval", @@ -5054,12 +4386,8 @@ }, { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "sum(rate(node_network_transmit_bytes{instance=\"$host\", device!=\"lo\"}[$interval])) or sum(irate(node_network_transmit_bytes{instance=\"$host\", device!=\"lo\"}[5m])) or\nsum(max_over_time(rdsosmetrics_network_tx{instance=\"$host\"}[$interval])) or sum(max_over_time(rdsosmetrics_network_tx{instance=\"$host\"}[5m]))", "format": "time_series", "interval": "$interval", @@ -5071,9 +4399,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Network Traffic", @@ -5090,9 +4416,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -5117,9 +4441,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -5128,9 +4450,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -5154,29 +4474,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(node_vmstat_pswpin{instance=\"$host\"}[$interval]) * 4096 or irate(node_vmstat_pswpin{instance=\"$host\"}[5m]) * 4096", "format": "time_series", "interval": "$interval", @@ -5189,12 +4501,8 @@ }, { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(node_vmstat_pswpout{instance=\"$host\"}[$interval]) * 4096 or irate(node_vmstat_pswpout{instance=\"$host\"}[5m]) * 4096", "format": "time_series", "interval": "$interval", @@ -5206,9 +4514,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Swap Activity", @@ -5225,9 +4531,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -5254,10 +4558,7 @@ ], "refresh": "1m", "schemaVersion": 16, - "tags": [ - "Percona", - "MySQL" - ], + "tags": ["Percona", "MySQL"], "templating": { "list": [ { @@ -5325,9 +4626,7 @@ { "allFormat": "glob", "allValue": null, - "current": { - - }, + "current": {}, "datasource": "Prometheus", "hide": 0, "includeAll": false, @@ -5335,18 +4634,14 @@ "multi": false, "multiFormat": "regex values", "name": "host", - "options": [ - - ], + "options": [], "query": "label_values(mysql_up, instance)", "refresh": 1, "refresh_on_load": false, "regex": "", "sort": 1, "tagValuesQuery": null, - "tags": [ - - ], + "tags": [], "tagsQuery": null, "type": "query", "useTags": false @@ -5363,18 +4658,7 @@ "hidden": false, "notice": false, "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], + "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"], "status": "Stable", "type": "timepicker" }, @@ -5382,4 +4666,4 @@ "title": "MySQL Overview", "uid": "MQWgroiiz", "version": 1 -} \ No newline at end of file +} diff --git a/devenv/docker/ha_test/README.md b/devenv/docker/ha_test/README.md index 7a8b9a7d055..b18b0f1acbf 100644 --- a/devenv/docker/ha_test/README.md +++ b/devenv/docker/ha_test/README.md @@ -53,6 +53,7 @@ $ docker-compose up -d ``` Browse + - http://grafana.loc/ - http://prometheus.loc/ diff --git a/devenv/docker/ha_test/grafana/provisioning/dashboards/alerts/overview.json b/devenv/docker/ha_test/grafana/provisioning/dashboards/alerts/overview.json index 0357c3d10f1..822052ac4ab 100644 --- a/devenv/docker/ha_test/grafana/provisioning/dashboards/alerts/overview.json +++ b/devenv/docker/ha_test/grafana/provisioning/dashboards/alerts/overview.json @@ -140,21 +140,10 @@ "to": "now" }, "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] + "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "", "title": "Overview", "uid": "xHy7-hAik", "version": 6 -} \ No newline at end of file +} diff --git a/devenv/docker/ha_test/grafana/provisioning/dashboards/mysql/overview.json b/devenv/docker/ha_test/grafana/provisioning/dashboards/mysql/overview.json index 2bf789366cc..204c8b392d6 100644 --- a/devenv/docker/ha_test/grafana/provisioning/dashboards/mysql/overview.json +++ b/devenv/docker/ha_test/grafana/provisioning/dashboards/mysql/overview.json @@ -10,9 +10,7 @@ "limit": 100, "name": "PMM Annotations", "showIn": 0, - "tags": [ - "pmm_annotation" - ], + "tags": ["pmm_annotation"], "type": "tags" }, { @@ -24,9 +22,7 @@ "limit": 100, "name": "Annotations & Alerts", "showIn": 0, - "tags": [ - - ], + "tags": [], "type": "dashboard" } ] @@ -41,9 +37,7 @@ "icon": "dashboard", "includeVars": true, "keepTime": true, - "tags": [ - "QAN" - ], + "tags": ["QAN"], "targetBlank": false, "title": "Query Analytics", "type": "link", @@ -53,9 +47,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "OS" - ], + "tags": ["OS"], "targetBlank": false, "title": "OS", "type": "dashboards" @@ -64,9 +56,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "MySQL" - ], + "tags": ["MySQL"], "targetBlank": false, "title": "MySQL", "type": "dashboards" @@ -75,9 +65,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "MongoDB" - ], + "tags": ["MongoDB"], "targetBlank": false, "title": "MongoDB", "type": "dashboards" @@ -86,9 +74,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "PostgreSQL" - ], + "tags": ["PostgreSQL"], "targetBlank": false, "title": "PostgreSQL", "type": "dashboards" @@ -97,9 +83,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "HA" - ], + "tags": ["HA"], "targetBlank": false, "title": "HA", "type": "dashboards" @@ -108,9 +92,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "Cloud" - ], + "tags": ["Cloud"], "targetBlank": false, "title": "Cloud", "type": "dashboards" @@ -119,9 +101,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "Insight" - ], + "tags": ["Insight"], "targetBlank": false, "title": "Insight", "type": "dashboards" @@ -130,9 +110,7 @@ "asDropdown": true, "includeVars": true, "keepTime": true, - "tags": [ - "PMM" - ], + "tags": ["PMM"], "targetBlank": false, "title": "PMM", "type": "dashboards" @@ -148,9 +126,7 @@ "y": 0 }, "id": 382, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "", "type": "row" @@ -159,11 +135,7 @@ "cacheTimeout": null, "colorBackground": false, "colorValue": true, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], + "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], "datasource": "Prometheus", "decimals": 1, "description": "**MySQL Uptime**\n\nThe amount of time since the last restart of the MySQL server process.", @@ -186,9 +158,7 @@ "height": "125px", "id": 12, "interval": "$interval", - "links": [ - - ], + "links": [], "mappingType": 1, "mappingTypes": [ { @@ -224,12 +194,8 @@ "targets": [ { "calculatedInterval": "10m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_uptime{instance=\"$host\"}", "format": "time_series", "interval": "5m", @@ -245,20 +211,14 @@ "transparent": false, "type": "singlestat", "valueFontSize": "80%", - "valueMaps": [ - - ], + "valueMaps": [], "valueName": "current" }, { "cacheTimeout": null, "colorBackground": false, "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], + "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], "datasource": "Prometheus", "decimals": 2, "description": "**Current QPS**\n\nBased on the queries reported by MySQL's ``SHOW STATUS`` command, it is the number of statements executed by the server within the last second. This variable includes statements executed within stored programs, unlike the Questions variable. It does not count \n``COM_PING`` or ``COM_STATISTICS`` commands.", @@ -324,12 +284,8 @@ "targets": [ { "calculatedInterval": "10m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_queries{instance=\"$host\"}[$interval]) or irate(mysql_global_status_queries{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -345,20 +301,14 @@ "transparent": false, "type": "singlestat", "valueFontSize": "80%", - "valueMaps": [ - - ], + "valueMaps": [], "valueName": "current" }, { "cacheTimeout": null, "colorBackground": false, "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], + "colors": ["rgba(50, 172, 45, 0.97)", "rgba(237, 129, 40, 0.89)", "rgba(245, 54, 54, 0.9)"], "datasource": "Prometheus", "decimals": 0, "description": "**InnoDB Buffer Pool Size**\n\nInnoDB maintains a storage area called the buffer pool for caching data and indexes in memory. Knowing how the InnoDB buffer pool works, and taking advantage of it to keep frequently accessed data in memory, is one of the most important aspects of MySQL tuning. The goal is to keep the working set in memory. In most cases, this should be between 60%-90% of available memory on a dedicated database host, but depends on many factors.", @@ -424,12 +374,8 @@ "targets": [ { "calculatedInterval": "10m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_innodb_buffer_pool_size{instance=\"$host\"}", "format": "time_series", "interval": "5m", @@ -445,20 +391,14 @@ "transparent": false, "type": "singlestat", "valueFontSize": "80%", - "valueMaps": [ - - ], + "valueMaps": [], "valueName": "current" }, { "cacheTimeout": null, "colorBackground": false, "colorValue": true, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], + "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], "datasource": "Prometheus", "decimals": 0, "description": "**InnoDB Buffer Pool Size % of Total RAM**\n\nInnoDB maintains a storage area called the buffer pool for caching data and indexes in memory. Knowing how the InnoDB buffer pool works, and taking advantage of it to keep frequently accessed data in memory, is one of the most important aspects of MySQL tuning. The goal is to keep the working set in memory. In most cases, this should be between 60%-90% of available memory on a dedicated database host, but depends on many factors.", @@ -527,12 +467,8 @@ "targets": [ { "calculatedInterval": "10m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "(mysql_global_variables_innodb_buffer_pool_size{instance=\"$host\"} * 100) / on (instance) node_memory_MemTotal{instance=\"$host\"}", "format": "time_series", "interval": "5m", @@ -548,9 +484,7 @@ "transparent": false, "type": "singlestat", "valueFontSize": "80%", - "valueMaps": [ - - ], + "valueMaps": [], "valueName": "current" }, { @@ -562,17 +496,13 @@ "y": 3 }, "id": 383, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Connections", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -582,9 +512,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -632,12 +560,8 @@ "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "max(max_over_time(mysql_global_status_threads_connected{instance=\"$host\"}[$interval]) or mysql_global_status_threads_connected{instance=\"$host\"} )", "format": "time_series", "interval": "$interval", @@ -649,12 +573,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_max_used_connections{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -667,12 +587,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_max_connections{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -684,9 +600,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Connections", @@ -702,9 +616,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -730,9 +642,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -742,9 +652,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -767,9 +675,7 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, @@ -798,12 +704,8 @@ "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "max_over_time(mysql_global_status_threads_connected{instance=\"$host\"}[$interval]) or\nmax_over_time(mysql_global_status_threads_connected{instance=\"$host\"}[5m])", "format": "time_series", "hide": false, @@ -816,12 +718,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "max_over_time(mysql_global_status_threads_running{instance=\"$host\"}[$interval]) or\nmax_over_time(mysql_global_status_threads_running{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -841,9 +739,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Client Thread Activity", @@ -859,9 +755,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - "total" - ] + "values": ["total"] }, "yaxes": [ { @@ -895,17 +789,13 @@ "y": 11 }, "id": 384, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Table Locks", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -915,9 +805,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -953,21 +841,15 @@ "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_questions{instance=\"$host\"}[$interval]) or irate(mysql_global_status_questions{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -978,9 +860,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Questions", @@ -996,9 +876,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1022,9 +900,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1034,9 +910,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -1083,12 +957,8 @@ "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_thread_cache_size{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -1100,12 +970,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_threads_cached{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -1117,12 +983,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_threads_created{instance=\"$host\"}[$interval]) or irate(mysql_global_status_threads_created{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1133,9 +995,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Thread Cache", @@ -1152,9 +1012,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1186,17 +1044,13 @@ "y": 19 }, "id": 385, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Temporary Objects", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1205,9 +1059,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -1230,29 +1082,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_created_tmp_tables{instance=\"$host\"}[$interval]) or irate(mysql_global_status_created_tmp_tables{instance=\"$host\"}[5m])", "interval": "$interval", "intervalFactor": 1, @@ -1263,12 +1107,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_created_tmp_disk_tables{instance=\"$host\"}[$interval]) or irate(mysql_global_status_created_tmp_disk_tables{instance=\"$host\"}[5m])", "interval": "$interval", "intervalFactor": 1, @@ -1279,12 +1119,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_created_tmp_files{instance=\"$host\"}[$interval]) or irate(mysql_global_status_created_tmp_files{instance=\"$host\"}[5m])", "interval": "$interval", "intervalFactor": 1, @@ -1294,9 +1130,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Temporary Objects", @@ -1312,9 +1146,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1338,9 +1170,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1350,9 +1180,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -1377,29 +1205,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_select_full_join{instance=\"$host\"}[$interval]) or irate(mysql_global_status_select_full_join{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1411,12 +1231,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_select_full_range_join{instance=\"$host\"}[$interval]) or irate(mysql_global_status_select_full_range_join{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1428,12 +1244,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_select_range{instance=\"$host\"}[$interval]) or irate(mysql_global_status_select_range{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1445,12 +1257,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_select_range_check{instance=\"$host\"}[$interval]) or irate(mysql_global_status_select_range_check{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1462,12 +1270,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_select_scan{instance=\"$host\"}[$interval]) or irate(mysql_global_status_select_scan{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1478,9 +1282,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Select Types", @@ -1496,9 +1298,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1530,17 +1330,13 @@ "y": 27 }, "id": 386, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Sorts", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1550,9 +1346,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -1576,29 +1370,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_sort_rows{instance=\"$host\"}[$interval]) or irate(mysql_global_status_sort_rows{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1610,12 +1396,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_sort_range{instance=\"$host\"}[$interval]) or irate(mysql_global_status_sort_range{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1627,12 +1409,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_sort_merge_passes{instance=\"$host\"}[$interval]) or irate(mysql_global_status_sort_merge_passes{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1644,12 +1422,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_sort_scan{instance=\"$host\"}[$interval]) or irate(mysql_global_status_sort_scan{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1660,9 +1434,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Sorts", @@ -1678,9 +1450,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1704,9 +1474,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1716,9 +1484,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -1740,29 +1506,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_slow_queries{instance=\"$host\"}[$interval]) or irate(mysql_global_status_slow_queries{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1773,9 +1531,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Slow Queries", @@ -1791,9 +1547,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1827,17 +1581,13 @@ "y": 35 }, "id": 387, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Aborted", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1847,9 +1597,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -1871,29 +1619,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_aborted_connects{instance=\"$host\"}[$interval]) or irate(mysql_global_status_aborted_connects{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1905,12 +1645,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_aborted_clients{instance=\"$host\"}[$interval]) or irate(mysql_global_status_aborted_clients{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -1922,9 +1658,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Aborted Connections", @@ -1940,9 +1674,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -1968,9 +1700,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -1980,9 +1710,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -2005,29 +1733,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_table_locks_immediate{instance=\"$host\"}[$interval]) or irate(mysql_global_status_table_locks_immediate{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -2039,12 +1759,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_table_locks_waited{instance=\"$host\"}[$interval]) or irate(mysql_global_status_table_locks_waited{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -2055,9 +1771,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Table Locks", @@ -2073,9 +1787,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2107,17 +1819,13 @@ "y": 43 }, "id": 388, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Network", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -2127,9 +1835,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -2152,29 +1858,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_bytes_received{instance=\"$host\"}[$interval]) or irate(mysql_global_status_bytes_received{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -2186,12 +1884,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_bytes_sent{instance=\"$host\"}[$interval]) or irate(mysql_global_status_bytes_sent{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -2202,9 +1896,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Network Traffic", @@ -2220,9 +1912,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2246,9 +1936,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": true, "dashLength": 10, "dashes": false, @@ -2258,9 +1946,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -2284,29 +1970,21 @@ }, "lines": false, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "increase(mysql_global_status_bytes_received{instance=\"$host\"}[1h])", "format": "time_series", "interval": "1h", @@ -2318,12 +1996,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "increase(mysql_global_status_bytes_sent{instance=\"$host\"}[1h])", "format": "time_series", "interval": "1h", @@ -2334,9 +2008,7 @@ "step": 3600 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": "24h", "timeShift": null, "title": "MySQL Network Usage Hourly", @@ -2352,9 +2024,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2386,17 +2056,13 @@ "y": 51 }, "id": 389, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Memory", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -2406,9 +2072,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -2538,9 +2202,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Internal Memory Overview", @@ -2556,9 +2218,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2592,17 +2252,13 @@ "y": 59 }, "id": 390, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Command, Handlers, Processes", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -2612,9 +2268,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -2651,21 +2305,15 @@ "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "topk(5, rate(mysql_global_status_commands_total{instance=\"$host\"}[$interval])>0) or topk(5, irate(mysql_global_status_commands_total{instance=\"$host\"}[5m])>0)", "format": "time_series", "hide": false, @@ -2677,9 +2325,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Top Command Counters", @@ -2695,9 +2341,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2721,9 +2365,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": true, "dashLength": 10, "dashes": false, @@ -2733,9 +2375,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -2771,21 +2411,15 @@ "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "topk(5, increase(mysql_global_status_commands_total{instance=\"$host\"}[1h])>0)", "format": "time_series", "interval": "1h", @@ -2796,9 +2430,7 @@ "step": 3600 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": "24h", "timeShift": null, "title": "Top Command Counters Hourly", @@ -2814,9 +2446,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2840,9 +2470,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -2852,9 +2480,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -2878,29 +2504,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_handlers_total{instance=\"$host\", handler!~\"commit|rollback|savepoint.*|prepare\"}[$interval]) or irate(mysql_global_status_handlers_total{instance=\"$host\", handler!~\"commit|rollback|savepoint.*|prepare\"}[5m])", "format": "time_series", "interval": "$interval", @@ -2911,9 +2529,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Handlers", @@ -2929,9 +2545,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -2955,9 +2569,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -2966,9 +2578,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -2992,29 +2602,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_handlers_total{instance=\"$host\", handler=~\"commit|rollback|savepoint.*|prepare\"}[$interval]) or irate(mysql_global_status_handlers_total{instance=\"$host\", handler=~\"commit|rollback|savepoint.*|prepare\"}[5m])", "interval": "$interval", "intervalFactor": 1, @@ -3024,9 +2626,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Transaction Handlers", @@ -3042,9 +2642,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3068,9 +2666,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -3079,9 +2675,7 @@ "editable": true, "error": false, "fill": 0, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -3105,29 +2699,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_info_schema_threads{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -3138,9 +2724,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Process States", @@ -3156,9 +2740,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3182,9 +2764,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": true, "dashLength": 10, "dashes": false, @@ -3193,9 +2773,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -3219,29 +2797,21 @@ }, "lines": false, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "topk(5, avg_over_time(mysql_info_schema_threads{instance=\"$host\"}[1h]))", "interval": "1h", "intervalFactor": 1, @@ -3251,9 +2821,7 @@ "step": 3600 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": "24h", "timeShift": null, "title": "Top Process States Hourly", @@ -3269,9 +2837,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3303,17 +2869,13 @@ "y": 102 }, "id": 391, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Query Cache", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -3323,9 +2885,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -3348,29 +2908,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_qcache_free_memory{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -3382,12 +2934,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_query_cache_size{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -3398,9 +2946,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Query Cache Memory", @@ -3416,9 +2962,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3442,9 +2986,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -3454,9 +2996,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -3480,29 +3020,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_qcache_hits{instance=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_hits{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -3514,12 +3046,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_qcache_inserts{instance=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_inserts{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -3531,12 +3059,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_qcache_not_cached{instance=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_not_cached{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -3548,12 +3072,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_qcache_lowmem_prunes{instance=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_lowmem_prunes{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -3565,12 +3085,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_qcache_queries_in_cache{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -3581,9 +3097,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Query Cache Activity", @@ -3599,9 +3113,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3633,17 +3145,13 @@ "y": 110 }, "id": 392, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Files and Tables", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -3652,9 +3160,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -3677,29 +3183,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_opened_files{instance=\"$host\"}[$interval]) or irate(mysql_global_status_opened_files{instance=\"$host\"}[5m])", "interval": "$interval", "intervalFactor": 1, @@ -3709,9 +3207,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL File Openings", @@ -3727,9 +3223,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3753,9 +3247,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -3764,9 +3256,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -3789,29 +3279,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_open_files{instance=\"$host\"}", "interval": "$interval", "intervalFactor": 1, @@ -3822,12 +3304,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_open_files_limit{instance=\"$host\"}", "interval": "$interval", "intervalFactor": 1, @@ -3845,9 +3323,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Open Files", @@ -3863,9 +3339,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -3897,17 +3371,13 @@ "y": 118 }, "id": 393, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "Table Openings", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -3917,9 +3387,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -3966,12 +3434,8 @@ "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(mysql_global_status_opened_tables{instance=\"$host\"}[$interval]) or irate(mysql_global_status_opened_tables{instance=\"$host\"}[5m])", "format": "time_series", "interval": "$interval", @@ -4018,9 +3482,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Table Open Cache Status", @@ -4036,9 +3498,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4062,9 +3522,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -4074,9 +3532,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -4111,21 +3567,15 @@ "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_open_tables{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -4137,12 +3587,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_table_open_cache{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -4153,9 +3599,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Open Tables", @@ -4171,9 +3615,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4205,17 +3647,13 @@ "y": 126 }, "id": 394, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "MySQL Table Definition Cache", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -4225,9 +3663,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 24, @@ -4274,12 +3710,8 @@ "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_status_open_table_definitions{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -4291,12 +3723,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "mysql_global_variables_table_definition_cache{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -4316,9 +3744,7 @@ "step": 20 } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "MySQL Table Definition Cache", @@ -4334,9 +3760,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4368,17 +3792,13 @@ "y": 134 }, "id": 395, - "panels": [ - - ], + "panels": [], "repeat": null, "title": "System Charts", "type": "row" }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -4387,9 +3807,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -4413,29 +3831,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(node_vmstat_pgpgin{instance=\"$host\"}[$interval]) * 1024 or irate(node_vmstat_pgpgin{instance=\"$host\"}[5m]) * 1024", "format": "time_series", "interval": "$interval", @@ -4448,12 +3858,8 @@ }, { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(node_vmstat_pgpgout{instance=\"$host\"}[$interval]) * 1024 or irate(node_vmstat_pgpgout{instance=\"$host\"}[5m]) * 1024", "format": "time_series", "interval": "$interval", @@ -4465,9 +3871,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "I/O Activity", @@ -4484,9 +3888,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4511,9 +3913,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -4522,9 +3922,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -4549,29 +3947,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "max(node_memory_MemTotal{instance=\"$host\"}) without(job) - \n(max(node_memory_MemFree{instance=\"$host\"}) without(job) + \nmax(node_memory_Buffers{instance=\"$host\"}) without(job) + \n(max(node_memory_Cached{instance=\"$host\",job=~\"rds-enhanced|linux\"}) without (job) or \nmax(node_memory_Cached{instance=\"$host\",job=\"rds-basic\"}) without (job)))", "format": "time_series", "interval": "$interval", @@ -4584,12 +3974,8 @@ }, { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "node_memory_MemFree{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -4602,12 +3988,8 @@ }, { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "node_memory_Buffers{instance=\"$host\"}", "format": "time_series", "interval": "$interval", @@ -4620,12 +4002,8 @@ }, { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "max(node_memory_Cached{instance=~\"$host\",job=~\"rds-enhanced|linux\"}) without (job) or \nmax(node_memory_Cached{instance=~\"$host\",job=~\"rds-basic\"}) without (job)", "format": "time_series", "interval": "$interval", @@ -4637,9 +4015,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Memory Distribution", @@ -4656,9 +4032,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4700,9 +4074,7 @@ "editable": true, "error": false, "fill": 6, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -4728,9 +4100,7 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, @@ -4759,12 +4129,8 @@ "targets": [ { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "clamp_max(((avg by (mode) ( (clamp_max(rate(node_cpu{instance=\"$host\",mode!=\"idle\"}[$interval]),1)) or (clamp_max(irate(node_cpu{instance=\"$host\",mode!=\"idle\"}[5m]),1)) ))*100 or (avg_over_time(node_cpu_average{instance=~\"$host\", mode!=\"total\", mode!=\"idle\"}[$interval]) or avg_over_time(node_cpu_average{instance=~\"$host\", mode!=\"total\", mode!=\"idle\"}[5m]))),100)", "format": "time_series", "hide": false, @@ -4794,9 +4160,7 @@ "refId": "C" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "CPU Usage / Load", @@ -4812,9 +4176,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4840,9 +4202,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -4851,9 +4211,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -4879,29 +4237,21 @@ }, "lines": false, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 1, "points": true, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "sum((rate(node_disk_read_time_ms{device!~\"dm-.+\", instance=\"$host\"}[$interval]) / rate(node_disk_reads_completed{device!~\"dm-.+\", instance=\"$host\"}[$interval])) or (irate(node_disk_read_time_ms{device!~\"dm-.+\", instance=\"$host\"}[5m]) / irate(node_disk_reads_completed{device!~\"dm-.+\", instance=\"$host\"}[5m]))\nor avg_over_time(aws_rds_read_latency_average{instance=\"$host\"}[$interval]) or avg_over_time(aws_rds_read_latency_average{instance=\"$host\"}[5m]))", "format": "time_series", "interval": "$interval", @@ -4914,12 +4264,8 @@ }, { "calculatedInterval": "2m", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "sum((rate(node_disk_write_time_ms{device!~\"dm-.+\", instance=\"$host\"}[$interval]) / rate(node_disk_writes_completed{device!~\"dm-.+\", instance=\"$host\"}[$interval])) or (irate(node_disk_write_time_ms{device!~\"dm-.+\", instance=\"$host\"}[5m]) / irate(node_disk_writes_completed{device!~\"dm-.+\", instance=\"$host\"}[5m])) or \navg_over_time(aws_rds_write_latency_average{instance=\"$host\"}[$interval]) or avg_over_time(aws_rds_write_latency_average{instance=\"$host\"}[5m]))", "format": "time_series", "interval": "$interval", @@ -4931,9 +4277,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Disk Latency", @@ -4950,9 +4294,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -4978,9 +4320,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -4989,9 +4329,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -5016,9 +4354,7 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, @@ -5036,12 +4372,8 @@ "targets": [ { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "sum(rate(node_network_receive_bytes{instance=\"$host\", device!=\"lo\"}[$interval])) or sum(irate(node_network_receive_bytes{instance=\"$host\", device!=\"lo\"}[5m])) or sum(max_over_time(rdsosmetrics_network_rx{instance=\"$host\"}[$interval])) or sum(max_over_time(rdsosmetrics_network_rx{instance=\"$host\"}[5m])) ", "format": "time_series", "interval": "$interval", @@ -5054,12 +4386,8 @@ }, { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "sum(rate(node_network_transmit_bytes{instance=\"$host\", device!=\"lo\"}[$interval])) or sum(irate(node_network_transmit_bytes{instance=\"$host\", device!=\"lo\"}[5m])) or\nsum(max_over_time(rdsosmetrics_network_tx{instance=\"$host\"}[$interval])) or sum(max_over_time(rdsosmetrics_network_tx{instance=\"$host\"}[5m]))", "format": "time_series", "interval": "$interval", @@ -5071,9 +4399,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Network Traffic", @@ -5090,9 +4416,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -5117,9 +4441,7 @@ } }, { - "aliasColors": { - - }, + "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, @@ -5128,9 +4450,7 @@ "editable": true, "error": false, "fill": 2, - "grid": { - - }, + "grid": {}, "gridPos": { "h": 7, "w": 12, @@ -5154,29 +4474,21 @@ }, "lines": true, "linewidth": 2, - "links": [ - - ], + "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", - "seriesOverrides": [ - - ], + "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(node_vmstat_pswpin{instance=\"$host\"}[$interval]) * 4096 or irate(node_vmstat_pswpin{instance=\"$host\"}[5m]) * 4096", "format": "time_series", "interval": "$interval", @@ -5189,12 +4501,8 @@ }, { "calculatedInterval": "2s", - "datasourceErrors": { - - }, - "errors": { - - }, + "datasourceErrors": {}, + "errors": {}, "expr": "rate(node_vmstat_pswpout{instance=\"$host\"}[$interval]) * 4096 or irate(node_vmstat_pswpout{instance=\"$host\"}[5m]) * 4096", "format": "time_series", "interval": "$interval", @@ -5206,9 +4514,7 @@ "target": "" } ], - "thresholds": [ - - ], + "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Swap Activity", @@ -5225,9 +4531,7 @@ "mode": "time", "name": null, "show": true, - "values": [ - - ] + "values": [] }, "yaxes": [ { @@ -5254,10 +4558,7 @@ ], "refresh": "1m", "schemaVersion": 16, - "tags": [ - "Percona", - "MySQL" - ], + "tags": ["Percona", "MySQL"], "templating": { "list": [ { @@ -5325,9 +4626,7 @@ { "allFormat": "glob", "allValue": null, - "current": { - - }, + "current": {}, "datasource": "Prometheus", "hide": 0, "includeAll": false, @@ -5335,18 +4634,14 @@ "multi": false, "multiFormat": "regex values", "name": "host", - "options": [ - - ], + "options": [], "query": "label_values(mysql_up, instance)", "refresh": 1, "refresh_on_load": false, "regex": "", "sort": 1, "tagValuesQuery": null, - "tags": [ - - ], + "tags": [], "tagsQuery": null, "type": "query", "useTags": false @@ -5363,18 +4658,7 @@ "hidden": false, "notice": false, "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], + "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"], "status": "Stable", "type": "timepicker" }, @@ -5382,4 +4666,4 @@ "title": "MySQL Overview", "uid": "MQWgroiiz", "version": 1 -} \ No newline at end of file +} diff --git a/devenv/docker/loadtest/README.md b/devenv/docker/loadtest/README.md index 34faf18d72f..92d55205093 100644 --- a/devenv/docker/loadtest/README.md +++ b/devenv/docker/loadtest/README.md @@ -59,7 +59,6 @@ Run API key test (option `-k` must be a valid `admin` API key) $ ./run.sh -c auth_token_test -k "" ``` - Example output: ```bash diff --git a/devenv/frontend-service/README.md b/devenv/frontend-service/README.md index 97725978e1a..e0a3491ac53 100644 --- a/devenv/frontend-service/README.md +++ b/devenv/frontend-service/README.md @@ -2,16 +2,16 @@ This directory contains a docker compose + Tilt setup for running a full frontend service stack locally. It contains: - - frontend-service - - backend api - - static asset cdn. +- frontend-service +- backend api +- static asset cdn. ## Getting started On top of the main Grafana development dependencies, you will need installed: - - [Docker](https://docs.docker.com/get-started/get-docker/) - - [Tilt](https://docs.tilt.dev/install.html). At the moment we're not using Kubernetes locally, so you shouldn't need to follow the instructions to install kubectl or kind. +- [Docker](https://docs.docker.com/get-started/get-docker/) +- [Tilt](https://docs.tilt.dev/install.html). At the moment we're not using Kubernetes locally, so you shouldn't need to follow the instructions to install kubectl or kind. To start the stack, from the root of the Grafana project run `make frontend-service-up`. Tilt will orchestrate the webpack and docker builds, and then run the services with Docker compose. You can monitor it's progress and see logs with the URL to the Tilt console. Once done, you can access Grafana at `http://localhost:3000`. @@ -21,8 +21,8 @@ Quitting the process will not stop the service from running. Run `make frontend- To simulate the `/bootdata` endpoint being available, there are special control URLs you can visit that use cookies to control behaviour: - - `/-/down` - Simulates the endpoint being unavailable for 60 seconds. - - `/-/down/:seconds` - Simulates the endpoint being unavailable for a custom number of seconds. - - `/-/up` - Restores the endpoint to being available. +- `/-/down` - Simulates the endpoint being unavailable for 60 seconds. +- `/-/down/:seconds` - Simulates the endpoint being unavailable for a custom number of seconds. +- `/-/up` - Restores the endpoint to being available. When unavailable, the API will return `HTTP 503 Service Unavailable` with a JSON payload. From a4ed9c4bb653e7d3863eb62e9e56ed03e4019667 Mon Sep 17 00:00:00 2001 From: Matheus Macabu Date: Mon, 4 Aug 2025 13:01:08 +0200 Subject: [PATCH 53/89] Secrets: Better error message for not matching resource owner (#109113) --- pkg/registry/apis/secret/service/inline_secure_value.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/registry/apis/secret/service/inline_secure_value.go b/pkg/registry/apis/secret/service/inline_secure_value.go index 365ff00cd6e..a02b9c5bf97 100644 --- a/pkg/registry/apis/secret/service/inline_secure_value.go +++ b/pkg/registry/apis/secret/service/inline_secure_value.go @@ -117,7 +117,10 @@ func (s *inlineSecureValueService) isSecureValueOwnedByResource(ctx context.Cont return true, nil // The secure value is owned by the same owner reference, pass! } - return false, fmt.Errorf("secure value %s is not owned by %v but by %v", name, owner, actualOwner) + return false, fmt.Errorf( + "secure value %s is not owned by %s/%s/%s/%s but by %s/%s/%s", + name, owner.APIGroup, owner.APIVersion, owner.Kind, owner.Name, actualOwner.APIVersion, actualOwner.Kind, actualOwner.Name, + ) } // not owned From ff9ab1763601c5290e8636c47eac81282f1f0292 Mon Sep 17 00:00:00 2001 From: Andres Martinez Gotor Date: Mon, 4 Aug 2025 13:27:35 +0200 Subject: [PATCH 54/89] Fix useRecentlyUsedDataSources (#108971) --- public/app/features/datasources/hooks.test.ts | 114 ++++++++++++++++++ public/app/features/datasources/hooks.ts | 7 +- 2 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 public/app/features/datasources/hooks.test.ts diff --git a/public/app/features/datasources/hooks.test.ts b/public/app/features/datasources/hooks.test.ts new file mode 100644 index 00000000000..a36f8ac2e8b --- /dev/null +++ b/public/app/features/datasources/hooks.test.ts @@ -0,0 +1,114 @@ +import { renderHook, act } from '@testing-library/react'; + +import { TestDataSettings } from '../query/state/mocks/mockDataSource'; + +import { useRecentlyUsedDataSources } from './hooks'; + +// Mock react-use's useLocalStorage +jest.mock('react-use', () => ({ + useLocalStorage: jest.fn(), +})); + +const mockUseLocalStorage = jest.requireMock('react-use').useLocalStorage; + +describe('useRecentlyUsedDataSources', () => { + let mockSetStorage: jest.Mock; + + beforeEach(() => { + jest.clearAllMocks(); + mockSetStorage = jest.fn(); + + // Default mock implementation + mockUseLocalStorage.mockReturnValue([[], mockSetStorage]); + }); + + describe('basic functionality', () => { + it('should return an array and a function', () => { + const { result } = renderHook(() => useRecentlyUsedDataSources()); + + expect(Array.isArray(result.current[0])).toBe(true); + expect(typeof result.current[1]).toBe('function'); + }); + + it('should return stored values from local storage', () => { + const storedValues = ['uid1', 'uid2', 'uid3']; + mockUseLocalStorage.mockReturnValue([storedValues, mockSetStorage]); + + const { result } = renderHook(() => useRecentlyUsedDataSources()); + + expect(result.current[0]).toEqual(storedValues); + }); + }); + + describe('adding data sources', () => { + it('should add a new data source to an empty list', () => { + const { result } = renderHook(() => useRecentlyUsedDataSources()); + const dataSource = { ...TestDataSettings, uid: 'test-uid' }; + + act(() => { + result.current[1](dataSource); + }); + + expect(mockSetStorage).toHaveBeenCalledWith(['test-uid']); + }); + + it('should add a new data source to the end of existing list', () => { + const existingValues = ['uid1', 'uid2']; + mockUseLocalStorage.mockReturnValue([existingValues, mockSetStorage]); + + const { result } = renderHook(() => useRecentlyUsedDataSources()); + const dataSource = { ...TestDataSettings, uid: 'test-uid' }; + + act(() => { + result.current[1](dataSource); + }); + + expect(mockSetStorage).toHaveBeenCalledWith(['uid1', 'uid2', 'test-uid']); + }); + + it('should not store built-in data sources', () => { + const { result } = renderHook(() => useRecentlyUsedDataSources()); + const builtInDataSource = { ...TestDataSettings, meta: { ...TestDataSettings.meta, builtIn: true } }; + + act(() => { + result.current[1](builtInDataSource); + }); + + expect(mockSetStorage).not.toHaveBeenCalled(); + }); + }); + + describe('duplicate handling', () => { + it('should move existing data source to the end when adding duplicate', () => { + const existingValues = ['uid1', 'test-uid', 'uid3']; + mockUseLocalStorage.mockReturnValue([existingValues, mockSetStorage]); + + const { result } = renderHook(() => useRecentlyUsedDataSources()); + const dataSource = { ...TestDataSettings, uid: 'test-uid' }; + + act(() => { + result.current[1](dataSource); + }); + + // uid2 should be moved to the end, others should maintain order + expect(mockSetStorage).toHaveBeenCalledWith(['uid1', 'uid3', 'test-uid']); + }); + }); + + describe('maximum items limit', () => { + it('should limit the array to 5 items when adding to a full list', () => { + const existingValues = ['uid1', 'uid2', 'uid3', 'uid4', 'uid5']; + mockUseLocalStorage.mockReturnValue([existingValues, mockSetStorage]); + + const { result } = renderHook(() => useRecentlyUsedDataSources()); + const dataSource = { ...TestDataSettings, uid: 'test-uid' }; + + act(() => { + result.current[1](dataSource); + }); + + // Should remove the first item and add new one at the end + expect(mockSetStorage).toHaveBeenCalledWith(['uid2', 'uid3', 'uid4', 'uid5', 'test-uid']); + }); + }); +}); diff --git a/public/app/features/datasources/hooks.ts b/public/app/features/datasources/hooks.ts index 3a08d716cb2..73c356c4ff8 100644 --- a/public/app/features/datasources/hooks.ts +++ b/public/app/features/datasources/hooks.ts @@ -28,7 +28,12 @@ export function useRecentlyUsedDataSources(): [string[], (ds: DataSourceInstance ); setStorage([...value, ds.uid]); } else { - setStorage([...value, ds.uid].slice(1, 6)); + const newArray = [...value, ds.uid]; + if (newArray.length > 5) { + setStorage(newArray.slice(1, 6)); + } else { + setStorage(newArray); + } } }, [value, setStorage] From 3a84f6ad42fd40c34ca0ae906013cb5b3eb9d2a2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 13:05:31 +0100 Subject: [PATCH 55/89] Update dependency react-hook-form to v7.62.0 (#109114) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 023528f1dd0..d2a1dec4500 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27011,11 +27011,11 @@ __metadata: linkType: hard "react-hook-form@npm:^7.49.2": - version: 7.61.1 - resolution: "react-hook-form@npm:7.61.1" + version: 7.62.0 + resolution: "react-hook-form@npm:7.62.0" peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - checksum: 10/961c5ad1f6fe694a66c1aa9934e5cd7ef014a8fd0d4ed15ac6d97d31d8d53b9e6196cb8b66d119883f49508c11589bc4b1478e1080790eb2e91c476551c82186 + checksum: 10/092dcf0317ed3e314b124ed9df3f3494cf3447326078cd857f6fdc47aad0504e466ab2fb593bbb8e79c247b8772159f83aebe54a7e5799926b00d7e401d127a6 languageName: node linkType: hard From e88b54e9d3412508342809fd0bb85f836cd50d73 Mon Sep 17 00:00:00 2001 From: Ezequiel Victorero Date: Mon, 4 Aug 2025 09:12:12 -0300 Subject: [PATCH 56/89] ShortURL: Create k8s API (#108821) --- .github/CODEOWNERS | 1 + Dockerfile | 1 + apps/shorturl/Makefile | 9 + apps/shorturl/go.mod | 92 +++++ apps/shorturl/go.sum | 236 +++++++++++++ apps/shorturl/kinds/cue.mod/module.cue | 2 + apps/shorturl/kinds/manifest.cue | 68 ++++ apps/shorturl/kinds/shorturl.cue | 16 + .../pkg/apis/shorturl/v1alpha1/constants.go | 18 + .../shorturl/v1alpha1/shorturl_codec_gen.go | 28 ++ .../v1alpha1/shorturl_metadata_gen.go | 31 ++ .../shorturl/v1alpha1/shorturl_object_gen.go | 319 ++++++++++++++++++ .../shorturl/v1alpha1/shorturl_schema_gen.go | 34 ++ .../shorturl/v1alpha1/shorturl_spec_gen.go | 14 + .../shorturl/v1alpha1/shorturl_status_gen.go | 46 +++ apps/shorturl/pkg/apis/shorturl_manifest.go | 75 ++++ apps/shorturl/pkg/app/app.go | 69 ++++ .../shorturl/v1alpha1/shorturl_object_gen.ts | 49 +++ .../shorturl/v1alpha1/types.metadata.gen.ts | 30 ++ .../shorturl/v1alpha1/types.spec.gen.ts | 11 + .../shorturl/v1alpha1/types.status.gen.ts | 33 ++ go.work | 1 + go.work.sum | 4 +- .../src/types/featureToggles.gen.ts | 4 + pkg/registry/apps/apps.go | 9 +- pkg/registry/apps/shorturl/conversions.go | 34 ++ pkg/registry/apps/shorturl/legacy_storage.go | 145 ++++++++ pkg/registry/apps/shorturl/register.go | 97 ++++++ pkg/registry/apps/wireset.go | 2 + pkg/server/wire_gen.go | 13 +- pkg/services/featuremgmt/registry.go | 7 + pkg/services/featuremgmt/toggles_gen.csv | 1 + pkg/services/featuremgmt/toggles_gen.go | 4 + pkg/services/featuremgmt/toggles_gen.json | 13 + 34 files changed, 1510 insertions(+), 6 deletions(-) create mode 100644 apps/shorturl/Makefile create mode 100644 apps/shorturl/go.mod create mode 100644 apps/shorturl/go.sum create mode 100644 apps/shorturl/kinds/cue.mod/module.cue create mode 100644 apps/shorturl/kinds/manifest.cue create mode 100644 apps/shorturl/kinds/shorturl.cue create mode 100644 apps/shorturl/pkg/apis/shorturl/v1alpha1/constants.go create mode 100644 apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_codec_gen.go create mode 100644 apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_metadata_gen.go create mode 100644 apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_object_gen.go create mode 100644 apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_schema_gen.go create mode 100644 apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_spec_gen.go create mode 100644 apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_status_gen.go create mode 100644 apps/shorturl/pkg/apis/shorturl_manifest.go create mode 100644 apps/shorturl/pkg/app/app.go create mode 100644 apps/shorturl/plugin/src/generated/shorturl/v1alpha1/shorturl_object_gen.ts create mode 100644 apps/shorturl/plugin/src/generated/shorturl/v1alpha1/types.metadata.gen.ts create mode 100644 apps/shorturl/plugin/src/generated/shorturl/v1alpha1/types.spec.gen.ts create mode 100644 apps/shorturl/plugin/src/generated/shorturl/v1alpha1/types.status.gen.ts create mode 100644 pkg/registry/apps/shorturl/conversions.go create mode 100644 pkg/registry/apps/shorturl/legacy_storage.go create mode 100644 pkg/registry/apps/shorturl/register.go diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 749fa4f3058..e667e9fe6e0 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -83,6 +83,7 @@ /apps/dashboard/ @grafana/grafana-app-platform-squad @grafana/dashboards-squad /apps/folder/ @grafana/grafana-app-platform-squad /apps/playlist/ @grafana/grafana-app-platform-squad +/apps/shorturl/ @grafana/sharing-squad /apps/secret/ @grafana/grafana-operator-experience-squad /apps/investigations/ @fcjack @matryer @svennergr /apps/advisor/ @grafana/plugins-platform-backend diff --git a/Dockerfile b/Dockerfile index 7300e989823..e7c0ec0fadb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -83,6 +83,7 @@ COPY pkg/storage/unified/apistore pkg/storage/unified/apistore COPY pkg/semconv pkg/semconv COPY pkg/aggregator pkg/aggregator COPY apps/playlist apps/playlist +COPY apps/shorturl apps/shorturl COPY apps/provisioning apps/provisioning COPY apps/secret apps/secret COPY apps/investigations apps/investigations diff --git a/apps/shorturl/Makefile b/apps/shorturl/Makefile new file mode 100644 index 00000000000..230bfd4149a --- /dev/null +++ b/apps/shorturl/Makefile @@ -0,0 +1,9 @@ +include ../sdk.mk + +.PHONY: generate # Run Grafana App SDK code generation +generate: install-app-sdk update-app-sdk + @$(APP_SDK_BIN) generate \ + --source=./kinds/ \ + --gogenpath=./pkg/apis \ + --grouping=group \ + --defencoding=none \ No newline at end of file diff --git a/apps/shorturl/go.mod b/apps/shorturl/go.mod new file mode 100644 index 00000000000..deaba460063 --- /dev/null +++ b/apps/shorturl/go.mod @@ -0,0 +1,92 @@ +module github.com/grafana/grafana/apps/shorturl + +go 1.24.0 + +toolchain go1.24.5 + +require ( + github.com/grafana/grafana-app-sdk v0.40.2 + k8s.io/apimachinery v0.33.3 + k8s.io/klog/v2 v2.130.1 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect + github.com/cenkalti/backoff/v5 v5.0.2 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.12.1 // indirect + github.com/evanphx/json-patch v5.9.11+incompatible // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/getkin/kin-openapi v0.132.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-test/deep v1.1.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/gnostic-models v0.6.9 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grafana/grafana-app-sdk/logging v0.40.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mailru/easyjson v0.9.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect + github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect + github.com/onsi/ginkgo/v2 v2.22.2 // indirect + github.com/onsi/gomega v1.36.2 // indirect + github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/prometheus/client_golang v1.22.0 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.65.0 // indirect + github.com/prometheus/procfs v0.16.1 // indirect + github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/spf13/pflag v1.0.7 // indirect + github.com/x448/float16 v0.8.4 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel v1.37.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 // indirect + go.opentelemetry.io/otel/metric v1.37.0 // indirect + go.opentelemetry.io/otel/sdk v1.37.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect + go.opentelemetry.io/otel/trace v1.37.0 // indirect + go.opentelemetry.io/proto/otlp v1.7.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect + golang.org/x/net v0.42.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.34.0 // indirect + golang.org/x/term v0.33.0 // indirect + golang.org/x/text v0.27.0 // indirect + golang.org/x/time v0.11.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect + google.golang.org/grpc v1.74.2 // indirect + google.golang.org/protobuf v1.36.6 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.33.3 // indirect + k8s.io/apiextensions-apiserver v0.33.3 // indirect + k8s.io/client-go v0.33.3 // indirect + k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect + k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect + sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect + sigs.k8s.io/yaml v1.5.0 // indirect +) diff --git a/apps/shorturl/go.sum b/apps/shorturl/go.sum new file mode 100644 index 00000000000..88512ac2ed8 --- /dev/null +++ b/apps/shorturl/go.sum @@ -0,0 +1,236 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous= +github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c= +github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= +github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= +github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= +github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk= +github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= +github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= +github.com/google/go-cmp v0.5.9/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/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grafana/grafana-app-sdk v0.40.2 h1:j2ftFuqhX+exYUipfEjeWDs3i7oiJkweTF8gFLL7wWU= +github.com/grafana/grafana-app-sdk v0.40.2/go.mod h1:BbNXPNki3mtbkWxYqJsyA1Cj9AShSyaY33z8WkyfVv0= +github.com/grafana/grafana-app-sdk/logging v0.40.1 h1:ru+GqbaQk6jthA5l2Yo1WI/JbNXKNQmLiqNrxz7HGP4= +github.com/grafana/grafana-app-sdk/logging v0.40.1/go.mod h1:otUD9XpJD7A5sCLb8mcs9hIXGdeV6lnhzVwe747g4RU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +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= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= +github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= +github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= +github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= +github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= +github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU= +github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= +github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 h1:EtFWSnwW9hGObjkIdmlnWSydO+Qs8OwzfzXLUPg4xOc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0/go.mod h1:QjUEoiGCPkvFZ/MjK6ZZfNOS6mfVEVKYE99dFhuN2LI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 h1:bDMKF3RUSxshZ5OjOTi8rsHGaPKsAt76FaqgvIUySLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0/go.mod h1:dDT67G/IkA46Mr2l9Uj7HsQVwsjASyV9SjGofsiUZDA= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= +go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= +go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= +golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= +gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= +google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= +google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +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= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8= +k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE= +k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs= +k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8= +k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA= +k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA= +k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= +k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= +k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI= +sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= +sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= diff --git a/apps/shorturl/kinds/cue.mod/module.cue b/apps/shorturl/kinds/cue.mod/module.cue new file mode 100644 index 00000000000..2e6cdd1ee5b --- /dev/null +++ b/apps/shorturl/kinds/cue.mod/module.cue @@ -0,0 +1,2 @@ +module: "github.com/grafana/grafana/apps/shorturl/kinds" +language: version: "v0.8.2" diff --git a/apps/shorturl/kinds/manifest.cue b/apps/shorturl/kinds/manifest.cue new file mode 100644 index 00000000000..27519d040af --- /dev/null +++ b/apps/shorturl/kinds/manifest.cue @@ -0,0 +1,68 @@ +package kinds + +manifest: { + // appName is the unique name of your app. It is used to reference the app from other config objects, + // and to generate the group used by your app in the app platform API. + appName: "shorturl" + groupOverride: "shorturl.grafana.app" + // groupOverride can be used to specify a non-appName-based API group. + // By default, an app's API group is LOWER(REPLACE(appName, '-', '')).ext.grafana.com, + // but there are cases where this needs to be changed. + // Keep in mind that changing this after an app is deployed can cause problems with clients and/or kind data. + // groupOverride: foo.ext.grafana.app + + // versions is a map of versions supported by your app. Version names should follow the format "v" or + // "v(alpha|beta)". Each version contains the kinds your app manages for that version. + // If your app needs access to kinds managed by another app, use permissions.accessKinds to allow your app access. + versions: { + "v1alpha1": v1alpha1 + } + // extraPermissions contains any additional permissions your app may require to function. + // Your app will always have all permissions for each kind it manages (the items defined in 'kinds'). + extraPermissions: { + // If your app needs access to additional kinds supplied by other apps, you can list them here + accessKinds: [ + // Here is an example for your app accessing the playlist kind for reads and watch + // { + // group: "playlist.grafana.app" + // resource: "playlists" + // actions: ["get","list","watch"] + // } + ] + } +} + +// v1alpha1 is the v1alpha1 version of the app's API. +// It includes kinds which the v1alpha1 API serves, and (future) custom routes served globally from the v1alpha1 version. +v1alpha1: { + // kinds is the list of kinds served by this version + kinds: [shorturl] + // [OPTIONAL] + // served indicates whether this particular version is served by the API server. + // served should be set to false before a version is removed from the manifest entirely. + // served defaults to true if not present. + served: true + // [OPTIONAL] + // Codegen is a trait that tells the grafana-app-sdk, or other code generation tooling, how to process this kind. + // If not present, default values within the codegen trait are used. + // If you wish to specify codegen per-version, put this section in the version's object + // (for example, v1alpha1) instead. + codegen: { + // [OPTIONAL] + // ts contains TypeScript code generation properties for the kind + ts: { + // [OPTIONAL] + // enabled indicates whether the CLI should generate front-end TypeScript code for the kind. + // Defaults to true if not present. + enabled: true + } + // [OPTIONAL] + // go contains go code generation properties for the kind + go: { + // [OPTIONAL] + // enabled indicates whether the CLI should generate back-end go code for the kind. + // Defaults to true if not present. + enabled: true + } + } +} diff --git a/apps/shorturl/kinds/shorturl.cue b/apps/shorturl/kinds/shorturl.cue new file mode 100644 index 00000000000..d88e10ad3e3 --- /dev/null +++ b/apps/shorturl/kinds/shorturl.cue @@ -0,0 +1,16 @@ +package kinds + +shorturl: { + kind: "ShortURL" + pluralName: "ShortURLs" + schema: { + spec: { + // The original path to where the short url is linking too e.g. https://localhost:3000/eer8i1kictngga/new-dashboard-with-lib-panel + path: string + } + status: { + // The last time the short URL was used, 0 is the initial value + lastSeenAt: int64 + } + } +} diff --git a/apps/shorturl/pkg/apis/shorturl/v1alpha1/constants.go b/apps/shorturl/pkg/apis/shorturl/v1alpha1/constants.go new file mode 100644 index 00000000000..e6000ff1f42 --- /dev/null +++ b/apps/shorturl/pkg/apis/shorturl/v1alpha1/constants.go @@ -0,0 +1,18 @@ +package v1alpha1 + +import "k8s.io/apimachinery/pkg/runtime/schema" + +const ( + // APIGroup is the API group used by all kinds in this package + APIGroup = "shorturl.grafana.app" + // APIVersion is the API version used by all kinds in this package + APIVersion = "v1alpha1" +) + +var ( + // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package + GroupVersion = schema.GroupVersion{ + Group: APIGroup, + Version: APIVersion, + } +) diff --git a/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_codec_gen.go b/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_codec_gen.go new file mode 100644 index 00000000000..15d7493bb80 --- /dev/null +++ b/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_codec_gen.go @@ -0,0 +1,28 @@ +// +// Code generated by grafana-app-sdk. DO NOT EDIT. +// + +package v1alpha1 + +import ( + "encoding/json" + "io" + + "github.com/grafana/grafana-app-sdk/resource" +) + +// ShortURLJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding +type ShortURLJSONCodec struct{} + +// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into` +func (*ShortURLJSONCodec) Read(reader io.Reader, into resource.Object) error { + return json.NewDecoder(reader).Decode(into) +} + +// Write writes JSON-encoded bytes into `writer` marshaled from `from` +func (*ShortURLJSONCodec) Write(writer io.Writer, from resource.Object) error { + return json.NewEncoder(writer).Encode(from) +} + +// Interface compliance checks +var _ resource.Codec = &ShortURLJSONCodec{} diff --git a/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_metadata_gen.go b/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_metadata_gen.go new file mode 100644 index 00000000000..e7509c1a38e --- /dev/null +++ b/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_metadata_gen.go @@ -0,0 +1,31 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" +) + +// metadata contains embedded CommonMetadata and can be extended with custom string fields +// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here +// without external reference as using the CommonMetadata reference breaks thema codegen. +type ShortURLMetadata struct { + UpdateTimestamp time.Time `json:"updateTimestamp"` + CreatedBy string `json:"createdBy"` + Uid string `json:"uid"` + CreationTimestamp time.Time `json:"creationTimestamp"` + DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"` + Finalizers []string `json:"finalizers"` + ResourceVersion string `json:"resourceVersion"` + Generation int64 `json:"generation"` + UpdatedBy string `json:"updatedBy"` + Labels map[string]string `json:"labels"` +} + +// NewShortURLMetadata creates a new ShortURLMetadata object. +func NewShortURLMetadata() *ShortURLMetadata { + return &ShortURLMetadata{ + Finalizers: []string{}, + Labels: map[string]string{}, + } +} diff --git a/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_object_gen.go b/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_object_gen.go new file mode 100644 index 00000000000..734af74aae3 --- /dev/null +++ b/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_object_gen.go @@ -0,0 +1,319 @@ +// +// Code generated by grafana-app-sdk. DO NOT EDIT. +// + +package v1alpha1 + +import ( + "fmt" + "github.com/grafana/grafana-app-sdk/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "time" +) + +// +k8s:openapi-gen=true +type ShortURL struct { + metav1.TypeMeta `json:",inline" yaml:",inline"` + metav1.ObjectMeta `json:"metadata" yaml:"metadata"` + + // Spec is the spec of the ShortURL + Spec ShortURLSpec `json:"spec" yaml:"spec"` + + Status ShortURLStatus `json:"status" yaml:"status"` +} + +func (o *ShortURL) GetSpec() any { + return o.Spec +} + +func (o *ShortURL) SetSpec(spec any) error { + cast, ok := spec.(ShortURLSpec) + if !ok { + return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec) + } + o.Spec = cast + return nil +} + +func (o *ShortURL) GetSubresources() map[string]any { + return map[string]any{ + "status": o.Status, + } +} + +func (o *ShortURL) GetSubresource(name string) (any, bool) { + switch name { + case "status": + return o.Status, true + default: + return nil, false + } +} + +func (o *ShortURL) SetSubresource(name string, value any) error { + switch name { + case "status": + cast, ok := value.(ShortURLStatus) + if !ok { + return fmt.Errorf("cannot set status type %#v, not of type ShortURLStatus", value) + } + o.Status = cast + return nil + default: + return fmt.Errorf("subresource '%s' does not exist", name) + } +} + +func (o *ShortURL) GetStaticMetadata() resource.StaticMetadata { + gvk := o.GroupVersionKind() + return resource.StaticMetadata{ + Name: o.ObjectMeta.Name, + Namespace: o.ObjectMeta.Namespace, + Group: gvk.Group, + Version: gvk.Version, + Kind: gvk.Kind, + } +} + +func (o *ShortURL) SetStaticMetadata(metadata resource.StaticMetadata) { + o.Name = metadata.Name + o.Namespace = metadata.Namespace + o.SetGroupVersionKind(schema.GroupVersionKind{ + Group: metadata.Group, + Version: metadata.Version, + Kind: metadata.Kind, + }) +} + +func (o *ShortURL) GetCommonMetadata() resource.CommonMetadata { + dt := o.DeletionTimestamp + var deletionTimestamp *time.Time + if dt != nil { + deletionTimestamp = &dt.Time + } + // Legacy ExtraFields support + extraFields := make(map[string]any) + if o.Annotations != nil { + extraFields["annotations"] = o.Annotations + } + if o.ManagedFields != nil { + extraFields["managedFields"] = o.ManagedFields + } + if o.OwnerReferences != nil { + extraFields["ownerReferences"] = o.OwnerReferences + } + return resource.CommonMetadata{ + UID: string(o.UID), + ResourceVersion: o.ResourceVersion, + Generation: o.Generation, + Labels: o.Labels, + CreationTimestamp: o.CreationTimestamp.Time, + DeletionTimestamp: deletionTimestamp, + Finalizers: o.Finalizers, + UpdateTimestamp: o.GetUpdateTimestamp(), + CreatedBy: o.GetCreatedBy(), + UpdatedBy: o.GetUpdatedBy(), + ExtraFields: extraFields, + } +} + +func (o *ShortURL) SetCommonMetadata(metadata resource.CommonMetadata) { + o.UID = types.UID(metadata.UID) + o.ResourceVersion = metadata.ResourceVersion + o.Generation = metadata.Generation + o.Labels = metadata.Labels + o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp) + if metadata.DeletionTimestamp != nil { + dt := metav1.NewTime(*metadata.DeletionTimestamp) + o.DeletionTimestamp = &dt + } else { + o.DeletionTimestamp = nil + } + o.Finalizers = metadata.Finalizers + if o.Annotations == nil { + o.Annotations = make(map[string]string) + } + if !metadata.UpdateTimestamp.IsZero() { + o.SetUpdateTimestamp(metadata.UpdateTimestamp) + } + if metadata.CreatedBy != "" { + o.SetCreatedBy(metadata.CreatedBy) + } + if metadata.UpdatedBy != "" { + o.SetUpdatedBy(metadata.UpdatedBy) + } + // Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields + if metadata.ExtraFields != nil { + if annotations, ok := metadata.ExtraFields["annotations"]; ok { + if cast, ok := annotations.(map[string]string); ok { + o.Annotations = cast + } + } + if managedFields, ok := metadata.ExtraFields["managedFields"]; ok { + if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok { + o.ManagedFields = cast + } + } + if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok { + if cast, ok := ownerReferences.([]metav1.OwnerReference); ok { + o.OwnerReferences = cast + } + } + } +} + +func (o *ShortURL) GetCreatedBy() string { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + return o.ObjectMeta.Annotations["grafana.com/createdBy"] +} + +func (o *ShortURL) SetCreatedBy(createdBy string) { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy +} + +func (o *ShortURL) GetUpdateTimestamp() time.Time { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"]) + return parsed +} + +func (o *ShortURL) SetUpdateTimestamp(updateTimestamp time.Time) { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339) +} + +func (o *ShortURL) GetUpdatedBy() string { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + return o.ObjectMeta.Annotations["grafana.com/updatedBy"] +} + +func (o *ShortURL) SetUpdatedBy(updatedBy string) { + if o.ObjectMeta.Annotations == nil { + o.ObjectMeta.Annotations = make(map[string]string) + } + + o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy +} + +func (o *ShortURL) Copy() resource.Object { + return resource.CopyObject(o) +} + +func (o *ShortURL) DeepCopyObject() runtime.Object { + return o.Copy() +} + +func (o *ShortURL) DeepCopy() *ShortURL { + cpy := &ShortURL{} + o.DeepCopyInto(cpy) + return cpy +} + +func (o *ShortURL) DeepCopyInto(dst *ShortURL) { + dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion + dst.TypeMeta.Kind = o.TypeMeta.Kind + o.ObjectMeta.DeepCopyInto(&dst.ObjectMeta) + o.Spec.DeepCopyInto(&dst.Spec) + o.Status.DeepCopyInto(&dst.Status) +} + +// Interface compliance compile-time check +var _ resource.Object = &ShortURL{} + +// +k8s:openapi-gen=true +type ShortURLList struct { + metav1.TypeMeta `json:",inline" yaml:",inline"` + metav1.ListMeta `json:"metadata" yaml:"metadata"` + Items []ShortURL `json:"items" yaml:"items"` +} + +func (o *ShortURLList) DeepCopyObject() runtime.Object { + return o.Copy() +} + +func (o *ShortURLList) Copy() resource.ListObject { + cpy := &ShortURLList{ + TypeMeta: o.TypeMeta, + Items: make([]ShortURL, len(o.Items)), + } + o.ListMeta.DeepCopyInto(&cpy.ListMeta) + for i := 0; i < len(o.Items); i++ { + if item, ok := o.Items[i].Copy().(*ShortURL); ok { + cpy.Items[i] = *item + } + } + return cpy +} + +func (o *ShortURLList) GetItems() []resource.Object { + items := make([]resource.Object, len(o.Items)) + for i := 0; i < len(o.Items); i++ { + items[i] = &o.Items[i] + } + return items +} + +func (o *ShortURLList) SetItems(items []resource.Object) { + o.Items = make([]ShortURL, len(items)) + for i := 0; i < len(items); i++ { + o.Items[i] = *items[i].(*ShortURL) + } +} + +func (o *ShortURLList) DeepCopy() *ShortURLList { + cpy := &ShortURLList{} + o.DeepCopyInto(cpy) + return cpy +} + +func (o *ShortURLList) DeepCopyInto(dst *ShortURLList) { + resource.CopyObjectInto(dst, o) +} + +// Interface compliance compile-time check +var _ resource.ListObject = &ShortURLList{} + +// Copy methods for all subresource types + +// DeepCopy creates a full deep copy of Spec +func (s *ShortURLSpec) DeepCopy() *ShortURLSpec { + cpy := &ShortURLSpec{} + s.DeepCopyInto(cpy) + return cpy +} + +// DeepCopyInto deep copies Spec into another Spec object +func (s *ShortURLSpec) DeepCopyInto(dst *ShortURLSpec) { + resource.CopyObjectInto(dst, s) +} + +// DeepCopy creates a full deep copy of ShortURLStatus +func (s *ShortURLStatus) DeepCopy() *ShortURLStatus { + cpy := &ShortURLStatus{} + s.DeepCopyInto(cpy) + return cpy +} + +// DeepCopyInto deep copies ShortURLStatus into another ShortURLStatus object +func (s *ShortURLStatus) DeepCopyInto(dst *ShortURLStatus) { + resource.CopyObjectInto(dst, s) +} diff --git a/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_schema_gen.go b/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_schema_gen.go new file mode 100644 index 00000000000..78f0d5839d2 --- /dev/null +++ b/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_schema_gen.go @@ -0,0 +1,34 @@ +// +// Code generated by grafana-app-sdk. DO NOT EDIT. +// + +package v1alpha1 + +import ( + "github.com/grafana/grafana-app-sdk/resource" +) + +// schema is unexported to prevent accidental overwrites +var ( + schemaShortURL = resource.NewSimpleSchema("shorturl.grafana.app", "v1alpha1", &ShortURL{}, &ShortURLList{}, resource.WithKind("ShortURL"), + resource.WithPlural("shorturls"), resource.WithScope(resource.NamespacedScope)) + kindShortURL = resource.Kind{ + Schema: schemaShortURL, + Codecs: map[resource.KindEncoding]resource.Codec{ + resource.KindEncodingJSON: &ShortURLJSONCodec{}, + }, + } +) + +// Kind returns a resource.Kind for this Schema with a JSON codec +func ShortURLKind() resource.Kind { + return kindShortURL +} + +// Schema returns a resource.SimpleSchema representation of ShortURL +func ShortURLSchema() *resource.SimpleSchema { + return schemaShortURL +} + +// Interface compliance checks +var _ resource.Schema = kindShortURL diff --git a/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_spec_gen.go b/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_spec_gen.go new file mode 100644 index 00000000000..56a453e5b69 --- /dev/null +++ b/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_spec_gen.go @@ -0,0 +1,14 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v1alpha1 + +// +k8s:openapi-gen=true +type ShortURLSpec struct { + // The original path to where the short url is linking too e.g. https://localhost:3000/eer8i1kictngga/new-dashboard-with-lib-panel + Path string `json:"path"` +} + +// NewShortURLSpec creates a new ShortURLSpec object. +func NewShortURLSpec() *ShortURLSpec { + return &ShortURLSpec{} +} diff --git a/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_status_gen.go b/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_status_gen.go new file mode 100644 index 00000000000..cfbeb15b338 --- /dev/null +++ b/apps/shorturl/pkg/apis/shorturl/v1alpha1/shorturl_status_gen.go @@ -0,0 +1,46 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +package v1alpha1 + +// +k8s:openapi-gen=true +type ShortURLstatusOperatorState struct { + // lastEvaluation is the ResourceVersion last evaluated + LastEvaluation string `json:"lastEvaluation"` + // state describes the state of the lastEvaluation. + // It is limited to three possible states for machine evaluation. + State ShortURLStatusOperatorStateState `json:"state"` + // descriptiveState is an optional more descriptive state field which has no requirements on format + DescriptiveState *string `json:"descriptiveState,omitempty"` + // details contains any extra information that is operator-specific + Details map[string]interface{} `json:"details,omitempty"` +} + +// NewShortURLstatusOperatorState creates a new ShortURLstatusOperatorState object. +func NewShortURLstatusOperatorState() *ShortURLstatusOperatorState { + return &ShortURLstatusOperatorState{} +} + +// +k8s:openapi-gen=true +type ShortURLStatus struct { + // The last time the short URL was used, 0 is the initial value + LastSeenAt int64 `json:"lastSeenAt"` + // operatorStates is a map of operator ID to operator state evaluations. + // Any operator which consumes this kind SHOULD add its state evaluation information to this field. + OperatorStates map[string]ShortURLstatusOperatorState `json:"operatorStates,omitempty"` + // additionalFields is reserved for future use + AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"` +} + +// NewShortURLStatus creates a new ShortURLStatus object. +func NewShortURLStatus() *ShortURLStatus { + return &ShortURLStatus{} +} + +// +k8s:openapi-gen=true +type ShortURLStatusOperatorStateState string + +const ( + ShortURLStatusOperatorStateStateSuccess ShortURLStatusOperatorStateState = "success" + ShortURLStatusOperatorStateStateInProgress ShortURLStatusOperatorStateState = "in_progress" + ShortURLStatusOperatorStateStateFailed ShortURLStatusOperatorStateState = "failed" +) diff --git a/apps/shorturl/pkg/apis/shorturl_manifest.go b/apps/shorturl/pkg/apis/shorturl_manifest.go new file mode 100644 index 00000000000..5cb4b1b2d07 --- /dev/null +++ b/apps/shorturl/pkg/apis/shorturl_manifest.go @@ -0,0 +1,75 @@ +// +// This file is generated by grafana-app-sdk +// DO NOT EDIT +// + +package apis + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/grafana/grafana-app-sdk/app" + "github.com/grafana/grafana-app-sdk/resource" + + v1alpha1 "github.com/grafana/grafana/apps/shorturl/pkg/apis/shorturl/v1alpha1" +) + +var ( + rawSchemaShortURLv1alpha1 = []byte(`{"spec":{"properties":{"path":{"description":"The original path to where the short url is linking too e.g. https://localhost:3000/eer8i1kictngga/new-dashboard-with-lib-panel","type":"string"}},"required":["path"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastSeenAt":{"description":"The last time the short URL was used, 0 is the initial value","format":"int64","type":"integer"},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"required":["lastSeenAt"],"type":"object"}}`) + versionSchemaShortURLv1alpha1 app.VersionSchema + _ = json.Unmarshal(rawSchemaShortURLv1alpha1, &versionSchemaShortURLv1alpha1) +) + +var appManifestData = app.ManifestData{ + AppName: "shorturl", + Group: "shorturl.grafana.app", + Versions: []app.ManifestVersion{ + { + Name: "v1alpha1", + Served: true, + Kinds: []app.ManifestVersionKind{ + { + Kind: "ShortURL", + Plural: "ShortURLs", + Scope: "Namespaced", + Conversion: false, + Schema: &versionSchemaShortURLv1alpha1, + }, + }, + }, + }, +} + +func LocalManifest() app.Manifest { + return app.NewEmbeddedManifest(appManifestData) +} + +func RemoteManifest() app.Manifest { + return app.NewAPIServerManifest("shorturl") +} + +var kindVersionToGoType = map[string]resource.Kind{ + "ShortURL/v1alpha1": v1alpha1.ShortURLKind(), +} + +// ManifestGoTypeAssociator returns the associated resource.Kind instance for a given Kind and Version, if one exists. +// If there is no association for the provided Kind and Version, exists will return false. +func ManifestGoTypeAssociator(kind, version string) (goType resource.Kind, exists bool) { + goType, exists = kindVersionToGoType[fmt.Sprintf("%s/%s", kind, version)] + return goType, exists +} + +var customRouteToGoResponseType = map[string]any{} + +// ManifestCustomRouteResponsesAssociator returns the associated response go type for a given kind, version, custom route path, and method, if one exists. +// kind may be empty for custom routes which are not kind subroutes. Leading slashes are removed from subroute paths. +// If there is no association for the provided kind, version, custom route path, and method, exists will return false. +func ManifestCustomRouteResponsesAssociator(kind, version, path, verb string) (goType any, exists bool) { + if len(path) > 0 && path[0] == '/' { + path = path[1:] + } + goType, exists = customRouteToGoResponseType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))] + return goType, exists +} diff --git a/apps/shorturl/pkg/app/app.go b/apps/shorturl/pkg/app/app.go new file mode 100644 index 00000000000..519ebd5f187 --- /dev/null +++ b/apps/shorturl/pkg/app/app.go @@ -0,0 +1,69 @@ +package app + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/klog/v2" + + "github.com/grafana/grafana-app-sdk/app" + "github.com/grafana/grafana-app-sdk/resource" + "github.com/grafana/grafana-app-sdk/simple" + shorturlv1alpha1 "github.com/grafana/grafana/apps/shorturl/pkg/apis/shorturl/v1alpha1" +) + +// Local error definitions to avoid importing the main shorturls package +var ( + ErrShortURLAbsolutePath = fmt.Errorf("path should be relative") + ErrShortURLInvalidPath = fmt.Errorf("invalid short URL path") +) + +type ShortURLConfig struct { + AppURL string +} + +func New(cfg app.Config) (app.App, error) { + // Extract the AppURL from the specific config + shortURLConfig, ok := cfg.SpecificConfig.(*ShortURLConfig) + if !ok || shortURLConfig == nil { + return nil, fmt.Errorf("invalid or missing ShortURLConfig") + } + + simpleConfig := simple.AppConfig{ + Name: "shorturl", + KubeConfig: cfg.KubeConfig, + InformerConfig: simple.AppInformerConfig{ + ErrorHandler: func(ctx context.Context, err error) { + klog.ErrorS(err, "Informer processing error") + }, + }, + ManagedKinds: []simple.AppManagedKind{ + { + Kind: shorturlv1alpha1.ShortURLKind(), + }, + }, + } + + a, err := simple.NewApp(simpleConfig) + if err != nil { + return nil, err + } + + err = a.ValidateManifest(cfg.ManifestData) + if err != nil { + return nil, err + } + + return a, nil +} + +func GetKinds() map[schema.GroupVersion][]resource.Kind { + gv := schema.GroupVersion{ + Group: shorturlv1alpha1.ShortURLKind().Group(), + Version: shorturlv1alpha1.ShortURLKind().Version(), + } + return map[schema.GroupVersion][]resource.Kind{ + gv: {shorturlv1alpha1.ShortURLKind()}, + } +} diff --git a/apps/shorturl/plugin/src/generated/shorturl/v1alpha1/shorturl_object_gen.ts b/apps/shorturl/plugin/src/generated/shorturl/v1alpha1/shorturl_object_gen.ts new file mode 100644 index 00000000000..3c4fe0bd088 --- /dev/null +++ b/apps/shorturl/plugin/src/generated/shorturl/v1alpha1/shorturl_object_gen.ts @@ -0,0 +1,49 @@ +/* + * This file was generated by grafana-app-sdk. DO NOT EDIT. + */ +import { Spec } from './types.spec.gen'; +import { Status } from './types.status.gen'; + +export interface Metadata { + name: string; + namespace: string; + generateName?: string; + selfLink?: string; + uid?: string; + resourceVersion?: string; + generation?: number; + creationTimestamp?: string; + deletionTimestamp?: string; + deletionGracePeriodSeconds?: number; + labels?: Record; + annotations?: Record; + ownerReferences?: OwnerReference[]; + finalizers?: string[]; + managedFields?: ManagedFieldsEntry[]; +} + +export interface OwnerReference { + apiVersion: string; + kind: string; + name: string; + uid: string; + controller?: boolean; + blockOwnerDeletion?: boolean; +} + +export interface ManagedFieldsEntry { + manager?: string; + operation?: string; + apiVersion?: string; + time?: string; + fieldsType?: string; + subresource?: string; +} + +export interface ShortURL { + kind: string; + apiVersion: string; + metadata: Metadata; + spec: Spec; + status: Status; +} diff --git a/apps/shorturl/plugin/src/generated/shorturl/v1alpha1/types.metadata.gen.ts b/apps/shorturl/plugin/src/generated/shorturl/v1alpha1/types.metadata.gen.ts new file mode 100644 index 00000000000..4377f3c1d08 --- /dev/null +++ b/apps/shorturl/plugin/src/generated/shorturl/v1alpha1/types.metadata.gen.ts @@ -0,0 +1,30 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +// metadata contains embedded CommonMetadata and can be extended with custom string fields +// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here +// without external reference as using the CommonMetadata reference breaks thema codegen. +export interface Metadata { + updateTimestamp: string; + createdBy: string; + uid: string; + creationTimestamp: string; + deletionTimestamp?: string; + finalizers: string[]; + resourceVersion: string; + generation: number; + updatedBy: string; + labels: Record; +} + +export const defaultMetadata = (): Metadata => ({ + updateTimestamp: "", + createdBy: "", + uid: "", + creationTimestamp: "", + finalizers: [], + resourceVersion: "", + generation: 0, + updatedBy: "", + labels: {}, +}); + diff --git a/apps/shorturl/plugin/src/generated/shorturl/v1alpha1/types.spec.gen.ts b/apps/shorturl/plugin/src/generated/shorturl/v1alpha1/types.spec.gen.ts new file mode 100644 index 00000000000..5c639fedf89 --- /dev/null +++ b/apps/shorturl/plugin/src/generated/shorturl/v1alpha1/types.spec.gen.ts @@ -0,0 +1,11 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +export interface Spec { + // The original path to where the short url is linking too e.g. https://localhost:3000/eer8i1kictngga/new-dashboard-with-lib-panel + path: string; +} + +export const defaultSpec = (): Spec => ({ + path: "", +}); + diff --git a/apps/shorturl/plugin/src/generated/shorturl/v1alpha1/types.status.gen.ts b/apps/shorturl/plugin/src/generated/shorturl/v1alpha1/types.status.gen.ts new file mode 100644 index 00000000000..c67940d5cab --- /dev/null +++ b/apps/shorturl/plugin/src/generated/shorturl/v1alpha1/types.status.gen.ts @@ -0,0 +1,33 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. + +export interface OperatorState { + // lastEvaluation is the ResourceVersion last evaluated + lastEvaluation: string; + // state describes the state of the lastEvaluation. + // It is limited to three possible states for machine evaluation. + state: "success" | "in_progress" | "failed"; + // descriptiveState is an optional more descriptive state field which has no requirements on format + descriptiveState?: string; + // details contains any extra information that is operator-specific + details?: Record; +} + +export const defaultOperatorState = (): OperatorState => ({ + lastEvaluation: "", + state: "success", +}); + +export interface Status { + // The last time the short URL was used, 0 is the initial value + lastSeenAt: number; + // operatorStates is a map of operator ID to operator state evaluations. + // Any operator which consumes this kind SHOULD add its state evaluation information to this field. + operatorStates?: Record; + // additionalFields is reserved for future use + additionalFields?: Record; +} + +export const defaultStatus = (): Status => ({ + lastSeenAt: 0, +}); + diff --git a/go.work b/go.work index a3bb9e88c39..51f59db084a 100644 --- a/go.work +++ b/go.work @@ -14,6 +14,7 @@ use ( ./apps/playlist ./apps/provisioning ./apps/secret + ./apps/shorturl ./pkg/aggregator ./pkg/apimachinery ./pkg/apiserver diff --git a/go.work.sum b/go.work.sum index d129bd22b1f..282086d51e6 100644 --- a/go.work.sum +++ b/go.work.sum @@ -920,7 +920,6 @@ github.com/google/go-pkcs11 v0.3.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMc 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/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= -github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= @@ -1206,10 +1205,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= -github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/zipkinexporter v0.124.1 h1:+aiMrDR6xiaDM7xN4ByrBYI0Craqt68nZicmpYpt0co= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/zipkinexporter v0.124.1/go.mod h1:H/TEWN4jgExt0McrtrBK2VFK6r9LRsWtqhEZrH690rs= github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.124.1 h1:NrjsoVPxI6lmV8jPImDcMeqYh+97Y71f/HB5Sfpfe3I= @@ -1741,6 +1738,7 @@ golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +golang.org/x/tools/go/expect v0.1.0-deprecated h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY= golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 68564d1ce0e..86faf2d7f04 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -286,6 +286,10 @@ export interface FeatureToggles { */ kubernetesDashboards?: boolean; /** + * Routes short url requests from /api to the /apis endpoint + */ + kubernetesShortURLs?: boolean; + /** * Disable schema validation for dashboards/v1 */ dashboardDisableSchemaValidationV1?: boolean; diff --git a/pkg/registry/apps/apps.go b/pkg/registry/apps/apps.go index fa7607102f8..62aec11ad97 100644 --- a/pkg/registry/apps/apps.go +++ b/pkg/registry/apps/apps.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana/pkg/registry/apps/alerting/notifications" "github.com/grafana/grafana/pkg/registry/apps/investigations" "github.com/grafana/grafana/pkg/registry/apps/playlist" + "github.com/grafana/grafana/pkg/registry/apps/shorturl" "github.com/grafana/grafana/pkg/services/apiserver" "github.com/grafana/grafana/pkg/services/apiserver/builder" "github.com/grafana/grafana/pkg/services/apiserver/builder/runner" @@ -24,9 +25,15 @@ import ( // ProvideAppInstallers returns a list of app installers that can be used to install apps. // This is the pattern that should be used to provide app installers in the app registry. func ProvideAppInstallers( + features featuremgmt.FeatureToggles, playlistAppInstaller *playlist.PlaylistAppInstaller, + shorturlAppInstaller *shorturl.ShortURLAppInstaller, ) []appsdkapiserver.AppInstaller { - return []appsdkapiserver.AppInstaller{playlistAppInstaller} + installers := []appsdkapiserver.AppInstaller{playlistAppInstaller} + if features.IsEnabledGlobally(featuremgmt.FlagKubernetesShortURLs) { + installers = append(installers, shorturlAppInstaller) + } + return installers } var ( diff --git a/pkg/registry/apps/shorturl/conversions.go b/pkg/registry/apps/shorturl/conversions.go new file mode 100644 index 00000000000..621f3618000 --- /dev/null +++ b/pkg/registry/apps/shorturl/conversions.go @@ -0,0 +1,34 @@ +package shorturl + +import ( + "fmt" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + shorturl "github.com/grafana/grafana/apps/shorturl/pkg/apis/shorturl/v1alpha1" + "github.com/grafana/grafana/pkg/services/apiserver/endpoints/request" + "github.com/grafana/grafana/pkg/services/shorturls" +) + +func convertToK8sResource(v *shorturls.ShortUrl, namespacer request.NamespaceMapper) *shorturl.ShortURL { + spec := shorturl.ShortURLSpec{ + Path: v.Path, + } + status := shorturl.ShortURLStatus{ + LastSeenAt: v.LastSeenAt, + } + p := &shorturl.ShortURL{ + ObjectMeta: metav1.ObjectMeta{ + Name: v.Uid, + UID: types.UID(v.Uid), + ResourceVersion: fmt.Sprintf("%d", v.LastSeenAt), + CreationTimestamp: metav1.NewTime(time.UnixMilli(v.CreatedAt)), + Namespace: namespacer(v.OrgId), + }, + Spec: spec, + Status: status, + } + return p +} diff --git a/pkg/registry/apps/shorturl/legacy_storage.go b/pkg/registry/apps/shorturl/legacy_storage.go new file mode 100644 index 00000000000..0b7948d62a5 --- /dev/null +++ b/pkg/registry/apps/shorturl/legacy_storage.go @@ -0,0 +1,145 @@ +package shorturl + +import ( + "context" + "errors" + "fmt" + "strings" + + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/apis/meta/internalversion" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apiserver/pkg/registry/rest" + + shorturl "github.com/grafana/grafana/apps/shorturl/pkg/apis/shorturl/v1alpha1" + "github.com/grafana/grafana/pkg/apimachinery/identity" + "github.com/grafana/grafana/pkg/services/apiserver/endpoints/request" + "github.com/grafana/grafana/pkg/services/authn" + "github.com/grafana/grafana/pkg/services/shorturls" + "github.com/grafana/grafana/pkg/services/user" +) + +var ( + _ rest.Scoper = (*legacyStorage)(nil) + _ rest.SingularNameProvider = (*legacyStorage)(nil) + _ rest.Getter = (*legacyStorage)(nil) + _ rest.Storage = (*legacyStorage)(nil) + _ rest.Creater = (*legacyStorage)(nil) + _ rest.Updater = (*legacyStorage)(nil) + _ rest.GracefulDeleter = (*legacyStorage)(nil) +) + +type legacyStorage struct { + service shorturls.Service + namespacer request.NamespaceMapper + tableConverter rest.TableConvertor +} + +func (s *legacyStorage) New() runtime.Object { + return shorturl.ShortURLKind().ZeroValue() +} + +func (s *legacyStorage) Destroy() {} + +func (s *legacyStorage) NamespaceScoped() bool { + return true // namespace == org +} + +func (s *legacyStorage) GetSingularName() string { + return strings.ToLower(shorturl.ShortURLKind().Kind()) +} + +func (s *legacyStorage) NewList() runtime.Object { + return shorturl.ShortURLKind().ZeroListValue() +} + +func (s *legacyStorage) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { + return s.tableConverter.ConvertToTable(ctx, object, tableOptions) +} + +func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) { + return nil, fmt.Errorf("List for shorturl not implemented") +} + +func (s *legacyStorage) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { + requester, err := identity.GetRequester(ctx) + if err != nil { + return nil, err + } + + // Convert identity.Requester to *user.SignedInUser + var signedInUser *user.SignedInUser + if authnIdentity, ok := requester.(*authn.Identity); ok { + signedInUser = authnIdentity.SignedInUser() + } else if userIdentity, ok := requester.(*user.SignedInUser); ok { + signedInUser = userIdentity + } else { + return nil, fmt.Errorf("unsupported identity type") + } + + dto, err := s.service.GetShortURLByUID(ctx, signedInUser, name) + if err != nil || dto == nil { + if errors.Is(err, shorturls.ErrShortURLNotFound) || err == nil { + err = k8serrors.NewNotFound(schema.GroupResource{ + Group: shorturl.ShortURLKind().Group(), + Resource: shorturl.ShortURLKind().Plural(), + }, name) + } + return nil, err + } + + return convertToK8sResource(dto, s.namespacer), nil +} + +func (s *legacyStorage) Create(ctx context.Context, + obj runtime.Object, + createValidation rest.ValidateObjectFunc, + options *metav1.CreateOptions, +) (runtime.Object, error) { + requester, err := identity.GetRequester(ctx) + if err != nil { + return nil, err + } + // Convert identity.Requester to *user.SignedInUser + var signedInUser *user.SignedInUser + if authnIdentity, ok := requester.(*authn.Identity); ok { + signedInUser = authnIdentity.SignedInUser() + } else if userIdentity, ok := requester.(*user.SignedInUser); ok { + signedInUser = userIdentity + } else { + return nil, fmt.Errorf("unsupported identity type") + } + + p, ok := obj.(*shorturl.ShortURL) + if !ok { + return nil, fmt.Errorf("expected shorturl?") + } + out, err := s.service.CreateShortURL(ctx, signedInUser, p.Spec.Path) + if err != nil { + return nil, err + } + return s.Get(ctx, out.Uid, nil) +} + +func (s *legacyStorage) Update(ctx context.Context, + name string, + objInfo rest.UpdatedObjectInfo, + createValidation rest.ValidateObjectFunc, + updateValidation rest.ValidateObjectUpdateFunc, + forceAllowCreate bool, + options *metav1.UpdateOptions, +) (runtime.Object, bool, error) { + return nil, false, fmt.Errorf("Update for shorturl not implemented") +} + +// GracefulDeleter +func (s *legacyStorage) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) { + return nil, false, fmt.Errorf("Delete for shorturl not implemented") +} + +// CollectionDeleter +func (s *legacyStorage) DeleteCollection(ctx context.Context, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions, listOptions *internalversion.ListOptions) (runtime.Object, error) { + return nil, fmt.Errorf("DeleteCollection for shorturl not implemented") +} diff --git a/pkg/registry/apps/shorturl/register.go b/pkg/registry/apps/shorturl/register.go new file mode 100644 index 00000000000..e280cd86a9e --- /dev/null +++ b/pkg/registry/apps/shorturl/register.go @@ -0,0 +1,97 @@ +package shorturl + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + restclient "k8s.io/client-go/rest" + + "github.com/grafana/grafana-app-sdk/app" + appsdkapiserver "github.com/grafana/grafana-app-sdk/k8s/apiserver" + "github.com/grafana/grafana-app-sdk/simple" + + "github.com/grafana/grafana/apps/shorturl/pkg/apis" + shorturl "github.com/grafana/grafana/apps/shorturl/pkg/apis/shorturl/v1alpha1" + shorturlapp "github.com/grafana/grafana/apps/shorturl/pkg/app" + "github.com/grafana/grafana/pkg/apimachinery/utils" + grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" + "github.com/grafana/grafana/pkg/services/apiserver/appinstaller" + "github.com/grafana/grafana/pkg/services/apiserver/endpoints/request" + "github.com/grafana/grafana/pkg/services/shorturls" + "github.com/grafana/grafana/pkg/setting" +) + +var ( + _ appsdkapiserver.AppInstaller = (*ShortURLAppInstaller)(nil) + _ appinstaller.LegacyStorageProvider = (*ShortURLAppInstaller)(nil) +) + +type ShortURLAppInstaller struct { + appsdkapiserver.AppInstaller + cfg *setting.Cfg + service shorturls.Service +} + +func RegisterAppInstaller( + cfg *setting.Cfg, + service shorturls.Service, +) (*ShortURLAppInstaller, error) { + installer := &ShortURLAppInstaller{ + cfg: cfg, + service: service, + } + specificConfig := any(&shorturlapp.ShortURLConfig{ + AppURL: cfg.AppURL, + }) + provider := simple.NewAppProvider(apis.LocalManifest(), specificConfig, shorturlapp.New) + + appCfg := app.Config{ + KubeConfig: restclient.Config{}, // this will be overridden by the installer's InitializeApp method + ManifestData: *apis.LocalManifest().ManifestData, + SpecificConfig: specificConfig, + } + i, err := appsdkapiserver.NewDefaultAppInstaller(provider, appCfg, apis.ManifestGoTypeAssociator, apis.ManifestCustomRouteResponsesAssociator) + if err != nil { + return nil, err + } + installer.AppInstaller = i + return installer, nil +} + +func (s *ShortURLAppInstaller) GetLegacyStorage(requested schema.GroupVersionResource) grafanarest.Storage { + gvr := schema.GroupVersionResource{ + Group: shorturl.ShortURLKind().Group(), + Version: shorturl.ShortURLKind().Version(), + Resource: shorturl.ShortURLKind().Plural(), + } + if requested.String() != gvr.String() { + return nil + } + legacyStore := &legacyStorage{ + service: s.service, + namespacer: request.GetNamespaceMapper(s.cfg), + } + legacyStore.tableConverter = utils.NewTableConverter( + gvr.GroupResource(), + utils.TableColumns{ + Definition: []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string", Format: "name"}, + {Name: "Path", Type: "string", Format: "string", Description: "The url path"}, + {Name: "Last Seen At", Type: "number"}, + }, + Reader: func(obj any) ([]interface{}, error) { + m, ok := obj.(*shorturl.ShortURL) + if !ok { + return nil, fmt.Errorf("expected shorturl") + } + return []interface{}{ + m.Name, + m.Spec.Path, + m.Status.LastSeenAt, + }, nil + }, + }, + ) + return legacyStore +} diff --git a/pkg/registry/apps/wireset.go b/pkg/registry/apps/wireset.go index 48212655418..b7ff8837665 100644 --- a/pkg/registry/apps/wireset.go +++ b/pkg/registry/apps/wireset.go @@ -7,6 +7,7 @@ import ( "github.com/grafana/grafana/pkg/registry/apps/alerting/notifications" "github.com/grafana/grafana/pkg/registry/apps/investigations" "github.com/grafana/grafana/pkg/registry/apps/playlist" + "github.com/grafana/grafana/pkg/registry/apps/shorturl" ) var WireSet = wire.NewSet( @@ -16,4 +17,5 @@ var WireSet = wire.NewSet( investigations.RegisterApp, advisor.RegisterApp, notifications.RegisterApp, + shorturl.RegisterAppInstaller, ) diff --git a/pkg/server/wire_gen.go b/pkg/server/wire_gen.go index cf76c869512..5448bd29d20 100644 --- a/pkg/server/wire_gen.go +++ b/pkg/server/wire_gen.go @@ -76,6 +76,7 @@ import ( notifications2 "github.com/grafana/grafana/pkg/registry/apps/alerting/notifications" "github.com/grafana/grafana/pkg/registry/apps/investigations" "github.com/grafana/grafana/pkg/registry/apps/playlist" + "github.com/grafana/grafana/pkg/registry/apps/shorturl" "github.com/grafana/grafana/pkg/registry/backgroundsvcs" "github.com/grafana/grafana/pkg/registry/usagestatssvcs" "github.com/grafana/grafana/pkg/services/accesscontrol" @@ -688,7 +689,11 @@ func Initialize(cfg *setting.Cfg, opts Options, apiOpts api.ServerOptions) (*Ser if err != nil { return nil, err } - v2 := appregistry.ProvideAppInstallers(playlistAppInstaller) + shortURLAppInstaller, err := shorturl.RegisterAppInstaller(cfg, shortURLService) + if err != nil { + return nil, err + } + v2 := appregistry.ProvideAppInstallers(featureToggles, playlistAppInstaller, shortURLAppInstaller) builderMetrics := builder.ProvideBuilderMetrics(registerer) apiserverService, err := apiserver.ProvideService(cfg, featureToggles, routeRegisterImpl, tracingService, serverLockService, sqlStore, kvStore, middlewareHandler, scopedPluginDatasourceProvider, plugincontextProvider, pluginstoreService, dualwriteService, resourceClient, eventualRestConfigProvider, v, eventualRestConfigProvider, registerer, aggregatorRunner, v2, builderMetrics) if err != nil { @@ -1249,7 +1254,11 @@ func InitializeForTest(t sqlutil.ITestDB, testingT interface { if err != nil { return nil, err } - v2 := appregistry.ProvideAppInstallers(playlistAppInstaller) + shortURLAppInstaller, err := shorturl.RegisterAppInstaller(cfg, shortURLService) + if err != nil { + return nil, err + } + v2 := appregistry.ProvideAppInstallers(featureToggles, playlistAppInstaller, shortURLAppInstaller) builderMetrics := builder.ProvideBuilderMetrics(registerer) apiserverService, err := apiserver.ProvideService(cfg, featureToggles, routeRegisterImpl, tracingService, serverLockService, sqlStore, kvStore, middlewareHandler, scopedPluginDatasourceProvider, plugincontextProvider, pluginstoreService, dualwriteService, resourceClient, eventualRestConfigProvider, v, eventualRestConfigProvider, registerer, aggregatorRunner, v2, builderMetrics) if err != nil { diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index 7b74ad685e8..ab2d9d14053 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -476,6 +476,13 @@ var ( Owner: grafanaAppPlatformSquad, FrontendOnly: true, }, + { + Name: "kubernetesShortURLs", + Description: "Routes short url requests from /api to the /apis endpoint", + Stage: FeatureStageExperimental, + Owner: grafanaAppPlatformSquad, + RequiresRestart: true, // changes the API routing + }, { Name: "dashboardDisableSchemaValidationV1", Description: "Disable schema validation for dashboards/v1", diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index 6e5c55cfd35..a0319c94bfb 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -61,6 +61,7 @@ formatString,GA,@grafana/dataviz-squad,false,false,true kubernetesSnapshots,experimental,@grafana/grafana-app-platform-squad,false,true,false kubernetesLibraryPanels,experimental,@grafana/grafana-app-platform-squad,false,true,false kubernetesDashboards,experimental,@grafana/grafana-app-platform-squad,false,false,true +kubernetesShortURLs,experimental,@grafana/grafana-app-platform-squad,false,true,false dashboardDisableSchemaValidationV1,experimental,@grafana/grafana-app-platform-squad,false,false,false dashboardDisableSchemaValidationV2,experimental,@grafana/grafana-app-platform-squad,false,false,false dashboardSchemaValidationLogging,experimental,@grafana/grafana-app-platform-squad,false,false,false diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index 0b00cf45ac1..c45b269451b 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -255,6 +255,10 @@ const ( // Use the kubernetes API in the frontend for dashboards FlagKubernetesDashboards = "kubernetesDashboards" + // FlagKubernetesShortURLs + // Routes short url requests from /api to the /apis endpoint + FlagKubernetesShortURLs = "kubernetesShortURLs" + // FlagDashboardDisableSchemaValidationV1 // Disable schema validation for dashboards/v1 FlagDashboardDisableSchemaValidationV1 = "dashboardDisableSchemaValidationV1" diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index e47603d79d4..503f8a657f6 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -1782,6 +1782,19 @@ "requiresRestart": true } }, + { + "metadata": { + "name": "kubernetesShortURLs", + "resourceVersion": "1753722806283", + "creationTimestamp": "2025-07-28T17:13:26Z" + }, + "spec": { + "description": "Routes short url requests from /api to the /apis endpoint", + "stage": "experimental", + "codeowner": "@grafana/grafana-app-platform-squad", + "requiresRestart": true + } + }, { "metadata": { "name": "kubernetesSnapshots", From 3b96a88aa2c575a851a67aff083ba13a75bf8734 Mon Sep 17 00:00:00 2001 From: Juan Cabanas Date: Mon, 4 Aug 2025 09:17:33 -0300 Subject: [PATCH 57/89] SortPicker: Disable SortPicker by prop (#109083) --- public/app/core/components/Select/SortPicker.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/public/app/core/components/Select/SortPicker.tsx b/public/app/core/components/Select/SortPicker.tsx index 4a0c635da2a..2b741cc1230 100644 --- a/public/app/core/components/Select/SortPicker.tsx +++ b/public/app/core/components/Select/SortPicker.tsx @@ -13,13 +13,14 @@ export interface Props { getSortOptions?: () => Promise; filter?: string[]; isClearable?: boolean; + disabled?: boolean; } const defaultSortOptionsGetter = (): Promise => { return getGrafanaSearcher().getSortOptions(); }; -export function SortPicker({ onChange, value, placeholder, filter, getSortOptions, isClearable }: Props) { +export function SortPicker({ onChange, value, placeholder, filter, getSortOptions, isClearable, disabled }: Props) { // Using sync Select and manual options fetching here since we need to find the selected option by value const options = useAsync<() => Promise>(async () => { const vals = await (getSortOptions ?? defaultSortOptionsGetter)(); @@ -45,6 +46,7 @@ export function SortPicker({ onChange, value, placeholder, filter, getSortOption placeholder={placeholder ?? `Sort (Default ${DEFAULT_SORT.label})`} prefix={} isClearable={isClearable} + disabled={disabled} /> ); } From 50ead8d4637e8424273d572c9141e772bb61c680 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 12:45:52 +0000 Subject: [PATCH 58/89] Update testing-library monorepo (#109121) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 4 +- packages/grafana-flamegraph/package.json | 2 +- .../grafana-o11y-ds-frontend/package.json | 2 +- packages/grafana-prometheus/package.json | 2 +- packages/grafana-runtime/package.json | 2 +- packages/grafana-sql/package.json | 2 +- packages/grafana-ui/package.json | 4 +- .../datasource/azuremonitor/package.json | 4 +- .../datasource/cloud-monitoring/package.json | 4 +- .../package.json | 2 +- .../grafana-pyroscope-datasource/package.json | 4 +- .../grafana-testdata-datasource/package.json | 4 +- .../plugins/datasource/jaeger/package.json | 4 +- .../app/plugins/datasource/loki/package.json | 4 +- .../app/plugins/datasource/mssql/package.json | 2 +- .../app/plugins/datasource/mysql/package.json | 2 +- .../app/plugins/datasource/parca/package.json | 2 +- .../app/plugins/datasource/tempo/package.json | 4 +- .../plugins/datasource/zipkin/package.json | 4 +- yarn.lock | 88 +++++++++++-------- 20 files changed, 81 insertions(+), 65 deletions(-) diff --git a/package.json b/package.json index e039d16d6a9..e759a80508d 100644 --- a/package.json +++ b/package.json @@ -107,8 +107,8 @@ "@stylistic/eslint-plugin-ts": "^4.0.0", "@swc/core": "1.13.3", "@swc/helpers": "0.5.17", - "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.6.3", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/babel__core": "^7", diff --git a/packages/grafana-flamegraph/package.json b/packages/grafana-flamegraph/package.json index c25abdd0104..7132e2cd4cb 100644 --- a/packages/grafana-flamegraph/package.json +++ b/packages/grafana-flamegraph/package.json @@ -61,7 +61,7 @@ "@babel/preset-react": "7.27.1", "@grafana/tsconfig": "^2.0.0", "@rollup/plugin-node-resolve": "16.0.1", - "@testing-library/dom": "10.4.0", + "@testing-library/dom": "10.4.1", "@testing-library/jest-dom": "^6.1.2", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", diff --git a/packages/grafana-o11y-ds-frontend/package.json b/packages/grafana-o11y-ds-frontend/package.json index e2fef5480c2..aee2372aa14 100644 --- a/packages/grafana-o11y-ds-frontend/package.json +++ b/packages/grafana-o11y-ds-frontend/package.json @@ -31,7 +31,7 @@ }, "devDependencies": { "@grafana/tsconfig": "^2.0.0", - "@testing-library/dom": "10.4.0", + "@testing-library/dom": "10.4.1", "@testing-library/jest-dom": "^6.1.2", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", diff --git a/packages/grafana-prometheus/package.json b/packages/grafana-prometheus/package.json index 8dc8f8a9a78..8736e3a0ef5 100644 --- a/packages/grafana-prometheus/package.json +++ b/packages/grafana-prometheus/package.json @@ -83,7 +83,7 @@ "@rollup/plugin-image": "3.0.3", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-node-resolve": "16.0.1", - "@testing-library/jest-dom": "6.6.3", + "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/jest": "29.5.14", diff --git a/packages/grafana-runtime/package.json b/packages/grafana-runtime/package.json index dfae8069cfe..f3506105902 100644 --- a/packages/grafana-runtime/package.json +++ b/packages/grafana-runtime/package.json @@ -70,7 +70,7 @@ "@grafana/tsconfig": "^2.0.0", "@rollup/plugin-node-resolve": "16.0.1", "@rollup/plugin-terser": "0.4.4", - "@testing-library/dom": "10.4.0", + "@testing-library/dom": "10.4.1", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/history": "4.7.11", diff --git a/packages/grafana-sql/package.json b/packages/grafana-sql/package.json index e045f423bd5..6b2ab84c1dc 100644 --- a/packages/grafana-sql/package.json +++ b/packages/grafana-sql/package.json @@ -37,7 +37,7 @@ }, "devDependencies": { "@grafana/tsconfig": "^2.0.0", - "@testing-library/dom": "10.4.0", + "@testing-library/dom": "10.4.1", "@testing-library/jest-dom": "^6.1.2", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index f04ad6287e1..78f53868ba8 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -155,8 +155,8 @@ "@storybook/react-webpack5": "^8.6.2", "@storybook/test-runner": "^0.23.0", "@storybook/theming": "^8.6.2", - "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.6.3", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/chance": "^1.1.7", diff --git a/public/app/plugins/datasource/azuremonitor/package.json b/public/app/plugins/datasource/azuremonitor/package.json index 7e171898989..090711a0ffb 100644 --- a/public/app/plugins/datasource/azuremonitor/package.json +++ b/public/app/plugins/datasource/azuremonitor/package.json @@ -28,8 +28,8 @@ "devDependencies": { "@grafana/e2e-selectors": "12.2.0-pre", "@grafana/plugin-configs": "12.2.0-pre", - "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.6.3", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/jest": "29.5.14", diff --git a/public/app/plugins/datasource/cloud-monitoring/package.json b/public/app/plugins/datasource/cloud-monitoring/package.json index 538804b9904..6d6c4879ee1 100644 --- a/public/app/plugins/datasource/cloud-monitoring/package.json +++ b/public/app/plugins/datasource/cloud-monitoring/package.json @@ -28,8 +28,8 @@ "devDependencies": { "@grafana/e2e-selectors": "12.2.0-pre", "@grafana/plugin-configs": "12.2.0-pre", - "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.6.3", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/debounce-promise": "3.1.9", diff --git a/public/app/plugins/datasource/grafana-postgresql-datasource/package.json b/public/app/plugins/datasource/grafana-postgresql-datasource/package.json index 8c50ca4f3ee..a6188574668 100644 --- a/public/app/plugins/datasource/grafana-postgresql-datasource/package.json +++ b/public/app/plugins/datasource/grafana-postgresql-datasource/package.json @@ -18,7 +18,7 @@ "devDependencies": { "@grafana/e2e-selectors": "12.2.0-pre", "@grafana/plugin-configs": "12.2.0-pre", - "@testing-library/dom": "10.4.0", + "@testing-library/dom": "10.4.1", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/jest": "29.5.14", diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json b/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json index 974cfaa729f..b97b9af0c3e 100644 --- a/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json +++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json @@ -21,8 +21,8 @@ }, "devDependencies": { "@grafana/plugin-configs": "12.2.0-pre", - "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.6.3", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/jest": "29.5.14", diff --git a/public/app/plugins/datasource/grafana-testdata-datasource/package.json b/public/app/plugins/datasource/grafana-testdata-datasource/package.json index 641fe7cea96..544457c4a16 100644 --- a/public/app/plugins/datasource/grafana-testdata-datasource/package.json +++ b/public/app/plugins/datasource/grafana-testdata-datasource/package.json @@ -23,8 +23,8 @@ "devDependencies": { "@grafana/e2e-selectors": "12.2.0-pre", "@grafana/plugin-configs": "12.2.0-pre", - "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.6.3", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/d3-random": "^3.0.2", diff --git a/public/app/plugins/datasource/jaeger/package.json b/public/app/plugins/datasource/jaeger/package.json index 052ccac2b5b..7832f9f3624 100644 --- a/public/app/plugins/datasource/jaeger/package.json +++ b/public/app/plugins/datasource/jaeger/package.json @@ -24,8 +24,8 @@ }, "devDependencies": { "@grafana/plugin-configs": "workspace:*", - "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.6.3", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/jest": "29.5.14", diff --git a/public/app/plugins/datasource/loki/package.json b/public/app/plugins/datasource/loki/package.json index d34f48d7c34..b98404726cd 100644 --- a/public/app/plugins/datasource/loki/package.json +++ b/public/app/plugins/datasource/loki/package.json @@ -26,8 +26,8 @@ "devDependencies": { "@grafana/e2e-selectors": "12.2.0-pre", "@grafana/plugin-configs": "12.2.0-pre", - "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.6.3", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/d3-random": "^3.0.2", diff --git a/public/app/plugins/datasource/mssql/package.json b/public/app/plugins/datasource/mssql/package.json index 8a2bfadaa02..82bdec4b732 100644 --- a/public/app/plugins/datasource/mssql/package.json +++ b/public/app/plugins/datasource/mssql/package.json @@ -19,7 +19,7 @@ "devDependencies": { "@grafana/e2e-selectors": "12.2.0-pre", "@grafana/plugin-configs": "12.2.0-pre", - "@testing-library/dom": "10.4.0", + "@testing-library/dom": "10.4.1", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/jest": "29.5.14", diff --git a/public/app/plugins/datasource/mysql/package.json b/public/app/plugins/datasource/mysql/package.json index 7e03ed499fb..5c3a9654e7d 100644 --- a/public/app/plugins/datasource/mysql/package.json +++ b/public/app/plugins/datasource/mysql/package.json @@ -18,7 +18,7 @@ "devDependencies": { "@grafana/e2e-selectors": "12.2.0-pre", "@grafana/plugin-configs": "12.2.0-pre", - "@testing-library/dom": "10.4.0", + "@testing-library/dom": "10.4.1", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/jest": "29.5.14", diff --git a/public/app/plugins/datasource/parca/package.json b/public/app/plugins/datasource/parca/package.json index d4785ed9846..3b08680a41a 100644 --- a/public/app/plugins/datasource/parca/package.json +++ b/public/app/plugins/datasource/parca/package.json @@ -19,7 +19,7 @@ }, "devDependencies": { "@grafana/plugin-configs": "12.2.0-pre", - "@testing-library/dom": "10.4.0", + "@testing-library/dom": "10.4.1", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/lodash": "4.17.20", diff --git a/public/app/plugins/datasource/tempo/package.json b/public/app/plugins/datasource/tempo/package.json index cc592a1f15f..f948e1044ef 100644 --- a/public/app/plugins/datasource/tempo/package.json +++ b/public/app/plugins/datasource/tempo/package.json @@ -39,8 +39,8 @@ }, "devDependencies": { "@grafana/plugin-configs": "12.2.0-pre", - "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.6.3", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@testing-library/user-event": "14.6.1", "@types/jest": "29.5.14", diff --git a/public/app/plugins/datasource/zipkin/package.json b/public/app/plugins/datasource/zipkin/package.json index fb9bbf0ef7b..7217e9c0ac0 100644 --- a/public/app/plugins/datasource/zipkin/package.json +++ b/public/app/plugins/datasource/zipkin/package.json @@ -21,8 +21,8 @@ }, "devDependencies": { "@grafana/plugin-configs": "workspace:*", - "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.6.3", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.6.4", "@testing-library/react": "16.3.0", "@types/jest": "29.5.14", "@types/lodash": "4.17.20", diff --git a/yarn.lock b/yarn.lock index d2a1dec4500..d5176ffa5ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2545,8 +2545,8 @@ __metadata: "@grafana/schema": "npm:12.2.0-pre" "@grafana/ui": "npm:12.2.0-pre" "@kusto/monaco-kusto": "npm:^10.0.0" - "@testing-library/dom": "npm:10.4.0" - "@testing-library/jest-dom": "npm:6.6.3" + "@testing-library/dom": "npm:10.4.1" + "@testing-library/jest-dom": "npm:6.6.4" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/jest": "npm:29.5.14" @@ -2590,7 +2590,7 @@ __metadata: "@grafana/runtime": "npm:12.2.0-pre" "@grafana/sql": "npm:12.2.0-pre" "@grafana/ui": "npm:12.2.0-pre" - "@testing-library/dom": "npm:10.4.0" + "@testing-library/dom": "npm:10.4.1" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/jest": "npm:29.5.14" @@ -2620,8 +2620,8 @@ __metadata: "@grafana/runtime": "npm:12.2.0-pre" "@grafana/schema": "npm:12.2.0-pre" "@grafana/ui": "npm:12.2.0-pre" - "@testing-library/dom": "npm:10.4.0" - "@testing-library/jest-dom": "npm:6.6.3" + "@testing-library/dom": "npm:10.4.1" + "@testing-library/jest-dom": "npm:6.6.4" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/jest": "npm:29.5.14" @@ -2661,8 +2661,8 @@ __metadata: "@grafana/runtime": "npm:12.2.0-pre" "@grafana/schema": "npm:12.2.0-pre" "@grafana/ui": "npm:12.2.0-pre" - "@testing-library/dom": "npm:10.4.0" - "@testing-library/jest-dom": "npm:6.6.3" + "@testing-library/dom": "npm:10.4.1" + "@testing-library/jest-dom": "npm:6.6.4" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/d3-random": "npm:^3.0.2" @@ -2703,8 +2703,8 @@ __metadata: "@grafana/plugin-ui": "npm:0.10.7" "@grafana/runtime": "workspace:*" "@grafana/ui": "workspace:*" - "@testing-library/dom": "npm:10.4.0" - "@testing-library/jest-dom": "npm:6.6.3" + "@testing-library/dom": "npm:10.4.1" + "@testing-library/jest-dom": "npm:6.6.4" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/jest": "npm:29.5.14" @@ -2748,8 +2748,8 @@ __metadata: "@grafana/runtime": "npm:12.2.0-pre" "@grafana/schema": "npm:12.2.0-pre" "@grafana/ui": "npm:12.2.0-pre" - "@testing-library/dom": "npm:10.4.0" - "@testing-library/jest-dom": "npm:6.6.3" + "@testing-library/dom": "npm:10.4.1" + "@testing-library/jest-dom": "npm:6.6.4" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/d3-random": "npm:^3.0.2" @@ -2791,7 +2791,7 @@ __metadata: "@grafana/runtime": "npm:12.2.0-pre" "@grafana/sql": "npm:12.2.0-pre" "@grafana/ui": "npm:12.2.0-pre" - "@testing-library/dom": "npm:10.4.0" + "@testing-library/dom": "npm:10.4.1" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/jest": "npm:29.5.14" @@ -2823,7 +2823,7 @@ __metadata: "@grafana/runtime": "npm:12.2.0-pre" "@grafana/sql": "npm:12.2.0-pre" "@grafana/ui": "npm:12.2.0-pre" - "@testing-library/dom": "npm:10.4.0" + "@testing-library/dom": "npm:10.4.1" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/jest": "npm:29.5.14" @@ -2853,7 +2853,7 @@ __metadata: "@grafana/runtime": "npm:12.2.0-pre" "@grafana/schema": "npm:12.2.0-pre" "@grafana/ui": "npm:12.2.0-pre" - "@testing-library/dom": "npm:10.4.0" + "@testing-library/dom": "npm:10.4.1" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/lodash": "npm:4.17.20" @@ -2889,8 +2889,8 @@ __metadata: "@grafana/runtime": "npm:12.2.0-pre" "@grafana/schema": "npm:12.2.0-pre" "@grafana/ui": "npm:12.2.0-pre" - "@testing-library/dom": "npm:10.4.0" - "@testing-library/jest-dom": "npm:6.6.3" + "@testing-library/dom": "npm:10.4.1" + "@testing-library/jest-dom": "npm:6.6.4" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/debounce-promise": "npm:3.1.9" @@ -2943,8 +2943,8 @@ __metadata: "@opentelemetry/api": "npm:1.9.0" "@opentelemetry/exporter-collector": "npm:0.25.0" "@opentelemetry/semantic-conventions": "npm:1.36.0" - "@testing-library/dom": "npm:10.4.0" - "@testing-library/jest-dom": "npm:6.6.3" + "@testing-library/dom": "npm:10.4.1" + "@testing-library/jest-dom": "npm:6.6.4" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/jest": "npm:29.5.14" @@ -2995,8 +2995,8 @@ __metadata: "@grafana/plugin-ui": "npm:0.10.7" "@grafana/runtime": "workspace:*" "@grafana/ui": "workspace:*" - "@testing-library/dom": "npm:10.4.0" - "@testing-library/jest-dom": "npm:6.6.3" + "@testing-library/dom": "npm:10.4.1" + "@testing-library/jest-dom": "npm:6.6.4" "@testing-library/react": "npm:16.3.0" "@types/jest": "npm:29.5.14" "@types/lodash": "npm:4.17.20" @@ -3258,7 +3258,7 @@ __metadata: "@grafana/ui": "npm:12.2.0-pre" "@leeoniya/ufuzzy": "npm:1.0.18" "@rollup/plugin-node-resolve": "npm:16.0.1" - "@testing-library/dom": "npm:10.4.0" + "@testing-library/dom": "npm:10.4.1" "@testing-library/jest-dom": "npm:^6.1.2" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" @@ -3382,7 +3382,7 @@ __metadata: "@grafana/schema": "npm:12.2.0-pre" "@grafana/tsconfig": "npm:^2.0.0" "@grafana/ui": "npm:12.2.0-pre" - "@testing-library/dom": "npm:10.4.0" + "@testing-library/dom": "npm:10.4.1" "@testing-library/jest-dom": "npm:^6.1.2" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" @@ -3501,7 +3501,7 @@ __metadata: "@rollup/plugin-image": "npm:3.0.3" "@rollup/plugin-json": "npm:6.1.0" "@rollup/plugin-node-resolve": "npm:16.0.1" - "@testing-library/jest-dom": "npm:6.6.3" + "@testing-library/jest-dom": "npm:6.6.4" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/debounce-promise": "npm:3.1.9" @@ -3560,7 +3560,7 @@ __metadata: "@grafana/ui": "npm:12.2.0-pre" "@rollup/plugin-node-resolve": "npm:16.0.1" "@rollup/plugin-terser": "npm:0.4.4" - "@testing-library/dom": "npm:10.4.0" + "@testing-library/dom": "npm:10.4.1" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/history": "npm:4.7.11" @@ -3666,7 +3666,7 @@ __metadata: "@grafana/tsconfig": "npm:^2.0.0" "@grafana/ui": "npm:12.2.0-pre" "@react-awesome-query-builder/ui": "npm:6.6.15" - "@testing-library/dom": "npm:10.4.0" + "@testing-library/dom": "npm:10.4.1" "@testing-library/jest-dom": "npm:^6.1.2" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" @@ -3763,8 +3763,8 @@ __metadata: "@storybook/test-runner": "npm:^0.23.0" "@storybook/theming": "npm:^8.6.2" "@tanstack/react-virtual": "npm:^3.5.1" - "@testing-library/dom": "npm:10.4.0" - "@testing-library/jest-dom": "npm:6.6.3" + "@testing-library/dom": "npm:10.4.1" + "@testing-library/jest-dom": "npm:6.6.4" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/chance": "npm:^1.1.7" @@ -8725,7 +8725,7 @@ __metadata: languageName: unknown linkType: soft -"@testing-library/dom@npm:10.4.0, @testing-library/dom@npm:>=7": +"@testing-library/dom@npm:10.4.0": version: 10.4.0 resolution: "@testing-library/dom@npm:10.4.0" dependencies: @@ -8741,6 +8741,22 @@ __metadata: languageName: node linkType: hard +"@testing-library/dom@npm:10.4.1, @testing-library/dom@npm:>=7": + version: 10.4.1 + resolution: "@testing-library/dom@npm:10.4.1" + dependencies: + "@babel/code-frame": "npm:^7.10.4" + "@babel/runtime": "npm:^7.12.5" + "@types/aria-query": "npm:^5.0.1" + aria-query: "npm:5.3.0" + dom-accessibility-api: "npm:^0.5.9" + lz-string: "npm:^1.5.0" + picocolors: "npm:1.1.1" + pretty-format: "npm:^27.0.2" + checksum: 10/7f93e09ea015f151f8b8f42cbab0b2b858999b5445f15239a72a612ef7716e672b14c40c421218194cf191cbecbde0afa6f3dc2cc83dda93ff6a4fb0237df6e6 + languageName: node + linkType: hard + "@testing-library/jest-dom@npm:6.5.0": version: 6.5.0 resolution: "@testing-library/jest-dom@npm:6.5.0" @@ -8756,18 +8772,18 @@ __metadata: languageName: node linkType: hard -"@testing-library/jest-dom@npm:6.6.3, @testing-library/jest-dom@npm:^6.1.2, @testing-library/jest-dom@npm:^6.6.3": - version: 6.6.3 - resolution: "@testing-library/jest-dom@npm:6.6.3" +"@testing-library/jest-dom@npm:6.6.4, @testing-library/jest-dom@npm:^6.1.2, @testing-library/jest-dom@npm:^6.6.3": + version: 6.6.4 + resolution: "@testing-library/jest-dom@npm:6.6.4" dependencies: "@adobe/css-tools": "npm:^4.4.0" aria-query: "npm:^5.0.0" - chalk: "npm:^3.0.0" css.escape: "npm:^1.5.1" dom-accessibility-api: "npm:^0.6.3" lodash: "npm:^4.17.21" + picocolors: "npm:^1.1.1" redent: "npm:^3.0.0" - checksum: 10/1f3427e45870eab9dcc59d6504b780d4a595062fe1687762ae6e67d06a70bf439b40ab64cf58cbace6293a99e3764d4647fdc8300a633b721764f5ce39dade18 + checksum: 10/5e67112c789f884fb75b279c2cddfdd0995a012a7847a03c474e4134f0d213934ee70c97433bca26b45e3a5ffa56faafe6499c8e57841179c4f2bd80eef429cd languageName: node linkType: hard @@ -18254,8 +18270,8 @@ __metadata: "@stylistic/eslint-plugin-ts": "npm:^4.0.0" "@swc/core": "npm:1.13.3" "@swc/helpers": "npm:0.5.17" - "@testing-library/dom": "npm:10.4.0" - "@testing-library/jest-dom": "npm:6.6.3" + "@testing-library/dom": "npm:10.4.1" + "@testing-library/jest-dom": "npm:6.6.4" "@testing-library/react": "npm:16.3.0" "@testing-library/user-event": "npm:14.6.1" "@types/babel__core": "npm:^7" @@ -25295,7 +25311,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": +"picocolors@npm:1.1.1, picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: 10/e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 From 0dfcaf56d356cacc65f75c5d0475fc835a18c51e Mon Sep 17 00:00:00 2001 From: Kristina Date: Mon, 4 Aug 2025 07:53:26 -0500 Subject: [PATCH 59/89] Transformations: Add empty values options to Transpose (#108421) * Extract functions to util and utilize in both transforms * Fix mistaken label and add better null logic to transpose * Add a new row and add a blurb to docs about the new setting * Update public/app/features/transformers/docs/content.ts Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com> * Update docs content, simplify null logic * Add test, clarify empty logic --------- Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com> --- .../transform-data/index.md | 2 +- .../transformers/groupingToMatrix.ts | 17 +------ .../transformers/transpose.test.ts | 44 +++++++++++++++++ .../transformations/transformers/transpose.ts | 17 ++++--- .../src/transformations/transformers/utils.ts | 17 +++++++ .../app/features/transformers/docs/content.ts | 2 +- .../GroupingToMatrixTransformerEditor.tsx | 47 +------------------ .../editors/TransposeTransformerEditor.tsx | 17 ++++++- public/app/features/transformers/utils.ts | 31 ++++++++++++ public/locales/en-US/grafana.json | 32 ++++++------- 10 files changed, 139 insertions(+), 87 deletions(-) diff --git a/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md b/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md index ba94fe38671..bb8de19264f 100644 --- a/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md +++ b/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md @@ -1465,7 +1465,7 @@ For each generated **Trend** field value, a calculation function can be selected ### Transpose Use this transformation to pivot the data frame, converting rows into columns and columns into rows. This transformation is particularly useful when you want to switch the orientation of your data to better suit your visualization needs. -If you have multiple types it will default to string type. +If you have multiple types, it will default to string type. You can select how empty cells should be represented. **Before Transformation:** diff --git a/packages/grafana-data/src/transformations/transformers/groupingToMatrix.ts b/packages/grafana-data/src/transformations/transformers/groupingToMatrix.ts index 3415590d64b..e9d33f33587 100644 --- a/packages/grafana-data/src/transformations/transformers/groupingToMatrix.ts +++ b/packages/grafana-data/src/transformations/transformers/groupingToMatrix.ts @@ -12,6 +12,7 @@ import { fieldMatchers } from '../matchers'; import { FieldMatcherID } from '../matchers/ids'; import { DataTransformerID } from './ids'; +import { getSpecialValue } from './utils'; export interface GroupingToMatrixTransformerOptions { columnField?: string; @@ -172,19 +173,3 @@ function findKeyField(frame: DataFrame, matchTitle: string): Field | null { return null; } - -function getSpecialValue(specialValue: SpecialValue) { - switch (specialValue) { - case SpecialValue.False: - return false; - case SpecialValue.True: - return true; - case SpecialValue.Null: - return null; - case SpecialValue.Zero: - return 0; - case SpecialValue.Empty: - default: - return ''; - } -} diff --git a/packages/grafana-data/src/transformations/transformers/transpose.test.ts b/packages/grafana-data/src/transformations/transformers/transpose.test.ts index c14026a8920..73db0fb11c9 100644 --- a/packages/grafana-data/src/transformations/transformers/transpose.test.ts +++ b/packages/grafana-data/src/transformations/transformers/transpose.test.ts @@ -2,6 +2,7 @@ import { DataTransformerConfig } from '@grafana/schema'; import { toDataFrame } from '../../dataframe/processDataFrame'; import { FieldType } from '../../types/dataFrame'; +import { SpecialValue } from '../../types/transformations'; import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; import { transformDataFrame } from '../transformDataFrame'; @@ -246,4 +247,47 @@ describe('Transpose transformer', () => { ]); }); }); + + it('should fill in empty values with the indicated option', async () => { + const cfgC: DataTransformerConfig = { + id: DataTransformerID.transpose, + options: { + emptyValue: SpecialValue.Zero, + }, + }; + const seriesC = toDataFrame({ + name: 'C', + fields: [ + { name: 'A', type: FieldType.string, values: ['apple', undefined] }, + { name: 'B', type: FieldType.string, values: [undefined, 'orange'] }, + { name: 'C', type: FieldType.string, values: ['banana', undefined] }, + { name: 'D', type: FieldType.string, values: ['strawberry', 'pear'] }, + ], + }); + await expect(transformDataFrame([cfgC], [seriesC])).toEmitValuesWith((received) => { + const result = received[0]; + expect(result[0].fields).toEqual([ + { + name: 'Field', + type: FieldType.string, + values: ['B', 'C', 'D'], + config: {}, + }, + { + name: 'Value', + labels: { A: 'apple' }, + type: FieldType.string, + values: [0, 'banana', 'strawberry'], + config: {}, + }, + { + name: 'Value', + labels: { A: 0 }, + type: FieldType.string, + values: ['orange', 0, 'pear'], + config: {}, + }, + ]); + }); + }); }); diff --git a/packages/grafana-data/src/transformations/transformers/transpose.ts b/packages/grafana-data/src/transformations/transformers/transpose.ts index 651254a736d..aff84099192 100644 --- a/packages/grafana-data/src/transformations/transformers/transpose.ts +++ b/packages/grafana-data/src/transformations/transformers/transpose.ts @@ -2,13 +2,15 @@ import { map } from 'rxjs/operators'; import { cacheFieldDisplayNames } from '../../field/fieldState'; import { DataFrame, Field, FieldType } from '../../types/dataFrame'; -import { DataTransformerInfo } from '../../types/transformations'; +import { DataTransformerInfo, SpecialValue } from '../../types/transformations'; import { DataTransformerID } from './ids'; +import { getSpecialValue } from './utils'; export interface TransposeTransformerOptions { firstFieldName?: string; restFieldsName?: string; + emptyValue?: SpecialValue; } export const transposeTransformer: DataTransformerInfo = { @@ -30,6 +32,7 @@ export const transposeTransformer: DataTransformerInfo { const firstField = frame.fields[0]; @@ -38,7 +41,7 @@ function transposeDataFrame(options: TransposeTransformerOptions, data: DataFram const useFirstFieldAsHeaders = firstField.type === FieldType.string || firstField.type === FieldType.time || firstField.type === FieldType.enum; const headers = useFirstFieldAsHeaders - ? [firstName, ...fieldValuesAsStrings(firstField, firstField.values)] + ? [firstName, ...fieldValuesAsStrings(firstField, firstField.values, emptyValue)] : [firstName, ...firstField.values.map((_, i) => restName)]; const rows = useFirstFieldAsHeaders ? frame.fields @@ -65,7 +68,7 @@ function transposeDataFrame(options: TransposeTransformerOptions, data: DataFram const values = frame.fields.map((field) => { if (fieldType === FieldType.string) { - return fieldValuesAsStrings(field, [field.values[index - 1]])[0]; + return fieldValuesAsStrings(field, [field.values[index - 1]], emptyValue)[0]; } return field.values[index - 1]; }); @@ -97,17 +100,17 @@ function determineFieldType(fieldTypes: FieldType[]): FieldType { return uniqueFieldTypes.size === 1 ? [...uniqueFieldTypes][0] : FieldType.string; } -function fieldValuesAsStrings(field: Field, values: unknown[]) { +function fieldValuesAsStrings(field: Field, values: unknown[], emptyValue: SpecialValue) { switch (field.type) { case FieldType.time: case FieldType.number: case FieldType.boolean: case FieldType.string: - return values.map((v) => `${v}`); + return values.map((v) => (v != null ? `${v}` : getSpecialValue(emptyValue))); case FieldType.enum: // @ts-ignore - return values.map((v) => field.config.type!.enum!.text![v]); + return values.map((v) => field.config.type!.enum!.text![v] ?? getSpecialValue(emptyValue)); default: - return values.map((v) => JSON.stringify(v)); + return values.map((v) => (v != null ? JSON.stringify(v) : getSpecialValue(emptyValue))); } } diff --git a/packages/grafana-data/src/transformations/transformers/utils.ts b/packages/grafana-data/src/transformations/transformers/utils.ts index c10b1e8a1d7..29ac89b29ee 100644 --- a/packages/grafana-data/src/transformations/transformers/utils.ts +++ b/packages/grafana-data/src/transformations/transformers/utils.ts @@ -1,5 +1,6 @@ import { BootData } from '../../types/config'; import { DataFrame } from '../../types/dataFrame'; +import { SpecialValue } from '../../types/transformations'; declare global { interface Window { @@ -22,3 +23,19 @@ export function findMaxFields(data: DataFrame[]) { return maxFields; } + +export function getSpecialValue(specialValue: SpecialValue) { + switch (specialValue) { + case SpecialValue.False: + return false; + case SpecialValue.True: + return true; + case SpecialValue.Null: + return null; + case SpecialValue.Zero: + return 0; + case SpecialValue.Empty: + default: + return ''; + } +} diff --git a/public/app/features/transformers/docs/content.ts b/public/app/features/transformers/docs/content.ts index 5f7d8e14703..273cbe22c94 100644 --- a/public/app/features/transformers/docs/content.ts +++ b/public/app/features/transformers/docs/content.ts @@ -1559,7 +1559,7 @@ ${buildImageContent( getHelperDocs: function (imageRenderType: ImageRenderType = ImageRenderType.ShortcodeFigure) { return ` Use this transformation to pivot the data frame, converting rows into columns and columns into rows. This transformation is particularly useful when you want to switch the orientation of your data to better suit your visualization needs. -If you have multiple types it will default to string type. +If you have multiple types, it will default to string type. You can select how empty cells should be represented. **Before Transformation:** diff --git a/public/app/features/transformers/editors/GroupingToMatrixTransformerEditor.tsx b/public/app/features/transformers/editors/GroupingToMatrixTransformerEditor.tsx index 6eb793e082a..dd8416c64b3 100644 --- a/public/app/features/transformers/editors/GroupingToMatrixTransformerEditor.tsx +++ b/public/app/features/transformers/editors/GroupingToMatrixTransformerEditor.tsx @@ -17,7 +17,7 @@ import { InlineField, InlineFieldRow, Select } from '@grafana/ui'; import { getTransformationContent } from '../docs/getTransformationContent'; import darkImage from '../images/dark/groupingToMatrix.svg'; import lightImage from '../images/light/groupingToMatrix.svg'; -import { useAllFieldNamesFromDataFrames } from '../utils'; +import { getEmptyOptions, useAllFieldNamesFromDataFrames } from '../utils'; export const GroupingToMatrixTransformerEditor = ({ input, @@ -61,49 +61,6 @@ export const GroupingToMatrixTransformerEditor = ({ [onChange, options] ); - const specialValueOptions: Array> = [ - { - label: t('transformers.grouping-to-matrix-transformer-editor.special-value-options.label.null', 'Null'), - value: SpecialValue.Null, - description: t( - 'transformers.grouping-to-matrix-transformer-editor.special-value-options.description.null-value', - 'Null value' - ), - }, - { - label: t('transformers.grouping-to-matrix-transformer-editor.special-value-options.label.true', 'True'), - value: SpecialValue.True, - description: t( - 'transformers.grouping-to-matrix-transformer-editor.special-value-options.description.boolean-true-value', - 'Boolean true value' - ), - }, - { - label: t('transformers.grouping-to-matrix-transformer-editor.special-value-options.label.false', 'False'), - value: SpecialValue.False, - description: t( - 'transformers.grouping-to-matrix-transformer-editor.special-value-options.description.boolean-false-value', - 'Boolean false value' - ), - }, - { - label: t('transformers.grouping-to-matrix-transformer-editor.special-value-options.label.zero', 'Zero'), - value: SpecialValue.Zero, - description: t( - 'transformers.grouping-to-matrix-transformer-editor.special-value-options.description.number-value', - 'Number 0 value' - ), - }, - { - label: t('transformers.grouping-to-matrix-transformer-editor.special-value-options.label.empty', 'Empty'), - value: SpecialValue.Empty, - description: t( - 'transformers.grouping-to-matrix-transformer-editor.special-value-options.description.empty-string', - 'Empty string' - ), - }, - ]; - const onSelectEmptyValue = useCallback( (value: SelectableValue) => { onChange({ @@ -143,7 +100,7 @@ export const GroupingToMatrixTransformerEditor = ({ /> - diff --git a/public/app/features/transformers/editors/TransposeTransformerEditor.tsx b/public/app/features/transformers/editors/TransposeTransformerEditor.tsx index baeee2461e5..fda90c7ee64 100644 --- a/public/app/features/transformers/editors/TransposeTransformerEditor.tsx +++ b/public/app/features/transformers/editors/TransposeTransformerEditor.tsx @@ -4,15 +4,25 @@ import { TransformerRegistryItem, TransformerUIProps, TransformerCategory, + SpecialValue, + SelectableValue, } from '@grafana/data'; import { TransposeTransformerOptions } from '@grafana/data/internal'; import { t } from '@grafana/i18n'; -import { InlineField, InlineFieldRow, Input } from '@grafana/ui'; +import { InlineField, InlineFieldRow, Input, Select } from '@grafana/ui'; import darkImage from '../images/dark/transpose.svg'; import lightImage from '../images/light/transpose.svg'; +import { getEmptyOptions } from '../utils'; export const TransposeTransformerEditor = ({ options, onChange }: TransformerUIProps) => { + const onSelectEmptyValue = (value?: SelectableValue) => { + onChange({ + ...options, + emptyValue: value?.value, + }); + }; + return ( <> @@ -42,6 +52,11 @@ export const TransposeTransformerEditor = ({ options, onChange }: TransformerUIP /> + + +