mirror of
https://github.com/grafana/grafana.git
synced 2025-12-20 19:44:55 +08:00
Compare commits
19 Commits
docs/add-a
...
eshields/s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f685893b8 | ||
|
|
2bf5047d37 | ||
|
|
0ac54b2d09 | ||
|
|
3b14940c7f | ||
|
|
2779905296 | ||
|
|
b2f8e1b4d1 | ||
|
|
fde846d8e5 | ||
|
|
43c43c98de | ||
|
|
e568a5859b | ||
|
|
ebc6980a57 | ||
|
|
0969179918 | ||
|
|
2eb3898c71 | ||
|
|
3bf27d926e | ||
|
|
862998a9cb | ||
|
|
4b34d8d8a0 | ||
|
|
e3ff80a38b | ||
|
|
7430af15e6 | ||
|
|
42cdd9a46b | ||
|
|
3cf45edc15 |
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -24,6 +24,7 @@
|
||||
/NOTICE.md @torkelo
|
||||
/README.md @grafana/docs-grafana
|
||||
/ROADMAP.md @torkelo
|
||||
/SECURITY.md @grafana/security-team
|
||||
/SUPPORT.md @torkelo
|
||||
/WORKFLOW.md @torkelo
|
||||
/contribute/ @grafana/grafana-community-support
|
||||
|
||||
12
.github/actions/build-package/action.yml
vendored
12
.github/actions/build-package/action.yml
vendored
@@ -82,6 +82,14 @@ inputs:
|
||||
description: Docker registry of produced images
|
||||
default: docker.io
|
||||
required: false
|
||||
ubuntu-base:
|
||||
type: string
|
||||
default: 'ubuntu:22.04'
|
||||
required: false
|
||||
alpine-base:
|
||||
type: string
|
||||
default: 'alpine:3.22'
|
||||
required: false
|
||||
outputs:
|
||||
dist-dir:
|
||||
description: Directory where artifacts are placed
|
||||
@@ -126,11 +134,13 @@ runs:
|
||||
UBUNTU_TAG_FORMAT: ${{ inputs.docker-tag-format-ubuntu }}
|
||||
CHECKSUM: ${{ inputs.checksum }}
|
||||
VERIFY: ${{ inputs.verify }}
|
||||
ALPINE_BASE: ${{ inputs.alpine-base }}
|
||||
UBUNTU_BASE: ${{ inputs.ubuntu-base }}
|
||||
with:
|
||||
verb: run
|
||||
dagger-flags: --verbose=0
|
||||
version: 0.18.8
|
||||
args: go run -C ${GRAFANA_PATH} ./pkg/build/cmd artifacts --artifacts ${ARTIFACTS} --grafana-dir=${GRAFANA_PATH} --enterprise-dir=${ENTERPRISE_PATH} --version=${VERSION} --patches-repo=${PATCHES_REPO} --patches-ref=${PATCHES_REF} --patches-path=${PATCHES_PATH} --build-id=${BUILD_ID} --tag-format="${TAG_FORMAT}" --ubuntu-tag-format="${UBUNTU_TAG_FORMAT}" --org=${DOCKER_ORG} --registry=${DOCKER_REGISTRY} --checksum=${CHECKSUM} --verify=${VERIFY} > $OUTFILE
|
||||
args: go run -C ${GRAFANA_PATH} ./pkg/build/cmd artifacts --artifacts ${ARTIFACTS} --grafana-dir=${GRAFANA_PATH} --alpine-base=${ALPINE_BASE} --ubuntu-base=${UBUNTU_BASE} --enterprise-dir=${ENTERPRISE_PATH} --version=${VERSION} --patches-repo=${PATCHES_REPO} --patches-ref=${PATCHES_REF} --patches-path=${PATCHES_PATH} --build-id=${BUILD_ID} --tag-format="${TAG_FORMAT}" --ubuntu-tag-format="${UBUNTU_TAG_FORMAT}" --org=${DOCKER_ORG} --registry=${DOCKER_REGISTRY} --checksum=${CHECKSUM} --verify=${VERIFY} > $OUTFILE
|
||||
- id: output
|
||||
shell: bash
|
||||
env:
|
||||
|
||||
1
.github/actions/change-detection/action.yml
vendored
1
.github/actions/change-detection/action.yml
vendored
@@ -95,7 +95,6 @@ runs:
|
||||
- 'nx.json'
|
||||
- 'tsconfig.json'
|
||||
- '.yarn/**'
|
||||
- 'apps/dashboard/pkg/migration/**'
|
||||
- '${{ inputs.self }}'
|
||||
e2e:
|
||||
- 'e2e/**'
|
||||
|
||||
4
.github/pr-commands.json
vendored
4
.github/pr-commands.json
vendored
@@ -365,9 +365,7 @@
|
||||
"type": "changedfiles",
|
||||
"matches": [
|
||||
"public/app/plugins/panel/gauge/**/*",
|
||||
"public/app/plugins/panel/radialbar/**/*",
|
||||
"/packages/grafana-ui/src/components/Gauge/**/*",
|
||||
"/packages/grafana-ui/src/components/RadialGauge/**/*"
|
||||
"/packages/grafana-ui/src/components/Gauge/**/*"
|
||||
],
|
||||
"action": "updateLabel",
|
||||
"addLabel": "area/panel/gauge"
|
||||
|
||||
2
.github/workflows/cleanup-branches.yml
vendored
2
.github/workflows/cleanup-branches.yml
vendored
@@ -14,5 +14,5 @@ jobs:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: grafana/shared-workflows/actions/cleanup-branches@cleanup-branches/v0.2.1
|
||||
with:
|
||||
dry-run: false
|
||||
dry-run: true
|
||||
max-date: "1 month ago"
|
||||
|
||||
41
.github/workflows/release-npm.yml
vendored
41
.github/workflows/release-npm.yml
vendored
@@ -90,7 +90,6 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ inputs.grafana_commit }}
|
||||
fetch-depth: 2 # Need HEAD~1 for e2e-selectors change detection
|
||||
|
||||
- name: Setup Node
|
||||
uses: ./.github/actions/setup-node
|
||||
@@ -128,43 +127,3 @@ jobs:
|
||||
env:
|
||||
NPM_TAG: ${{ steps.npm-tag.outputs.NPM_TAG }}
|
||||
run: ./scripts/publish-npm-packages.sh --dist-tag "$NPM_TAG" --registry 'https://registry.npmjs.org/'
|
||||
|
||||
# Notify plugin-tools when e2e-selectors changes so it can update its bundled version
|
||||
- name: Check for e2e-selectors changes
|
||||
id: check-e2e-changes
|
||||
run: |
|
||||
CHANGES=$(git diff --name-only HEAD~1 HEAD -- packages/grafana-e2e-selectors | wc -l)
|
||||
echo "changes=$CHANGES" >> "$GITHUB_OUTPUT"
|
||||
if [ "$CHANGES" -gt 0 ]; then
|
||||
echo "Detected $CHANGES file(s) changed in packages/grafana-e2e-selectors"
|
||||
fi
|
||||
|
||||
- name: Get Vault secrets
|
||||
if: steps.check-e2e-changes.outputs.changes > 0
|
||||
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 for plugin-tools
|
||||
if: steps.check-e2e-changes.outputs.changes > 0
|
||||
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: '["plugin-tools"]'
|
||||
permissions: '{"actions": "write"}'
|
||||
|
||||
- name: Dispatch to plugin-tools
|
||||
if: steps.check-e2e-changes.outputs.changes > 0
|
||||
env:
|
||||
VERSION: ${{ inputs.version }}
|
||||
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
|
||||
run: |
|
||||
echo "Dispatching bump-e2e-selectors workflow to grafana/plugin-tools with version $VERSION"
|
||||
gh workflow run bump-e2e-selectors.yml \
|
||||
--repo grafana/plugin-tools \
|
||||
--ref main \
|
||||
--field version="$VERSION"
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
diff --git a/dist/builder-manager/index.js b/dist/builder-manager/index.js
|
||||
index 3d7f9b213dae1801bda62b31db31b9113e382ccd..212501c63d20146c29db63fb0f6300c6779eecb5 100644
|
||||
--- a/dist/builder-manager/index.js
|
||||
+++ b/dist/builder-manager/index.js
|
||||
@@ -1970,7 +1970,7 @@ var pa = /^\/($|\?)/, G, C, xt = /* @__PURE__ */ o(async (e) => {
|
||||
bundle: !0,
|
||||
minify: !0,
|
||||
sourcemap: !1,
|
||||
- conditions: ["browser", "module", "default"],
|
||||
+ conditions: ["@grafana-app/source", "browser", "module", "default"],
|
||||
jsxFactory: "React.createElement",
|
||||
jsxFragment: "React.Fragment",
|
||||
jsx: "transform",
|
||||
29
SECURITY.md
Normal file
29
SECURITY.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Reporting security issues
|
||||
|
||||
If you think you have found a security vulnerability, we have two routes for reporting security issues.
|
||||
|
||||
Important: Whichever route you choose, we ask you to not disclose the vulnerability before it has been fixed and announced, unless you received a response from the Grafana Labs security team that you can do so.
|
||||
|
||||
[Full guidance on reporting a security issue can be found here](https://grafana.com/legal/report-a-security-issue/).
|
||||
|
||||
This product is in scope for our Bug Bounty Program. To submit a vulnerability report, please visit [Grafana Labs Bug Bounty page](https://app.intigriti.com/programs/grafanalabs/grafanaossbbp/detail) and follow the instructions provided. Our security team will review your submission and get back to you as soon as possible.
|
||||
|
||||
---
|
||||
|
||||
For products and services outside the scope of our bug bounty program, or if you do not wish to receive a bounty, you can report issues directly to us via email at security@grafana.com. This address can be used for all of Grafana Labs’ open source and commercial products (including but not limited to Grafana, Grafana Cloud, Grafana Enterprise, and grafana.com).
|
||||
|
||||
Please encrypt your message to us; please use our PGP key. The key fingerprint is:
|
||||
|
||||
225E 6A9B BB15 A37E 95EB 6312 C66A 51CC B44C 27E0
|
||||
|
||||
The key is available from [keyserver.ubuntu.com](https://keyserver.ubuntu.com/pks/lookup?search=0x225E6A9BBB15A37E95EB6312C66A51CCB44C27E0&fingerprint=on&op=index).
|
||||
|
||||
Grafana Labs will send you a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
|
||||
|
||||
**Important:** We ask you to not disclose the vulnerability before it have been fixed and announced, unless you received a response from the Grafana Labs security team that you can do so.
|
||||
|
||||
## Security announcements
|
||||
|
||||
We will post a summary, remediation, and mitigation details for any patch containing security fixes on the Grafana blog. The security announcement blog posts will be tagged with the [security tag](https://grafana.com/tags/security/).
|
||||
|
||||
You can also track security announcements via the [RSS feed](https://grafana.com/tags/security/index.xml).
|
||||
@@ -165,7 +165,6 @@ require (
|
||||
github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1 // indirect
|
||||
github.com/grafana/grafana/apps/provisioning v0.0.0 // indirect
|
||||
github.com/grafana/grafana/pkg/apiserver v0.0.0 // indirect
|
||||
github.com/grafana/grafana/pkg/semconv v0.0.0-20250804150913-990f1c69ecc2 // indirect
|
||||
github.com/grafana/otel-profiling-go v0.5.1 // indirect
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect
|
||||
github.com/grafana/sqlds/v4 v4.2.7 // indirect
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package v0alpha1
|
||||
|
||||
TemplateKind: *"grafana" | "mimir"
|
||||
|
||||
TemplateGroupSpec: {
|
||||
title: string
|
||||
content: string
|
||||
kind: TemplateKind
|
||||
}
|
||||
|
||||
@@ -2,24 +2,13 @@
|
||||
|
||||
package v0alpha1
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type TemplateGroupTemplateKind string
|
||||
|
||||
const (
|
||||
TemplateGroupTemplateKindGrafana TemplateGroupTemplateKind = "grafana"
|
||||
TemplateGroupTemplateKindMimir TemplateGroupTemplateKind = "mimir"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type TemplateGroupSpec struct {
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Kind TemplateGroupTemplateKind `json:"kind"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
// NewTemplateGroupSpec creates a new TemplateGroupSpec object.
|
||||
func NewTemplateGroupSpec() *TemplateGroupSpec {
|
||||
return &TemplateGroupSpec{
|
||||
Kind: TemplateGroupTemplateKindGrafana,
|
||||
}
|
||||
return &TemplateGroupSpec{}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ var (
|
||||
rawSchemaRoutingTreev0alpha1 = []byte(`{"Matcher":{"additionalProperties":false,"properties":{"label":{"type":"string"},"type":{"enum":["=","!=","=~","!~"],"type":"string"},"value":{"type":"string"}},"required":["type","label","value"],"type":"object"},"Route":{"additionalProperties":false,"properties":{"active_time_intervals":{"items":{"type":"string"},"type":"array"},"continue":{"type":"boolean"},"group_by":{"items":{"type":"string"},"type":"array"},"group_interval":{"type":"string"},"group_wait":{"type":"string"},"matchers":{"items":{"$ref":"#/components/schemas/Matcher"},"type":"array"},"mute_time_intervals":{"items":{"type":"string"},"type":"array"},"receiver":{"type":"string"},"repeat_interval":{"type":"string"},"routes":{"items":{"$ref":"#/components/schemas/Route"},"type":"array"}},"required":["continue"],"type":"object"},"RouteDefaults":{"additionalProperties":false,"properties":{"group_by":{"items":{"type":"string"},"type":"array"},"group_interval":{"type":"string"},"group_wait":{"type":"string"},"receiver":{"type":"string"},"repeat_interval":{"type":"string"}},"required":["receiver"],"type":"object"},"RoutingTree":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"defaults":{"$ref":"#/components/schemas/RouteDefaults"},"routes":{"items":{"$ref":"#/components/schemas/Route"},"type":"array"}},"required":["defaults","routes"],"type":"object"}}`)
|
||||
versionSchemaRoutingTreev0alpha1 app.VersionSchema
|
||||
_ = json.Unmarshal(rawSchemaRoutingTreev0alpha1, &versionSchemaRoutingTreev0alpha1)
|
||||
rawSchemaTemplateGroupv0alpha1 = []byte(`{"TemplateGroup":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"TemplateKind":{"enum":["grafana","mimir"],"type":"string"},"spec":{"additionalProperties":false,"properties":{"content":{"type":"string"},"kind":{"$ref":"#/components/schemas/TemplateKind","default":"grafana"},"title":{"type":"string"}},"required":["title","content","kind"],"type":"object"}}`)
|
||||
rawSchemaTemplateGroupv0alpha1 = []byte(`{"TemplateGroup":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"content":{"type":"string"},"title":{"type":"string"}},"required":["title","content"],"type":"object"}}`)
|
||||
versionSchemaTemplateGroupv0alpha1 app.VersionSchema
|
||||
_ = json.Unmarshal(rawSchemaTemplateGroupv0alpha1, &versionSchemaTemplateGroupv0alpha1)
|
||||
rawSchemaTimeIntervalv0alpha1 = []byte(`{"Interval":{"additionalProperties":false,"properties":{"days_of_month":{"items":{"type":"string"},"type":"array"},"location":{"type":"string"},"months":{"items":{"type":"string"},"type":"array"},"times":{"items":{"$ref":"#/components/schemas/TimeRange"},"type":"array"},"weekdays":{"items":{"type":"string"},"type":"array"},"years":{"items":{"type":"string"},"type":"array"}},"type":"object"},"TimeInterval":{"properties":{"spec":{"$ref":"#/components/schemas/spec"}},"required":["spec"]},"TimeRange":{"additionalProperties":false,"properties":{"end_time":{"type":"string"},"start_time":{"type":"string"}},"required":["start_time","end_time"],"type":"object"},"spec":{"additionalProperties":false,"properties":{"name":{"type":"string"},"time_intervals":{"items":{"$ref":"#/components/schemas/Interval"},"type":"array"}},"required":["name","time_intervals"],"type":"object"}}`)
|
||||
|
||||
@@ -300,9 +300,15 @@
|
||||
"y": 0
|
||||
},
|
||||
"id": 6,
|
||||
"options": {},
|
||||
"content": "# Graph panel \u003e\u003e Timeseries panel\n\nKnown issues:\n* hiding null/empty series\n* time regions",
|
||||
"mode": "markdown",
|
||||
"options": {
|
||||
"code": {
|
||||
"language": "plaintext",
|
||||
"showLineNumbers": false,
|
||||
"showMiniMap": false
|
||||
},
|
||||
"content": "# Graph panel \u003e\u003e Timeseries panel\n\nKnown issues:\n* hiding null/empty series\n* time regions",
|
||||
"mode": "markdown"
|
||||
},
|
||||
"pluginVersion": "11.0.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
{
|
||||
"apiVersion": "dashboard.grafana.app/v1beta1",
|
||||
"kind": "Dashboard",
|
||||
"metadata": {
|
||||
"name": "ad5vfcn",
|
||||
"namespace": "default",
|
||||
"uid": "dlMZZl6GndU8gJLUQSmgZxXBPCNXyXhNBeQJhHXl0r4X",
|
||||
"resourceVersion": "2",
|
||||
"generation": 2,
|
||||
"creationTimestamp": "2025-11-28T10:14:21Z",
|
||||
"labels": {
|
||||
"grafana.app/deprecatedInternalID": "288"
|
||||
},
|
||||
"annotations": {
|
||||
"grafana.app/createdBy": "user:eex2ofwuj0agwd",
|
||||
"grafana.app/updatedBy": "user:eex2ofwuj0agwd",
|
||||
"grafana.app/updatedTimestamp": "2025-11-28T10:15:06Z"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 288,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "gdev-testdata"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"showValues": false,
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "12.4.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {},
|
||||
"queryType": "randomWalk"
|
||||
},
|
||||
{
|
||||
"datasource": {},
|
||||
"queryType": "randomWalk"
|
||||
}
|
||||
],
|
||||
"title": "New panel",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"schemaVersion": 42,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "browser",
|
||||
"title": "Panel ds inheritance ",
|
||||
"uid": "ad5vfcn",
|
||||
"version": 2
|
||||
},
|
||||
"status": {}
|
||||
}
|
||||
@@ -1,864 +0,0 @@
|
||||
{
|
||||
"kind": "DashboardWithAccessInfo",
|
||||
"apiVersion": "dashboard.grafana.app/v2beta1",
|
||||
"metadata": {
|
||||
"name": "value-mapping-test",
|
||||
"namespace": "default",
|
||||
"uid": "value-mapping-test",
|
||||
"resourceVersion": "1765384157199094",
|
||||
"generation": 2,
|
||||
"creationTimestamp": "2025-11-19T20:09:28Z",
|
||||
"labels": {
|
||||
"grafana.app/deprecatedInternalID": "646372978987008"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"annotations": [
|
||||
{
|
||||
"kind": "AnnotationQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "grafana",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "-- Grafana --"
|
||||
},
|
||||
"spec": {}
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations \u0026 Alerts",
|
||||
"builtIn": true,
|
||||
"legacyOptions": {
|
||||
"type": "dashboard"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"cursorSync": "Off",
|
||||
"description": "Test dashboard for all value mapping types and override matcher types",
|
||||
"editable": true,
|
||||
"elements": {
|
||||
"panel-1": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 1,
|
||||
"title": "ValueMap Example",
|
||||
"description": "Panel with ValueMap mapping type - maps specific text values to colors and display text",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "prometheus",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "prometheus-uid"
|
||||
},
|
||||
"spec": {
|
||||
"expr": "up"
|
||||
}
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "VizConfig",
|
||||
"group": "stat",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"type": "value",
|
||||
"options": {
|
||||
"critical": {
|
||||
"text": "Critical!",
|
||||
"color": "red",
|
||||
"index": 0
|
||||
},
|
||||
"ok": {
|
||||
"text": "OK",
|
||||
"color": "green",
|
||||
"index": 2
|
||||
},
|
||||
"warning": {
|
||||
"text": "Warning",
|
||||
"color": "orange",
|
||||
"index": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "status"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 100
|
||||
},
|
||||
{
|
||||
"id": "custom.align",
|
||||
"value": "center"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-2": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 2,
|
||||
"title": "RangeMap Example",
|
||||
"description": "Panel with RangeMap mapping type - maps numerical ranges to colors and display text",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "prometheus",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "prometheus-uid"
|
||||
},
|
||||
"spec": {
|
||||
"expr": "cpu_usage_percent"
|
||||
}
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "VizConfig",
|
||||
"group": "gauge",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"type": "range",
|
||||
"options": {
|
||||
"from": 0,
|
||||
"to": 50,
|
||||
"result": {
|
||||
"text": "Low",
|
||||
"color": "green",
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "range",
|
||||
"options": {
|
||||
"from": 50,
|
||||
"to": 80,
|
||||
"result": {
|
||||
"text": "Medium",
|
||||
"color": "orange",
|
||||
"index": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "range",
|
||||
"options": {
|
||||
"from": 80,
|
||||
"to": 100,
|
||||
"result": {
|
||||
"text": "High",
|
||||
"color": "red",
|
||||
"index": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byRegexp",
|
||||
"options": "/^cpu_/"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "percent"
|
||||
},
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-3": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 3,
|
||||
"title": "RegexMap Example",
|
||||
"description": "Panel with RegexMap mapping type - maps values matching regex patterns to colors",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "prometheus",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "prometheus-uid"
|
||||
},
|
||||
"spec": {
|
||||
"expr": "log_level"
|
||||
}
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "VizConfig",
|
||||
"group": "stat",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "/^error.*/",
|
||||
"result": {
|
||||
"text": "Error",
|
||||
"color": "red",
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "/^warn.*/",
|
||||
"result": {
|
||||
"text": "Warning",
|
||||
"color": "orange",
|
||||
"index": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "/^info.*/",
|
||||
"result": {
|
||||
"text": "Info",
|
||||
"color": "blue",
|
||||
"index": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byType",
|
||||
"options": "string"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"type": "color-text"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-4": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 4,
|
||||
"title": "SpecialValueMap Example",
|
||||
"description": "Panel with SpecialValueMap mapping type - maps special values like null, NaN, true, false to display text",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "prometheus",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "prometheus-uid"
|
||||
},
|
||||
"spec": {
|
||||
"expr": "some_metric"
|
||||
}
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "VizConfig",
|
||||
"group": "stat",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "null",
|
||||
"result": {
|
||||
"text": "No Data",
|
||||
"color": "gray",
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "nan",
|
||||
"result": {
|
||||
"text": "Not a Number",
|
||||
"color": "gray",
|
||||
"index": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "null+nan",
|
||||
"result": {
|
||||
"text": "N/A",
|
||||
"color": "gray",
|
||||
"index": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "true",
|
||||
"result": {
|
||||
"text": "Yes",
|
||||
"color": "green",
|
||||
"index": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "false",
|
||||
"result": {
|
||||
"text": "No",
|
||||
"color": "red",
|
||||
"index": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "empty",
|
||||
"result": {
|
||||
"text": "Empty",
|
||||
"color": "gray",
|
||||
"index": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byFrameRefID",
|
||||
"options": "A"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"fixedColor": "blue",
|
||||
"mode": "fixed"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-6": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 6,
|
||||
"title": "Empty Properties Override Example",
|
||||
"description": "Panel with override that has empty properties array - tests conversion of overrides without any property modifications",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "prometheus",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "prometheus-uid"
|
||||
},
|
||||
"spec": {
|
||||
"expr": "empty_override_metric"
|
||||
}
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "VizConfig",
|
||||
"group": "stat",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "field_with_empty_override"
|
||||
},
|
||||
"properties": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-5": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 5,
|
||||
"title": "Combined Mappings and Overrides Example",
|
||||
"description": "Panel with all mapping types combined - demonstrates mixing different mapping types and multiple override matchers",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "prometheus",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "prometheus-uid"
|
||||
},
|
||||
"spec": {
|
||||
"expr": "combined_metric"
|
||||
}
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "prometheus",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "prometheus-uid"
|
||||
},
|
||||
"spec": {
|
||||
"expr": "secondary_metric"
|
||||
}
|
||||
},
|
||||
"refId": "B",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "VizConfig",
|
||||
"group": "table",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"type": "value",
|
||||
"options": {
|
||||
"failure": {
|
||||
"text": "Failure",
|
||||
"color": "red",
|
||||
"index": 1
|
||||
},
|
||||
"success": {
|
||||
"text": "Success",
|
||||
"color": "green",
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "range",
|
||||
"options": {
|
||||
"from": 0,
|
||||
"to": 100,
|
||||
"result": {
|
||||
"text": "In Range",
|
||||
"color": "blue",
|
||||
"index": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "/^[A-Z]{3}-\\d+$/",
|
||||
"result": {
|
||||
"text": "ID Format",
|
||||
"color": "purple",
|
||||
"index": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "null",
|
||||
"result": {
|
||||
"text": "Missing",
|
||||
"color": "gray",
|
||||
"index": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "status"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 120
|
||||
},
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"type": "color-background"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byRegexp",
|
||||
"options": "/^value_/"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "short"
|
||||
},
|
||||
{
|
||||
"id": "min",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"id": "max",
|
||||
"value": 100
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byType",
|
||||
"options": "number"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
},
|
||||
{
|
||||
"id": "thresholds",
|
||||
"value": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "yellow",
|
||||
"value": 50
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byFrameRefID",
|
||||
"options": "B"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "displayName",
|
||||
"value": "Secondary Query"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byValue",
|
||||
"options": {
|
||||
"op": "gte",
|
||||
"reducer": "allIsNull",
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.hidden",
|
||||
"value": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
"kind": "GridLayout",
|
||||
"spec": {
|
||||
"items": [
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 12,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-1"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 12,
|
||||
"y": 0,
|
||||
"width": 12,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-2"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 0,
|
||||
"y": 8,
|
||||
"width": 12,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-3"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 12,
|
||||
"y": 8,
|
||||
"width": 12,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-4"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 0,
|
||||
"y": 16,
|
||||
"width": 24,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-5"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 0,
|
||||
"y": 24,
|
||||
"width": 12,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-6"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"preload": false,
|
||||
"tags": [
|
||||
"value-mapping",
|
||||
"overrides",
|
||||
"test"
|
||||
],
|
||||
"timeSettings": {
|
||||
"timezone": "browser",
|
||||
"from": "now-6h",
|
||||
"to": "now",
|
||||
"autoRefresh": "",
|
||||
"autoRefreshIntervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"hideTimepicker": false,
|
||||
"fiscalYearStartMonth": 0
|
||||
},
|
||||
"title": "Value Mapping and Overrides Test",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -743,9 +743,7 @@
|
||||
"text": "prod",
|
||||
"value": "prod"
|
||||
},
|
||||
"datasource": {
|
||||
"uid": "$datasource"
|
||||
},
|
||||
"datasource": "$datasource",
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"label": "cluster",
|
||||
@@ -766,9 +764,7 @@
|
||||
"text": "prod",
|
||||
"value": "prod"
|
||||
},
|
||||
"datasource": {
|
||||
"uid": "$datasource"
|
||||
},
|
||||
"datasource": "$datasource",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "namespace",
|
||||
|
||||
@@ -961,12 +961,8 @@
|
||||
"hide": "dontHide",
|
||||
"refresh": "onDashboardLoad",
|
||||
"skipUrlSync": false,
|
||||
"datasource": {
|
||||
"type": "",
|
||||
"uid": "$datasource"
|
||||
},
|
||||
"query": {
|
||||
"kind": "",
|
||||
"kind": "prometheus",
|
||||
"spec": {
|
||||
"__legacyStringValue": "label_values(up, job)"
|
||||
}
|
||||
@@ -992,12 +988,8 @@
|
||||
"hide": "dontHide",
|
||||
"refresh": "onDashboardLoad",
|
||||
"skipUrlSync": false,
|
||||
"datasource": {
|
||||
"type": "",
|
||||
"uid": "$datasource"
|
||||
},
|
||||
"query": {
|
||||
"kind": "",
|
||||
"kind": "prometheus",
|
||||
"spec": {
|
||||
"__legacyStringValue": "label_values(up{job=~\"$cluster\"}, instance)"
|
||||
}
|
||||
|
||||
@@ -978,11 +978,8 @@
|
||||
"skipUrlSync": false,
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "",
|
||||
"group": "prometheus",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "$datasource"
|
||||
},
|
||||
"spec": {
|
||||
"__legacyStringValue": "label_values(up, job)"
|
||||
}
|
||||
@@ -1010,11 +1007,8 @@
|
||||
"skipUrlSync": false,
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "",
|
||||
"group": "prometheus",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "$datasource"
|
||||
},
|
||||
"spec": {
|
||||
"__legacyStringValue": "label_values(up{job=~\"$cluster\"}, instance)"
|
||||
}
|
||||
|
||||
@@ -115,14 +115,7 @@
|
||||
"kind": "logs",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "logs",
|
||||
"originalOptions": {
|
||||
"height": 100
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -120,14 +120,7 @@
|
||||
"group": "logs",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "logs",
|
||||
"originalOptions": {
|
||||
"height": 100
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -182,20 +182,7 @@
|
||||
"kind": "table",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "table",
|
||||
"originalOptions": {
|
||||
"grid": {
|
||||
"max": 100,
|
||||
"min": 0
|
||||
},
|
||||
"legend": true,
|
||||
"y2_format": "bytes",
|
||||
"y_format": "short"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -189,20 +189,7 @@
|
||||
"group": "table",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "table",
|
||||
"originalOptions": {
|
||||
"grid": {
|
||||
"max": 100,
|
||||
"min": 0
|
||||
},
|
||||
"legend": true,
|
||||
"y2_format": "bytes",
|
||||
"y_format": "short"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -435,29 +435,7 @@
|
||||
"kind": "table",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "table",
|
||||
"originalOptions": {
|
||||
"styles": [
|
||||
{
|
||||
"colors": [
|
||||
"red",
|
||||
"yellow",
|
||||
"green"
|
||||
],
|
||||
"pattern": "/.*/",
|
||||
"thresholds": [
|
||||
"10",
|
||||
"20"
|
||||
],
|
||||
"unit": "short"
|
||||
}
|
||||
],
|
||||
"table": "table2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -449,29 +449,7 @@
|
||||
"group": "table",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "table",
|
||||
"originalOptions": {
|
||||
"styles": [
|
||||
{
|
||||
"colors": [
|
||||
"red",
|
||||
"yellow",
|
||||
"green"
|
||||
],
|
||||
"pattern": "/.*/",
|
||||
"thresholds": [
|
||||
"10",
|
||||
"20"
|
||||
],
|
||||
"unit": "short"
|
||||
}
|
||||
],
|
||||
"table": "table2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -110,15 +110,7 @@
|
||||
"kind": "text",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "# Angular Text Panel\n# $constant\n\nFor markdown syntax help: [commonmark.org/help](https://commonmark.org/help/)\n\n## $text\n\n",
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -115,15 +115,7 @@
|
||||
"group": "text",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "# Angular Text Panel\n# $constant\n\nFor markdown syntax help: [commonmark.org/help](https://commonmark.org/help/)\n\n## $text\n\n",
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -361,15 +361,7 @@
|
||||
"kind": "text",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "## Data link variables overview\n\nThis dashboard presents variables that one can use when creating *data links*. All links redirect to this dashboard and this panel represents the values that were interpolated in the link that was clicked.\n\n\n#### Series variables\n1. **Name:** \u003cspan style=\"color: orange;\"\u003e$seriesName\u003c/span\u003e\n2. **label.datacenter:** \u003cspan style=\"color: orange;\"\u003e$labelDatacenter\u003c/span\u003e\n3. **label.datacenter.region:** \u003cspan style=\"color: orange;\"\u003e$labelDatacenterRegion\u003c/span\u003e\n\n#### Field variables\n1. **Name:** \u003cspan style=\"color: orange;\"\u003e$fieldName\u003c/span\u003e\n\n#### Value variables\n1. **Time:** \u003cspan style=\"color: orange;\"\u003e$valueTime\u003c/span\u003e\n2. **Numeric:** \u003cspan style=\"color: orange;\"\u003e$valueNumeric\u003c/span\u003e\n3. **Text:** \u003cspan style=\"color: orange;\"\u003e$valueText\u003c/span\u003e\n4. **Calc:** \u003cspan style=\"color: orange;\"\u003e$valueCalc\u003c/span\u003e\n\n",
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -372,15 +372,7 @@
|
||||
"group": "text",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "## Data link variables overview\n\nThis dashboard presents variables that one can use when creating *data links*. All links redirect to this dashboard and this panel represents the values that were interpolated in the link that was clicked.\n\n\n#### Series variables\n1. **Name:** \u003cspan style=\"color: orange;\"\u003e$seriesName\u003c/span\u003e\n2. **label.datacenter:** \u003cspan style=\"color: orange;\"\u003e$labelDatacenter\u003c/span\u003e\n3. **label.datacenter.region:** \u003cspan style=\"color: orange;\"\u003e$labelDatacenterRegion\u003c/span\u003e\n\n#### Field variables\n1. **Name:** \u003cspan style=\"color: orange;\"\u003e$fieldName\u003c/span\u003e\n\n#### Value variables\n1. **Time:** \u003cspan style=\"color: orange;\"\u003e$valueTime\u003c/span\u003e\n2. **Numeric:** \u003cspan style=\"color: orange;\"\u003e$valueNumeric\u003c/span\u003e\n3. **Text:** \u003cspan style=\"color: orange;\"\u003e$valueText\u003c/span\u003e\n4. **Calc:** \u003cspan style=\"color: orange;\"\u003e$valueCalc\u003c/span\u003e\n\n",
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -167,15 +167,7 @@
|
||||
"kind": "text",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "## Data center = $datacenter\n\n### server = $server\n\n#### pod = $pod",
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -174,15 +174,7 @@
|
||||
"group": "text",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "## Data center = $datacenter\n\n### server = $server\n\n#### pod = $pod",
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -273,15 +273,7 @@
|
||||
"kind": "text",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "## Data center = $datacenter\n\n### server = $server\n\n#### pod = $pod",
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -282,15 +282,7 @@
|
||||
"group": "text",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "## Data center = $datacenter\n\n### server = $server\n\n#### pod = $pod",
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -296,7 +296,6 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"content": "# Graph panel \u003e\u003e Timeseries panel\n\nKnown issues:\n* hiding null/empty series\n* time regions",
|
||||
"datasource": {
|
||||
"type": "grafana-testdata-datasource"
|
||||
},
|
||||
@@ -307,7 +306,15 @@
|
||||
"y": 0
|
||||
},
|
||||
"id": 6,
|
||||
"mode": "markdown",
|
||||
"options": {
|
||||
"code": {
|
||||
"language": "plaintext",
|
||||
"showLineNumbers": false,
|
||||
"showMiniMap": false
|
||||
},
|
||||
"content": "# Graph panel \u003e\u003e Timeseries panel\n\nKnown issues:\n* hiding null/empty series\n* time regions",
|
||||
"mode": "markdown"
|
||||
},
|
||||
"pluginVersion": "11.0.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
|
||||
@@ -1256,13 +1256,13 @@
|
||||
"spec": {
|
||||
"pluginVersion": "11.0.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "# Graph panel \u003e\u003e Timeseries panel\n\nKnown issues:\n* hiding null/empty series\n* time regions",
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
"code": {
|
||||
"language": "plaintext",
|
||||
"showLineNumbers": false,
|
||||
"showMiniMap": false
|
||||
},
|
||||
"content": "# Graph panel \u003e\u003e Timeseries panel\n\nKnown issues:\n* hiding null/empty series\n* time regions",
|
||||
"mode": "markdown"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
|
||||
@@ -1301,13 +1301,13 @@
|
||||
"version": "11.0.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "# Graph panel \u003e\u003e Timeseries panel\n\nKnown issues:\n* hiding null/empty series\n* time regions",
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
"code": {
|
||||
"language": "plaintext",
|
||||
"showLineNumbers": false,
|
||||
"showMiniMap": false
|
||||
},
|
||||
"content": "# Graph panel \u003e\u003e Timeseries panel\n\nKnown issues:\n* hiding null/empty series\n* time regions",
|
||||
"mode": "markdown"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
|
||||
@@ -62,12 +62,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -157,12 +151,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -253,12 +241,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -338,12 +320,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -425,12 +401,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -510,12 +480,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -595,12 +559,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -681,12 +639,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -778,12 +730,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -981,12 +927,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1066,12 +1006,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1151,12 +1085,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
|
||||
@@ -67,12 +67,6 @@
|
||||
"version": "7.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -165,12 +159,6 @@
|
||||
"version": "7.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -264,12 +252,6 @@
|
||||
"version": "7.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -352,12 +334,6 @@
|
||||
"version": "7.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -442,12 +418,6 @@
|
||||
"version": "7.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -530,12 +500,6 @@
|
||||
"version": "7.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -618,12 +582,6 @@
|
||||
"version": "7.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -707,12 +665,6 @@
|
||||
"version": "7.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -807,12 +759,6 @@
|
||||
"version": "7.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1015,12 +961,6 @@
|
||||
"version": "7.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1103,12 +1043,6 @@
|
||||
"version": "7.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
@@ -1191,12 +1125,6 @@
|
||||
"version": "7.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "gauge",
|
||||
"originalOptions": {
|
||||
"nullPointMode": "null"
|
||||
}
|
||||
},
|
||||
"baseColor": "#299c46",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
|
||||
@@ -412,17 +412,7 @@
|
||||
"kind": "text",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "Should be a long line connecting the null region in the `connected` mode, and in zero it should just be a line with zero value at the null points. ",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -466,17 +456,7 @@
|
||||
"kind": "text",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "Stacking values on top of nulls, should treat the null values as zero. ",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -520,17 +500,7 @@
|
||||
"kind": "text",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "Stacking when all values are null should leave a gap in the graph",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -1711,17 +1681,7 @@
|
||||
"kind": "text",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "Left is showing null between values for a normal line graph and staircase graph. Orphaned data points should be rendered as points",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -2101,17 +2061,7 @@
|
||||
"kind": "text",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "Just verify that the tooltip time has millisecond resolution ",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -2155,17 +2105,7 @@
|
||||
"kind": "text",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "Verify that axis labels look ok",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -429,17 +429,7 @@
|
||||
"group": "text",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "Should be a long line connecting the null region in the `connected` mode, and in zero it should just be a line with zero value at the null points. ",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -485,17 +475,7 @@
|
||||
"group": "text",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "Stacking values on top of nulls, should treat the null values as zero. ",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -541,17 +521,7 @@
|
||||
"group": "text",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "Stacking when all values are null should leave a gap in the graph",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -1809,17 +1779,7 @@
|
||||
"group": "text",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "Left is showing null between values for a normal line graph and staircase graph. Orphaned data points should be rendered as points",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -2212,17 +2172,7 @@
|
||||
"group": "text",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "Just verify that the tooltip time has millisecond resolution ",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -2268,17 +2218,7 @@
|
||||
"group": "text",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "text",
|
||||
"originalOptions": {
|
||||
"content": "Verify that axis labels look ok",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"mode": "markdown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -74,44 +74,7 @@
|
||||
"kind": "heatmap",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {},
|
||||
"color": {
|
||||
"cardColor": "#b4ff00",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateViridis",
|
||||
"exponent": 0.5,
|
||||
"mode": "spectrum"
|
||||
},
|
||||
"dataFormat": "timeseries",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": false,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": true
|
||||
},
|
||||
"reverseYBuckets": false,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": true
|
||||
},
|
||||
"tooltipDecimals": 4,
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"yAxis": {
|
||||
"decimals": 2,
|
||||
"format": "areaM2",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -153,46 +116,7 @@
|
||||
"kind": "heatmap",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {
|
||||
"cardRound": 50
|
||||
},
|
||||
"color": {
|
||||
"cardColor": "#1F60C4",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateOranges",
|
||||
"exponent": 0.5,
|
||||
"mode": "opacity"
|
||||
},
|
||||
"dataFormat": "tsbuckets",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": false,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": true
|
||||
},
|
||||
"reverseYBuckets": false,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": false
|
||||
},
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"yAxis": {
|
||||
"decimals": 1,
|
||||
"format": "kwatt",
|
||||
"logBase": 1,
|
||||
"show": true,
|
||||
"width": "100"
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -234,44 +158,7 @@
|
||||
"kind": "heatmap",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {},
|
||||
"color": {
|
||||
"cardColor": "#1F60C4",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateOranges",
|
||||
"exponent": 0.5,
|
||||
"mode": "opacity"
|
||||
},
|
||||
"dataFormat": "tsbuckets",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": false,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": true
|
||||
},
|
||||
"reverseYBuckets": true,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": false
|
||||
},
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"yAxis": {
|
||||
"decimals": 1,
|
||||
"format": "kwatt",
|
||||
"logBase": 1,
|
||||
"show": true,
|
||||
"width": "100"
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -317,46 +204,7 @@
|
||||
"kind": "heatmap",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {},
|
||||
"color": {
|
||||
"cardColor": "#b4ff00",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateViridis",
|
||||
"exponent": 0.5,
|
||||
"mode": "spectrum"
|
||||
},
|
||||
"dataFormat": "timeseries",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": false,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": true
|
||||
},
|
||||
"reverseYBuckets": false,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": true
|
||||
},
|
||||
"tooltipDecimals": 4,
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"yAxis": {
|
||||
"decimals": 2,
|
||||
"format": "areaM2",
|
||||
"logBase": 1,
|
||||
"max": "50",
|
||||
"min": "20",
|
||||
"show": true
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -398,44 +246,7 @@
|
||||
"kind": "heatmap",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {},
|
||||
"color": {
|
||||
"cardColor": "#b4ff00",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateBuGn",
|
||||
"exponent": 0.5,
|
||||
"mode": "spectrum"
|
||||
},
|
||||
"dataFormat": "timeseries",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": true,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": true
|
||||
},
|
||||
"reverseYBuckets": false,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": true
|
||||
},
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"xBucketNumber": 10,
|
||||
"yAxis": {
|
||||
"format": "short",
|
||||
"logBase": 2,
|
||||
"show": true,
|
||||
"splitFactor": 2
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -477,44 +288,7 @@
|
||||
"kind": "heatmap",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {},
|
||||
"color": {
|
||||
"cardColor": "#b4ff00",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateBuGn",
|
||||
"exponent": 0.5,
|
||||
"mode": "spectrum"
|
||||
},
|
||||
"dataFormat": "timeseries",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": true,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": true
|
||||
},
|
||||
"reverseYBuckets": false,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": true
|
||||
},
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"xBucketNumber": 10,
|
||||
"yAxis": {
|
||||
"format": "short",
|
||||
"logBase": 10,
|
||||
"show": true,
|
||||
"splitFactor": 5
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -78,44 +78,7 @@
|
||||
"group": "heatmap",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {},
|
||||
"color": {
|
||||
"cardColor": "#b4ff00",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateViridis",
|
||||
"exponent": 0.5,
|
||||
"mode": "spectrum"
|
||||
},
|
||||
"dataFormat": "timeseries",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": false,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": true
|
||||
},
|
||||
"reverseYBuckets": false,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": true
|
||||
},
|
||||
"tooltipDecimals": 4,
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"yAxis": {
|
||||
"decimals": 2,
|
||||
"format": "areaM2",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -160,46 +123,7 @@
|
||||
"group": "heatmap",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {
|
||||
"cardRound": 50
|
||||
},
|
||||
"color": {
|
||||
"cardColor": "#1F60C4",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateOranges",
|
||||
"exponent": 0.5,
|
||||
"mode": "opacity"
|
||||
},
|
||||
"dataFormat": "tsbuckets",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": false,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": true
|
||||
},
|
||||
"reverseYBuckets": false,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": false
|
||||
},
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"yAxis": {
|
||||
"decimals": 1,
|
||||
"format": "kwatt",
|
||||
"logBase": 1,
|
||||
"show": true,
|
||||
"width": "100"
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -244,44 +168,7 @@
|
||||
"group": "heatmap",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {},
|
||||
"color": {
|
||||
"cardColor": "#1F60C4",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateOranges",
|
||||
"exponent": 0.5,
|
||||
"mode": "opacity"
|
||||
},
|
||||
"dataFormat": "tsbuckets",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": false,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": true
|
||||
},
|
||||
"reverseYBuckets": true,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": false
|
||||
},
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"yAxis": {
|
||||
"decimals": 1,
|
||||
"format": "kwatt",
|
||||
"logBase": 1,
|
||||
"show": true,
|
||||
"width": "100"
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -329,46 +216,7 @@
|
||||
"group": "heatmap",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {},
|
||||
"color": {
|
||||
"cardColor": "#b4ff00",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateViridis",
|
||||
"exponent": 0.5,
|
||||
"mode": "spectrum"
|
||||
},
|
||||
"dataFormat": "timeseries",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": false,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": true
|
||||
},
|
||||
"reverseYBuckets": false,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": true
|
||||
},
|
||||
"tooltipDecimals": 4,
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"yAxis": {
|
||||
"decimals": 2,
|
||||
"format": "areaM2",
|
||||
"logBase": 1,
|
||||
"max": "50",
|
||||
"min": "20",
|
||||
"show": true
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -413,44 +261,7 @@
|
||||
"group": "heatmap",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {},
|
||||
"color": {
|
||||
"cardColor": "#b4ff00",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateBuGn",
|
||||
"exponent": 0.5,
|
||||
"mode": "spectrum"
|
||||
},
|
||||
"dataFormat": "timeseries",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": true,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": true
|
||||
},
|
||||
"reverseYBuckets": false,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": true
|
||||
},
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"xBucketNumber": 10,
|
||||
"yAxis": {
|
||||
"format": "short",
|
||||
"logBase": 2,
|
||||
"show": true,
|
||||
"splitFactor": 2
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
@@ -495,44 +306,7 @@
|
||||
"group": "heatmap",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {},
|
||||
"color": {
|
||||
"cardColor": "#b4ff00",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateBuGn",
|
||||
"exponent": 0.5,
|
||||
"mode": "spectrum"
|
||||
},
|
||||
"dataFormat": "timeseries",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": true,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": true
|
||||
},
|
||||
"reverseYBuckets": false,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": true
|
||||
},
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"xBucketNumber": 10,
|
||||
"yAxis": {
|
||||
"format": "short",
|
||||
"logBase": 10,
|
||||
"show": true,
|
||||
"splitFactor": 5
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -665,42 +665,7 @@
|
||||
"kind": "heatmap",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {},
|
||||
"color": {
|
||||
"cardColor": "#b4ff00",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateOranges",
|
||||
"exponent": 0.5,
|
||||
"mode": "spectrum"
|
||||
},
|
||||
"dataFormat": "timeseries",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": false,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": false
|
||||
},
|
||||
"reverseYBuckets": false,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": false
|
||||
},
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"yAxis": {
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -691,42 +691,7 @@
|
||||
"group": "heatmap",
|
||||
"version": "",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "heatmap",
|
||||
"originalOptions": {
|
||||
"cards": {},
|
||||
"color": {
|
||||
"cardColor": "#b4ff00",
|
||||
"colorScale": "sqrt",
|
||||
"colorScheme": "interpolateOranges",
|
||||
"exponent": 0.5,
|
||||
"mode": "spectrum"
|
||||
},
|
||||
"dataFormat": "timeseries",
|
||||
"heatmap": {},
|
||||
"hideZeroBuckets": false,
|
||||
"highlightCards": true,
|
||||
"legend": {
|
||||
"show": false
|
||||
},
|
||||
"reverseYBuckets": false,
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"showHistogram": false
|
||||
},
|
||||
"xAxis": {
|
||||
"show": true
|
||||
},
|
||||
"yAxis": {
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
"yBucketBound": "auto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
|
||||
@@ -56,14 +56,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "9.0.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "dashlist",
|
||||
"originalOptions": {
|
||||
"tags": [
|
||||
"panel-tests"
|
||||
]
|
||||
}
|
||||
},
|
||||
"maxItems": 1000,
|
||||
"query": "",
|
||||
"showHeadings": false,
|
||||
@@ -102,15 +94,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "9.0.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "dashlist",
|
||||
"originalOptions": {
|
||||
"tags": [
|
||||
"gdev",
|
||||
"demo"
|
||||
]
|
||||
}
|
||||
},
|
||||
"maxItems": 1000,
|
||||
"query": "",
|
||||
"showHeadings": false,
|
||||
@@ -150,15 +133,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "9.0.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "dashlist",
|
||||
"originalOptions": {
|
||||
"tags": [
|
||||
"templating",
|
||||
"gdev"
|
||||
]
|
||||
}
|
||||
},
|
||||
"maxItems": 1000,
|
||||
"query": "",
|
||||
"showHeadings": false,
|
||||
@@ -198,15 +172,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "9.0.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "dashlist",
|
||||
"originalOptions": {
|
||||
"tags": [
|
||||
"gdev",
|
||||
"datasource-test"
|
||||
]
|
||||
}
|
||||
},
|
||||
"maxItems": 1000,
|
||||
"query": "",
|
||||
"showHeadings": false,
|
||||
@@ -246,12 +211,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "9.0.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "dashlist",
|
||||
"originalOptions": {
|
||||
"tags": []
|
||||
}
|
||||
},
|
||||
"maxItems": 100,
|
||||
"query": "",
|
||||
"showHeadings": true,
|
||||
@@ -288,15 +247,6 @@
|
||||
"spec": {
|
||||
"pluginVersion": "9.0.0-pre",
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "dashlist",
|
||||
"originalOptions": {
|
||||
"tags": [
|
||||
"gdev",
|
||||
"demo"
|
||||
]
|
||||
}
|
||||
},
|
||||
"maxItems": 1000,
|
||||
"query": "",
|
||||
"showHeadings": false,
|
||||
|
||||
@@ -58,14 +58,6 @@
|
||||
"version": "9.0.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "dashlist",
|
||||
"originalOptions": {
|
||||
"tags": [
|
||||
"panel-tests"
|
||||
]
|
||||
}
|
||||
},
|
||||
"maxItems": 1000,
|
||||
"query": "",
|
||||
"showHeadings": false,
|
||||
@@ -105,15 +97,6 @@
|
||||
"version": "9.0.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "dashlist",
|
||||
"originalOptions": {
|
||||
"tags": [
|
||||
"gdev",
|
||||
"demo"
|
||||
]
|
||||
}
|
||||
},
|
||||
"maxItems": 1000,
|
||||
"query": "",
|
||||
"showHeadings": false,
|
||||
@@ -154,15 +137,6 @@
|
||||
"version": "9.0.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "dashlist",
|
||||
"originalOptions": {
|
||||
"tags": [
|
||||
"templating",
|
||||
"gdev"
|
||||
]
|
||||
}
|
||||
},
|
||||
"maxItems": 1000,
|
||||
"query": "",
|
||||
"showHeadings": false,
|
||||
@@ -203,15 +177,6 @@
|
||||
"version": "9.0.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "dashlist",
|
||||
"originalOptions": {
|
||||
"tags": [
|
||||
"gdev",
|
||||
"datasource-test"
|
||||
]
|
||||
}
|
||||
},
|
||||
"maxItems": 1000,
|
||||
"query": "",
|
||||
"showHeadings": false,
|
||||
@@ -252,12 +217,6 @@
|
||||
"version": "9.0.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "dashlist",
|
||||
"originalOptions": {
|
||||
"tags": []
|
||||
}
|
||||
},
|
||||
"maxItems": 100,
|
||||
"query": "",
|
||||
"showHeadings": true,
|
||||
@@ -295,15 +254,6 @@
|
||||
"version": "9.0.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"__angularMigration": {
|
||||
"autoMigrateFrom": "dashlist",
|
||||
"originalOptions": {
|
||||
"tags": [
|
||||
"gdev",
|
||||
"demo"
|
||||
]
|
||||
}
|
||||
},
|
||||
"maxItems": 1000,
|
||||
"query": "",
|
||||
"showHeadings": false,
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
{
|
||||
"kind": "Dashboard",
|
||||
"apiVersion": "dashboard.grafana.app/v0alpha1",
|
||||
"metadata": {
|
||||
"name": "ad5vfcn",
|
||||
"namespace": "default",
|
||||
"uid": "dlMZZl6GndU8gJLUQSmgZxXBPCNXyXhNBeQJhHXl0r4X",
|
||||
"resourceVersion": "2",
|
||||
"generation": 2,
|
||||
"creationTimestamp": "2025-11-28T10:14:21Z",
|
||||
"labels": {
|
||||
"grafana.app/deprecatedInternalID": "288"
|
||||
},
|
||||
"annotations": {
|
||||
"grafana.app/createdBy": "user:eex2ofwuj0agwd",
|
||||
"grafana.app/updatedBy": "user:eex2ofwuj0agwd",
|
||||
"grafana.app/updatedTimestamp": "2025-11-28T10:15:06Z"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations \u0026 Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 288,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "gdev-testdata"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"showValues": false,
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "12.4.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {},
|
||||
"queryType": "randomWalk"
|
||||
},
|
||||
{
|
||||
"datasource": {},
|
||||
"queryType": "randomWalk"
|
||||
}
|
||||
],
|
||||
"title": "New panel",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"schemaVersion": 42,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "browser",
|
||||
"title": "Panel ds inheritance ",
|
||||
"uid": "ad5vfcn",
|
||||
"version": 2
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
{
|
||||
"kind": "Dashboard",
|
||||
"apiVersion": "dashboard.grafana.app/v2alpha1",
|
||||
"metadata": {
|
||||
"name": "ad5vfcn",
|
||||
"namespace": "default",
|
||||
"uid": "dlMZZl6GndU8gJLUQSmgZxXBPCNXyXhNBeQJhHXl0r4X",
|
||||
"resourceVersion": "2",
|
||||
"generation": 2,
|
||||
"creationTimestamp": "2025-11-28T10:14:21Z",
|
||||
"labels": {
|
||||
"grafana.app/deprecatedInternalID": "288"
|
||||
},
|
||||
"annotations": {
|
||||
"grafana.app/createdBy": "user:eex2ofwuj0agwd",
|
||||
"grafana.app/updatedBy": "user:eex2ofwuj0agwd",
|
||||
"grafana.app/updatedTimestamp": "2025-11-28T10:15:06Z"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"annotations": [
|
||||
{
|
||||
"kind": "AnnotationQuery",
|
||||
"spec": {
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"query": {
|
||||
"kind": "grafana",
|
||||
"spec": {}
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations \u0026 Alerts",
|
||||
"builtIn": true,
|
||||
"legacyOptions": {
|
||||
"type": "dashboard"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"cursorSync": "Off",
|
||||
"editable": true,
|
||||
"elements": {
|
||||
"panel-1": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 1,
|
||||
"title": "New panel",
|
||||
"description": "",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "testdata",
|
||||
"spec": {
|
||||
"queryType": "randomWalk"
|
||||
}
|
||||
},
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "gdev-testdata"
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "testdata",
|
||||
"spec": {
|
||||
"queryType": "randomWalk"
|
||||
}
|
||||
},
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "gdev-testdata"
|
||||
},
|
||||
"refId": "B",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "timeseries",
|
||||
"spec": {
|
||||
"pluginVersion": "12.4.0-pre",
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"value": 0,
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"value": 80,
|
||||
"color": "red"
|
||||
}
|
||||
]
|
||||
},
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"showValues": false,
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
"kind": "GridLayout",
|
||||
"spec": {
|
||||
"items": [
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 12,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-1"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"preload": false,
|
||||
"tags": [],
|
||||
"timeSettings": {
|
||||
"timezone": "browser",
|
||||
"from": "now-6h",
|
||||
"to": "now",
|
||||
"autoRefresh": "",
|
||||
"autoRefreshIntervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"hideTimepicker": false,
|
||||
"fiscalYearStartMonth": 0
|
||||
},
|
||||
"title": "Panel ds inheritance ",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
{
|
||||
"kind": "Dashboard",
|
||||
"apiVersion": "dashboard.grafana.app/v2beta1",
|
||||
"metadata": {
|
||||
"name": "ad5vfcn",
|
||||
"namespace": "default",
|
||||
"uid": "dlMZZl6GndU8gJLUQSmgZxXBPCNXyXhNBeQJhHXl0r4X",
|
||||
"resourceVersion": "2",
|
||||
"generation": 2,
|
||||
"creationTimestamp": "2025-11-28T10:14:21Z",
|
||||
"labels": {
|
||||
"grafana.app/deprecatedInternalID": "288"
|
||||
},
|
||||
"annotations": {
|
||||
"grafana.app/createdBy": "user:eex2ofwuj0agwd",
|
||||
"grafana.app/updatedBy": "user:eex2ofwuj0agwd",
|
||||
"grafana.app/updatedTimestamp": "2025-11-28T10:15:06Z"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"annotations": [
|
||||
{
|
||||
"kind": "AnnotationQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "grafana",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "-- Grafana --"
|
||||
},
|
||||
"spec": {}
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations \u0026 Alerts",
|
||||
"builtIn": true,
|
||||
"legacyOptions": {
|
||||
"type": "dashboard"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"cursorSync": "Off",
|
||||
"editable": true,
|
||||
"elements": {
|
||||
"panel-1": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 1,
|
||||
"title": "New panel",
|
||||
"description": "",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "testdata",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "gdev-testdata"
|
||||
},
|
||||
"spec": {
|
||||
"queryType": "randomWalk"
|
||||
}
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "DataQuery",
|
||||
"group": "testdata",
|
||||
"version": "v0",
|
||||
"datasource": {
|
||||
"name": "gdev-testdata"
|
||||
},
|
||||
"spec": {
|
||||
"queryType": "randomWalk"
|
||||
}
|
||||
},
|
||||
"refId": "B",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "VizConfig",
|
||||
"group": "timeseries",
|
||||
"version": "12.4.0-pre",
|
||||
"spec": {
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"value": 0,
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"value": 80,
|
||||
"color": "red"
|
||||
}
|
||||
]
|
||||
},
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"showValues": false,
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
"kind": "GridLayout",
|
||||
"spec": {
|
||||
"items": [
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 12,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-1"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"preload": false,
|
||||
"tags": [],
|
||||
"timeSettings": {
|
||||
"timezone": "browser",
|
||||
"from": "now-6h",
|
||||
"to": "now",
|
||||
"autoRefresh": "",
|
||||
"autoRefreshIntervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"hideTimepicker": false,
|
||||
"fiscalYearStartMonth": 0
|
||||
},
|
||||
"title": "Panel ds inheritance ",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v1beta1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,640 +0,0 @@
|
||||
{
|
||||
"kind": "DashboardWithAccessInfo",
|
||||
"apiVersion": "dashboard.grafana.app/v0alpha1",
|
||||
"metadata": {
|
||||
"name": "value-mapping-test",
|
||||
"namespace": "default",
|
||||
"uid": "value-mapping-test",
|
||||
"resourceVersion": "1765384157199094",
|
||||
"generation": 2,
|
||||
"creationTimestamp": "2025-11-19T20:09:28Z",
|
||||
"labels": {
|
||||
"grafana.app/deprecatedInternalID": "646372978987008"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations \u0026 Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "Test dashboard for all value mapping types and override matcher types",
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"description": "Panel with ValueMap mapping type - maps specific text values to colors and display text",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"options": {
|
||||
"critical": {
|
||||
"color": "red",
|
||||
"index": 0,
|
||||
"text": "Critical!"
|
||||
},
|
||||
"ok": {
|
||||
"color": "green",
|
||||
"index": 2,
|
||||
"text": "OK"
|
||||
},
|
||||
"warning": {
|
||||
"color": "orange",
|
||||
"index": 1,
|
||||
"text": "Warning"
|
||||
}
|
||||
},
|
||||
"type": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "status"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 100
|
||||
},
|
||||
{
|
||||
"id": "custom.align",
|
||||
"value": "center"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {},
|
||||
"pluginVersion": "",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "up",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "ValueMap Example",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"description": "Panel with RangeMap mapping type - maps numerical ranges to colors and display text",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"options": {
|
||||
"from": 0,
|
||||
"result": {
|
||||
"color": "green",
|
||||
"index": 0,
|
||||
"text": "Low"
|
||||
},
|
||||
"to": 50
|
||||
},
|
||||
"type": "range"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"from": 50,
|
||||
"result": {
|
||||
"color": "orange",
|
||||
"index": 1,
|
||||
"text": "Medium"
|
||||
},
|
||||
"to": 80
|
||||
},
|
||||
"type": "range"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"from": 80,
|
||||
"result": {
|
||||
"color": "red",
|
||||
"index": 2,
|
||||
"text": "High"
|
||||
},
|
||||
"to": 100
|
||||
},
|
||||
"type": "range"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byRegexp",
|
||||
"options": "/^cpu_/"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "percent"
|
||||
},
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {},
|
||||
"pluginVersion": "",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "cpu_usage_percent",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "RangeMap Example",
|
||||
"type": "gauge"
|
||||
},
|
||||
{
|
||||
"description": "Panel with RegexMap mapping type - maps values matching regex patterns to colors",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"options": {
|
||||
"pattern": "/^error.*/",
|
||||
"result": {
|
||||
"color": "red",
|
||||
"index": 0,
|
||||
"text": "Error"
|
||||
}
|
||||
},
|
||||
"type": "regex"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"pattern": "/^warn.*/",
|
||||
"result": {
|
||||
"color": "orange",
|
||||
"index": 1,
|
||||
"text": "Warning"
|
||||
}
|
||||
},
|
||||
"type": "regex"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"pattern": "/^info.*/",
|
||||
"result": {
|
||||
"color": "blue",
|
||||
"index": 2,
|
||||
"text": "Info"
|
||||
}
|
||||
},
|
||||
"type": "regex"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byType",
|
||||
"options": "string"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"type": "color-text"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 8
|
||||
},
|
||||
"id": 3,
|
||||
"options": {},
|
||||
"pluginVersion": "",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "log_level",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "RegexMap Example",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"description": "Panel with SpecialValueMap mapping type - maps special values like null, NaN, true, false to display text",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"options": {
|
||||
"match": "null",
|
||||
"result": {
|
||||
"color": "gray",
|
||||
"index": 0,
|
||||
"text": "No Data"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"match": "nan",
|
||||
"result": {
|
||||
"color": "gray",
|
||||
"index": 1,
|
||||
"text": "Not a Number"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"match": "null+nan",
|
||||
"result": {
|
||||
"color": "gray",
|
||||
"index": 2,
|
||||
"text": "N/A"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"match": "true",
|
||||
"result": {
|
||||
"color": "green",
|
||||
"index": 3,
|
||||
"text": "Yes"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"match": "false",
|
||||
"result": {
|
||||
"color": "red",
|
||||
"index": 4,
|
||||
"text": "No"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"match": "empty",
|
||||
"result": {
|
||||
"color": "gray",
|
||||
"index": 5,
|
||||
"text": "Empty"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byFrameRefID",
|
||||
"options": "A"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"fixedColor": "blue",
|
||||
"mode": "fixed"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 8
|
||||
},
|
||||
"id": 4,
|
||||
"options": {},
|
||||
"pluginVersion": "",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "some_metric",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "SpecialValueMap Example",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"description": "Panel with all mapping types combined - demonstrates mixing different mapping types and multiple override matchers",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"options": {
|
||||
"failure": {
|
||||
"color": "red",
|
||||
"index": 1,
|
||||
"text": "Failure"
|
||||
},
|
||||
"success": {
|
||||
"color": "green",
|
||||
"index": 0,
|
||||
"text": "Success"
|
||||
}
|
||||
},
|
||||
"type": "value"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"from": 0,
|
||||
"result": {
|
||||
"color": "blue",
|
||||
"index": 2,
|
||||
"text": "In Range"
|
||||
},
|
||||
"to": 100
|
||||
},
|
||||
"type": "range"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"pattern": "/^[A-Z]{3}-\\d+$/",
|
||||
"result": {
|
||||
"color": "purple",
|
||||
"index": 3,
|
||||
"text": "ID Format"
|
||||
}
|
||||
},
|
||||
"type": "regex"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"match": "null",
|
||||
"result": {
|
||||
"color": "gray",
|
||||
"index": 4,
|
||||
"text": "Missing"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "status"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 120
|
||||
},
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"type": "color-background"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byRegexp",
|
||||
"options": "/^value_/"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "short"
|
||||
},
|
||||
{
|
||||
"id": "min",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"id": "max",
|
||||
"value": 100
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byType",
|
||||
"options": "number"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
},
|
||||
{
|
||||
"id": "thresholds",
|
||||
"value": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "yellow",
|
||||
"value": 50
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byFrameRefID",
|
||||
"options": "B"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "displayName",
|
||||
"value": "Secondary Query"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byValue",
|
||||
"options": {
|
||||
"op": "gte",
|
||||
"reducer": "allIsNull",
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.hidden",
|
||||
"value": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 16
|
||||
},
|
||||
"id": 5,
|
||||
"options": {},
|
||||
"pluginVersion": "",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "combined_metric",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "secondary_metric",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"title": "Combined Mappings and Overrides Example",
|
||||
"type": "table"
|
||||
},
|
||||
{
|
||||
"description": "Panel with override that has empty properties array - tests conversion of overrides without any property modifications",
|
||||
"fieldConfig": {
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "field_with_empty_override"
|
||||
},
|
||||
"properties": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 24
|
||||
},
|
||||
"id": 6,
|
||||
"options": {},
|
||||
"pluginVersion": "",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "empty_override_metric",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Empty Properties Override Example",
|
||||
"type": "stat"
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"refresh": "",
|
||||
"schemaVersion": 42,
|
||||
"tags": [
|
||||
"value-mapping",
|
||||
"overrides",
|
||||
"test"
|
||||
],
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
]
|
||||
},
|
||||
"timezone": "browser",
|
||||
"title": "Value Mapping and Overrides Test"
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v2beta1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,640 +0,0 @@
|
||||
{
|
||||
"kind": "DashboardWithAccessInfo",
|
||||
"apiVersion": "dashboard.grafana.app/v1beta1",
|
||||
"metadata": {
|
||||
"name": "value-mapping-test",
|
||||
"namespace": "default",
|
||||
"uid": "value-mapping-test",
|
||||
"resourceVersion": "1765384157199094",
|
||||
"generation": 2,
|
||||
"creationTimestamp": "2025-11-19T20:09:28Z",
|
||||
"labels": {
|
||||
"grafana.app/deprecatedInternalID": "646372978987008"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations \u0026 Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "Test dashboard for all value mapping types and override matcher types",
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"description": "Panel with ValueMap mapping type - maps specific text values to colors and display text",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"options": {
|
||||
"critical": {
|
||||
"color": "red",
|
||||
"index": 0,
|
||||
"text": "Critical!"
|
||||
},
|
||||
"ok": {
|
||||
"color": "green",
|
||||
"index": 2,
|
||||
"text": "OK"
|
||||
},
|
||||
"warning": {
|
||||
"color": "orange",
|
||||
"index": 1,
|
||||
"text": "Warning"
|
||||
}
|
||||
},
|
||||
"type": "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "status"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 100
|
||||
},
|
||||
{
|
||||
"id": "custom.align",
|
||||
"value": "center"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {},
|
||||
"pluginVersion": "",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "up",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "ValueMap Example",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"description": "Panel with RangeMap mapping type - maps numerical ranges to colors and display text",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"options": {
|
||||
"from": 0,
|
||||
"result": {
|
||||
"color": "green",
|
||||
"index": 0,
|
||||
"text": "Low"
|
||||
},
|
||||
"to": 50
|
||||
},
|
||||
"type": "range"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"from": 50,
|
||||
"result": {
|
||||
"color": "orange",
|
||||
"index": 1,
|
||||
"text": "Medium"
|
||||
},
|
||||
"to": 80
|
||||
},
|
||||
"type": "range"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"from": 80,
|
||||
"result": {
|
||||
"color": "red",
|
||||
"index": 2,
|
||||
"text": "High"
|
||||
},
|
||||
"to": 100
|
||||
},
|
||||
"type": "range"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byRegexp",
|
||||
"options": "/^cpu_/"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "percent"
|
||||
},
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {},
|
||||
"pluginVersion": "",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "cpu_usage_percent",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "RangeMap Example",
|
||||
"type": "gauge"
|
||||
},
|
||||
{
|
||||
"description": "Panel with RegexMap mapping type - maps values matching regex patterns to colors",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"options": {
|
||||
"pattern": "/^error.*/",
|
||||
"result": {
|
||||
"color": "red",
|
||||
"index": 0,
|
||||
"text": "Error"
|
||||
}
|
||||
},
|
||||
"type": "regex"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"pattern": "/^warn.*/",
|
||||
"result": {
|
||||
"color": "orange",
|
||||
"index": 1,
|
||||
"text": "Warning"
|
||||
}
|
||||
},
|
||||
"type": "regex"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"pattern": "/^info.*/",
|
||||
"result": {
|
||||
"color": "blue",
|
||||
"index": 2,
|
||||
"text": "Info"
|
||||
}
|
||||
},
|
||||
"type": "regex"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byType",
|
||||
"options": "string"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"type": "color-text"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 8
|
||||
},
|
||||
"id": 3,
|
||||
"options": {},
|
||||
"pluginVersion": "",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "log_level",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "RegexMap Example",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"description": "Panel with SpecialValueMap mapping type - maps special values like null, NaN, true, false to display text",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"options": {
|
||||
"match": "null",
|
||||
"result": {
|
||||
"color": "gray",
|
||||
"index": 0,
|
||||
"text": "No Data"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"match": "nan",
|
||||
"result": {
|
||||
"color": "gray",
|
||||
"index": 1,
|
||||
"text": "Not a Number"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"match": "null+nan",
|
||||
"result": {
|
||||
"color": "gray",
|
||||
"index": 2,
|
||||
"text": "N/A"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"match": "true",
|
||||
"result": {
|
||||
"color": "green",
|
||||
"index": 3,
|
||||
"text": "Yes"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"match": "false",
|
||||
"result": {
|
||||
"color": "red",
|
||||
"index": 4,
|
||||
"text": "No"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"match": "empty",
|
||||
"result": {
|
||||
"color": "gray",
|
||||
"index": 5,
|
||||
"text": "Empty"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byFrameRefID",
|
||||
"options": "A"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"fixedColor": "blue",
|
||||
"mode": "fixed"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 8
|
||||
},
|
||||
"id": 4,
|
||||
"options": {},
|
||||
"pluginVersion": "",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "some_metric",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "SpecialValueMap Example",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"description": "Panel with all mapping types combined - demonstrates mixing different mapping types and multiple override matchers",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"options": {
|
||||
"failure": {
|
||||
"color": "red",
|
||||
"index": 1,
|
||||
"text": "Failure"
|
||||
},
|
||||
"success": {
|
||||
"color": "green",
|
||||
"index": 0,
|
||||
"text": "Success"
|
||||
}
|
||||
},
|
||||
"type": "value"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"from": 0,
|
||||
"result": {
|
||||
"color": "blue",
|
||||
"index": 2,
|
||||
"text": "In Range"
|
||||
},
|
||||
"to": 100
|
||||
},
|
||||
"type": "range"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"pattern": "/^[A-Z]{3}-\\d+$/",
|
||||
"result": {
|
||||
"color": "purple",
|
||||
"index": 3,
|
||||
"text": "ID Format"
|
||||
}
|
||||
},
|
||||
"type": "regex"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"match": "null",
|
||||
"result": {
|
||||
"color": "gray",
|
||||
"index": 4,
|
||||
"text": "Missing"
|
||||
}
|
||||
},
|
||||
"type": "special"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "status"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 120
|
||||
},
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"type": "color-background"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byRegexp",
|
||||
"options": "/^value_/"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "short"
|
||||
},
|
||||
{
|
||||
"id": "min",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"id": "max",
|
||||
"value": 100
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byType",
|
||||
"options": "number"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
},
|
||||
{
|
||||
"id": "thresholds",
|
||||
"value": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "yellow",
|
||||
"value": 50
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byFrameRefID",
|
||||
"options": "B"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "displayName",
|
||||
"value": "Secondary Query"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byValue",
|
||||
"options": {
|
||||
"op": "gte",
|
||||
"reducer": "allIsNull",
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.hidden",
|
||||
"value": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 16
|
||||
},
|
||||
"id": 5,
|
||||
"options": {},
|
||||
"pluginVersion": "",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "combined_metric",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "secondary_metric",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"title": "Combined Mappings and Overrides Example",
|
||||
"type": "table"
|
||||
},
|
||||
{
|
||||
"description": "Panel with override that has empty properties array - tests conversion of overrides without any property modifications",
|
||||
"fieldConfig": {
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "field_with_empty_override"
|
||||
},
|
||||
"properties": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 24
|
||||
},
|
||||
"id": 6,
|
||||
"options": {},
|
||||
"pluginVersion": "",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"expr": "empty_override_metric",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Empty Properties Override Example",
|
||||
"type": "stat"
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"refresh": "",
|
||||
"schemaVersion": 42,
|
||||
"tags": [
|
||||
"value-mapping",
|
||||
"overrides",
|
||||
"test"
|
||||
],
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
]
|
||||
},
|
||||
"timezone": "browser",
|
||||
"title": "Value Mapping and Overrides Test"
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v2beta1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,850 +0,0 @@
|
||||
{
|
||||
"kind": "DashboardWithAccessInfo",
|
||||
"apiVersion": "dashboard.grafana.app/v2alpha1",
|
||||
"metadata": {
|
||||
"name": "value-mapping-test",
|
||||
"namespace": "default",
|
||||
"uid": "value-mapping-test",
|
||||
"resourceVersion": "1765384157199094",
|
||||
"generation": 2,
|
||||
"creationTimestamp": "2025-11-19T20:09:28Z",
|
||||
"labels": {
|
||||
"grafana.app/deprecatedInternalID": "646372978987008"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"annotations": [
|
||||
{
|
||||
"kind": "AnnotationQuery",
|
||||
"spec": {
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"query": {
|
||||
"kind": "grafana",
|
||||
"spec": {}
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations \u0026 Alerts",
|
||||
"builtIn": true,
|
||||
"legacyOptions": {
|
||||
"type": "dashboard"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"cursorSync": "Off",
|
||||
"description": "Test dashboard for all value mapping types and override matcher types",
|
||||
"editable": true,
|
||||
"elements": {
|
||||
"panel-1": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 1,
|
||||
"title": "ValueMap Example",
|
||||
"description": "Panel with ValueMap mapping type - maps specific text values to colors and display text",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "prometheus",
|
||||
"spec": {
|
||||
"expr": "up"
|
||||
}
|
||||
},
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "stat",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"type": "value",
|
||||
"options": {
|
||||
"critical": {
|
||||
"text": "Critical!",
|
||||
"color": "red",
|
||||
"index": 0
|
||||
},
|
||||
"ok": {
|
||||
"text": "OK",
|
||||
"color": "green",
|
||||
"index": 2
|
||||
},
|
||||
"warning": {
|
||||
"text": "Warning",
|
||||
"color": "orange",
|
||||
"index": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "status"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 100
|
||||
},
|
||||
{
|
||||
"id": "custom.align",
|
||||
"value": "center"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-2": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 2,
|
||||
"title": "RangeMap Example",
|
||||
"description": "Panel with RangeMap mapping type - maps numerical ranges to colors and display text",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "prometheus",
|
||||
"spec": {
|
||||
"expr": "cpu_usage_percent"
|
||||
}
|
||||
},
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "gauge",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"type": "range",
|
||||
"options": {
|
||||
"from": 0,
|
||||
"to": 50,
|
||||
"result": {
|
||||
"text": "Low",
|
||||
"color": "green",
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "range",
|
||||
"options": {
|
||||
"from": 50,
|
||||
"to": 80,
|
||||
"result": {
|
||||
"text": "Medium",
|
||||
"color": "orange",
|
||||
"index": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "range",
|
||||
"options": {
|
||||
"from": 80,
|
||||
"to": 100,
|
||||
"result": {
|
||||
"text": "High",
|
||||
"color": "red",
|
||||
"index": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byRegexp",
|
||||
"options": "/^cpu_/"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "percent"
|
||||
},
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-3": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 3,
|
||||
"title": "RegexMap Example",
|
||||
"description": "Panel with RegexMap mapping type - maps values matching regex patterns to colors",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "prometheus",
|
||||
"spec": {
|
||||
"expr": "log_level"
|
||||
}
|
||||
},
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "stat",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "/^error.*/",
|
||||
"result": {
|
||||
"text": "Error",
|
||||
"color": "red",
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "/^warn.*/",
|
||||
"result": {
|
||||
"text": "Warning",
|
||||
"color": "orange",
|
||||
"index": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "/^info.*/",
|
||||
"result": {
|
||||
"text": "Info",
|
||||
"color": "blue",
|
||||
"index": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byType",
|
||||
"options": "string"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"type": "color-text"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-4": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 4,
|
||||
"title": "SpecialValueMap Example",
|
||||
"description": "Panel with SpecialValueMap mapping type - maps special values like null, NaN, true, false to display text",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "prometheus",
|
||||
"spec": {
|
||||
"expr": "some_metric"
|
||||
}
|
||||
},
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "stat",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "null",
|
||||
"result": {
|
||||
"text": "No Data",
|
||||
"color": "gray",
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "nan",
|
||||
"result": {
|
||||
"text": "Not a Number",
|
||||
"color": "gray",
|
||||
"index": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "null+nan",
|
||||
"result": {
|
||||
"text": "N/A",
|
||||
"color": "gray",
|
||||
"index": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "true",
|
||||
"result": {
|
||||
"text": "Yes",
|
||||
"color": "green",
|
||||
"index": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "false",
|
||||
"result": {
|
||||
"text": "No",
|
||||
"color": "red",
|
||||
"index": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "empty",
|
||||
"result": {
|
||||
"text": "Empty",
|
||||
"color": "gray",
|
||||
"index": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byFrameRefID",
|
||||
"options": "A"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"fixedColor": "blue",
|
||||
"mode": "fixed"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-5": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 5,
|
||||
"title": "Combined Mappings and Overrides Example",
|
||||
"description": "Panel with all mapping types combined - demonstrates mixing different mapping types and multiple override matchers",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "prometheus",
|
||||
"spec": {
|
||||
"expr": "combined_metric"
|
||||
}
|
||||
},
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "prometheus",
|
||||
"spec": {
|
||||
"expr": "secondary_metric"
|
||||
}
|
||||
},
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"refId": "B",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "table",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"mappings": [
|
||||
{
|
||||
"type": "value",
|
||||
"options": {
|
||||
"failure": {
|
||||
"text": "Failure",
|
||||
"color": "red",
|
||||
"index": 1
|
||||
},
|
||||
"success": {
|
||||
"text": "Success",
|
||||
"color": "green",
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "range",
|
||||
"options": {
|
||||
"from": 0,
|
||||
"to": 100,
|
||||
"result": {
|
||||
"text": "In Range",
|
||||
"color": "blue",
|
||||
"index": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "regex",
|
||||
"options": {
|
||||
"pattern": "/^[A-Z]{3}-\\d+$/",
|
||||
"result": {
|
||||
"text": "ID Format",
|
||||
"color": "purple",
|
||||
"index": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "special",
|
||||
"options": {
|
||||
"match": "null",
|
||||
"result": {
|
||||
"text": "Missing",
|
||||
"color": "gray",
|
||||
"index": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "status"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 120
|
||||
},
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"type": "color-background"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byRegexp",
|
||||
"options": "/^value_/"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "short"
|
||||
},
|
||||
{
|
||||
"id": "min",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"id": "max",
|
||||
"value": 100
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byType",
|
||||
"options": "number"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
},
|
||||
{
|
||||
"id": "thresholds",
|
||||
"value": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "yellow",
|
||||
"value": 50
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byFrameRefID",
|
||||
"options": "B"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "displayName",
|
||||
"value": "Secondary Query"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byValue",
|
||||
"options": {
|
||||
"op": "gte",
|
||||
"reducer": "allIsNull",
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.hidden",
|
||||
"value": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-6": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"id": 6,
|
||||
"title": "Empty Properties Override Example",
|
||||
"description": "Panel with override that has empty properties array - tests conversion of overrides without any property modifications",
|
||||
"links": [],
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"query": {
|
||||
"kind": "prometheus",
|
||||
"spec": {
|
||||
"expr": "empty_override_metric"
|
||||
}
|
||||
},
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus-uid"
|
||||
},
|
||||
"refId": "A",
|
||||
"hidden": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"transformations": [],
|
||||
"queryOptions": {}
|
||||
}
|
||||
},
|
||||
"vizConfig": {
|
||||
"kind": "stat",
|
||||
"spec": {
|
||||
"pluginVersion": "",
|
||||
"options": {},
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "field_with_empty_override"
|
||||
},
|
||||
"properties": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
"kind": "GridLayout",
|
||||
"spec": {
|
||||
"items": [
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 12,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-1"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 12,
|
||||
"y": 0,
|
||||
"width": 12,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-2"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 0,
|
||||
"y": 8,
|
||||
"width": 12,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-3"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 12,
|
||||
"y": 8,
|
||||
"width": 12,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-4"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 0,
|
||||
"y": 16,
|
||||
"width": 24,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-5"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "GridLayoutItem",
|
||||
"spec": {
|
||||
"x": 0,
|
||||
"y": 24,
|
||||
"width": 12,
|
||||
"height": 8,
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-6"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"preload": false,
|
||||
"tags": [
|
||||
"value-mapping",
|
||||
"overrides",
|
||||
"test"
|
||||
],
|
||||
"timeSettings": {
|
||||
"timezone": "browser",
|
||||
"from": "now-6h",
|
||||
"to": "now",
|
||||
"autoRefresh": "",
|
||||
"autoRefreshIntervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"hideTimepicker": false,
|
||||
"fiscalYearStartMonth": 0
|
||||
},
|
||||
"title": "Value Mapping and Overrides Test",
|
||||
"variables": []
|
||||
},
|
||||
"status": {
|
||||
"conversion": {
|
||||
"failed": false,
|
||||
"storedVersion": "v2beta1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package conversion
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
@@ -80,57 +79,5 @@ func ConvertDashboard_V0_to_V1beta1(in *dashv0.Dashboard, out *dashv1.Dashboard,
|
||||
return schemaversion.NewMigrationError(err.Error(), schemaversion.GetSchemaVersion(in.Spec.Object), schemaversion.LATEST_VERSION, "Convert_V0_to_V1")
|
||||
}
|
||||
|
||||
// Normalize template variable datasources from string to object format
|
||||
// This handles legacy dashboards where query variables have datasource: "$datasource" (string)
|
||||
// instead of datasource: { uid: "$datasource" } (object)
|
||||
// our migration pipeline in v36 doesn't address because this was not addressed historically
|
||||
// in DashboardMigrator - see public/app/features/dashboard/state/DashboardMigrator.ts#L607
|
||||
// Which means that we have schemaVersion: 42 dashboards where datasource variable references are still strings
|
||||
normalizeTemplateVariableDatasources(out.Spec.Object)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// normalizeTemplateVariableDatasources converts template variable string datasources to object format.
|
||||
// Legacy dashboards may have query variables with datasource: "$datasource" (string).
|
||||
// This normalizes them to datasource: { uid: "$datasource" } for consistent V1→V2 conversion.
|
||||
func normalizeTemplateVariableDatasources(dashboard map[string]interface{}) {
|
||||
templating, ok := dashboard["templating"].(map[string]interface{})
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
list, ok := templating["list"].([]interface{})
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
for _, variable := range list {
|
||||
varMap, ok := variable.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
varType, _ := varMap["type"].(string)
|
||||
if varType != "query" {
|
||||
continue
|
||||
}
|
||||
|
||||
ds := varMap["datasource"]
|
||||
if dsStr, ok := ds.(string); ok && isTemplateVariableRef(dsStr) {
|
||||
// Convert string template variable reference to object format
|
||||
varMap["datasource"] = map[string]interface{}{
|
||||
"uid": dsStr,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// isTemplateVariableRef checks if a string is a Grafana template variable reference.
|
||||
// Template variables can be in the form: $varname or ${varname}
|
||||
func isTemplateVariableRef(s string) bool {
|
||||
if s == "" {
|
||||
return false
|
||||
}
|
||||
return strings.HasPrefix(s, "$") || strings.HasPrefix(s, "${")
|
||||
}
|
||||
|
||||
@@ -1185,10 +1185,6 @@ func buildQueryVariable(ctx context.Context, varMap map[string]interface{}, comm
|
||||
// If no UID and no type, use default
|
||||
datasourceType = getDefaultDatasourceType(ctx, dsIndexProvider)
|
||||
}
|
||||
} else if dsStr, ok := datasource.(string); ok && isTemplateVariable(dsStr) {
|
||||
// Handle datasource variable reference (e.g., "$datasource")
|
||||
// Only process template variables - other string values are not supported in V2 format
|
||||
datasourceUID = dsStr
|
||||
} else {
|
||||
datasourceType = getDefaultDatasourceType(ctx, dsIndexProvider)
|
||||
}
|
||||
@@ -1536,10 +1532,6 @@ func buildAdhocVariable(ctx context.Context, varMap map[string]interface{}, comm
|
||||
// If no UID and no type, use default
|
||||
datasourceType = getDefaultDatasourceType(ctx, dsIndexProvider)
|
||||
}
|
||||
} else if dsStr, ok := datasource.(string); ok && isTemplateVariable(dsStr) {
|
||||
// Handle datasource variable reference (e.g., "$datasource")
|
||||
// Only process template variables - other string values are not supported in V2 format
|
||||
datasourceUID = dsStr
|
||||
} else {
|
||||
datasourceType = getDefaultDatasourceType(ctx, dsIndexProvider)
|
||||
}
|
||||
@@ -1717,10 +1709,6 @@ func buildGroupByVariable(ctx context.Context, varMap map[string]interface{}, co
|
||||
|
||||
// Resolve Grafana datasource UID when type is "datasource" and UID is empty
|
||||
datasourceUID = resolveGrafanaDatasourceUID(datasourceType, datasourceUID)
|
||||
} else if dsStr, ok := datasource.(string); ok && isTemplateVariable(dsStr) {
|
||||
// Handle datasource variable reference (e.g., "$datasource")
|
||||
// Only process template variables - other string values are not supported in V2 format
|
||||
datasourceUID = dsStr
|
||||
} else {
|
||||
datasourceType = getDefaultDatasourceType(ctx, dsIndexProvider)
|
||||
}
|
||||
@@ -2018,28 +2006,6 @@ func transformPanelQueries(ctx context.Context, panelMap map[string]interface{},
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure each target has a non-empty refId. We only fill missing refIds;
|
||||
existingRefIds := make(map[string]bool)
|
||||
for _, target := range targets {
|
||||
if targetMap, ok := target.(map[string]interface{}); ok {
|
||||
if refId := schemaversion.GetStringValue(targetMap, "refId"); refId != "" {
|
||||
existingRefIds[refId] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, target := range targets {
|
||||
targetMap, ok := target.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
refId := schemaversion.GetStringValue(targetMap, "refId")
|
||||
if refId == "" {
|
||||
refId = nextAvailableRefId(existingRefIds)
|
||||
targetMap["refId"] = refId
|
||||
existingRefIds[refId] = true
|
||||
}
|
||||
}
|
||||
|
||||
queries := make([]dashv2alpha1.DashboardPanelQueryKind, 0, len(targets))
|
||||
|
||||
for _, target := range targets {
|
||||
@@ -2052,27 +2018,6 @@ func transformPanelQueries(ctx context.Context, panelMap map[string]interface{},
|
||||
return queries
|
||||
}
|
||||
|
||||
// nextAvailableRefId returns the next unused refId using the same sequence as the
|
||||
// frontend helper (A, B, ..., Z, AA, AB, ...).
|
||||
func nextAvailableRefId(existing map[string]bool) string {
|
||||
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
|
||||
var refIdFromIndex func(num int) string
|
||||
refIdFromIndex = func(num int) string {
|
||||
if num < len(letters) {
|
||||
return string(letters[num])
|
||||
}
|
||||
return refIdFromIndex(num/len(letters)-1) + string(letters[num%len(letters)])
|
||||
}
|
||||
|
||||
for i := 0; ; i++ {
|
||||
refId := refIdFromIndex(i)
|
||||
if !existing[refId] {
|
||||
return refId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func transformSingleQuery(ctx context.Context, targetMap map[string]interface{}, panelDatasource *dashv2alpha1.DashboardDataSourceRef, dsIndexProvider schemaversion.DataSourceIndexProvider) dashv2alpha1.DashboardPanelQueryKind {
|
||||
refId := schemaversion.GetStringValue(targetMap, "refId", "A")
|
||||
if refId == "" {
|
||||
@@ -2308,24 +2253,20 @@ func buildVizConfig(panelMap map[string]interface{}) dashv2alpha1.DashboardVizCo
|
||||
// We check two cases:
|
||||
// 1. Panel already has autoMigrateFrom set (from v0→v1 migration) - panel type already converted
|
||||
// 2. Panel type is a known Angular panel - need to convert type AND set autoMigrateFrom
|
||||
// 3. Panel has original options - need to set autoMigrateFrom and originalOptions
|
||||
autoMigrateFrom, hasAutoMigrateFrom := panelMap["autoMigrateFrom"].(string)
|
||||
originalOptions := extractAngularOptions(panelMap)
|
||||
|
||||
if !hasAutoMigrateFrom || autoMigrateFrom == "" {
|
||||
// Check if panel type is an Angular type that needs migration
|
||||
if newType := getAngularPanelMigration(panelType, panelMap); newType != "" {
|
||||
autoMigrateFrom = panelType // Original Angular type
|
||||
panelType = newType // New modern type
|
||||
} else if len(originalOptions) > 0 {
|
||||
autoMigrateFrom = panelType
|
||||
}
|
||||
}
|
||||
|
||||
if autoMigrateFrom != "" {
|
||||
options["__angularMigration"] = map[string]interface{}{
|
||||
"autoMigrateFrom": autoMigrateFrom,
|
||||
"originalOptions": originalOptions,
|
||||
"originalOptions": extractAngularOptions(panelMap),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -210,48 +210,6 @@ func TestV1beta1ToV2alpha1(t *testing.T) {
|
||||
assert.Equal(t, "", query.Spec.Query.Kind, "Query kind should be empty when datasource is empty object {}")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "missing refIds are assigned while existing refIds are preserved",
|
||||
createV1beta1: func() *dashv1.Dashboard {
|
||||
return &dashv1.Dashboard{
|
||||
Spec: dashv1.DashboardSpec{
|
||||
Object: map[string]interface{}{
|
||||
"title": "Test Dashboard",
|
||||
"panels": []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": 1,
|
||||
"type": "bargauge",
|
||||
"targets": []interface{}{
|
||||
map[string]interface{}{
|
||||
"refId": "",
|
||||
"scenarioId": "random_walk",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"refId": "",
|
||||
"scenarioId": "random_walk",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
validateV2alpha1: func(t *testing.T, v2alpha1 *dashv2alpha1.Dashboard) {
|
||||
require.NotNil(t, v2alpha1.Spec.Elements["panel-1"])
|
||||
panel := v2alpha1.Spec.Elements["panel-1"].PanelKind
|
||||
require.NotNil(t, panel)
|
||||
|
||||
require.Len(t, panel.Spec.Data.Spec.Queries, 3)
|
||||
assert.Equal(t, "B", panel.Spec.Data.Spec.Queries[0].Spec.RefId)
|
||||
assert.Equal(t, "A", panel.Spec.Data.Spec.Queries[1].Spec.RefId)
|
||||
assert.Equal(t, "C", panel.Spec.Data.Spec.Queries[2].Spec.RefId)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
|
||||
@@ -1973,16 +1973,16 @@ func convertFieldConfigOverridesToV1(overrides []dashv2alpha1.DashboardV2alpha1F
|
||||
"options": override.Matcher.Options,
|
||||
}
|
||||
|
||||
properties := make([]map[string]interface{}, 0, len(override.Properties))
|
||||
if len(override.Properties) > 0 {
|
||||
properties := make([]map[string]interface{}, 0, len(override.Properties))
|
||||
for _, prop := range override.Properties {
|
||||
properties = append(properties, map[string]interface{}{
|
||||
"id": prop.Id,
|
||||
"value": prop.Value,
|
||||
})
|
||||
}
|
||||
overrideMap["properties"] = properties
|
||||
}
|
||||
overrideMap["properties"] = properties
|
||||
|
||||
result = append(result, overrideMap)
|
||||
}
|
||||
@@ -2074,9 +2074,11 @@ func convertRegexMapToV1(regexMap *dashv2alpha1.DashboardRegexMap) map[string]in
|
||||
return nil
|
||||
}
|
||||
|
||||
options := map[string]interface{}{
|
||||
"pattern": regexMap.Options.Pattern,
|
||||
"result": convertValueMappingResultToV1(regexMap.Options.Result),
|
||||
options := []map[string]interface{}{
|
||||
{
|
||||
"pattern": regexMap.Options.Pattern,
|
||||
"result": convertValueMappingResultToV1(regexMap.Options.Result),
|
||||
},
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
|
||||
@@ -290,7 +290,6 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"content": "# Graph panel \u003e\u003e Timeseries panel\n\nKnown issues:\n* hiding null/empty series\n* time regions",
|
||||
"datasource": {
|
||||
"type": "grafana-testdata-datasource"
|
||||
},
|
||||
@@ -301,7 +300,15 @@
|
||||
"y": 0
|
||||
},
|
||||
"id": 6,
|
||||
"mode": "markdown",
|
||||
"options": {
|
||||
"code": {
|
||||
"language": "plaintext",
|
||||
"showLineNumbers": false,
|
||||
"showMiniMap": false
|
||||
},
|
||||
"content": "# Graph panel \u003e\u003e Timeseries panel\n\nKnown issues:\n* hiding null/empty series\n* time regions",
|
||||
"mode": "markdown"
|
||||
},
|
||||
"pluginVersion": "11.0.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
|
||||
@@ -654,9 +654,7 @@
|
||||
"text": "prod",
|
||||
"value": "prod"
|
||||
},
|
||||
"datasource": {
|
||||
"uid": "$datasource"
|
||||
},
|
||||
"datasource": "$datasource",
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"label": "cluster",
|
||||
@@ -679,9 +677,7 @@
|
||||
"text": "prod",
|
||||
"value": "prod"
|
||||
},
|
||||
"datasource": {
|
||||
"uid": "$datasource"
|
||||
},
|
||||
"datasource": "$datasource",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "namespace",
|
||||
|
||||
@@ -737,9 +737,7 @@
|
||||
"text": "prod",
|
||||
"value": "prod"
|
||||
},
|
||||
"datasource": {
|
||||
"uid": "$datasource"
|
||||
},
|
||||
"datasource": "$datasource",
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"label": "cluster",
|
||||
@@ -760,9 +758,7 @@
|
||||
"text": "prod",
|
||||
"value": "prod"
|
||||
},
|
||||
"datasource": {
|
||||
"uid": "$datasource"
|
||||
},
|
||||
"datasource": "$datasource",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "namespace",
|
||||
|
||||
@@ -717,9 +717,7 @@
|
||||
"text": "prod",
|
||||
"value": "prod"
|
||||
},
|
||||
"datasource": {
|
||||
"uid": "$datasource"
|
||||
},
|
||||
"datasource": "$datasource",
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"label": "cluster",
|
||||
@@ -741,9 +739,7 @@
|
||||
"text": "prod",
|
||||
"value": "prod"
|
||||
},
|
||||
"datasource": {
|
||||
"uid": "$datasource"
|
||||
},
|
||||
"datasource": "$datasource",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "namespace",
|
||||
|
||||
@@ -2287,8 +2287,8 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kms v0.34.3 h1:QzBOD0sk1bGQVMcZQAHGjtbP1iKZJUyhC6D0I+BTxIE=
|
||||
k8s.io/kms v0.34.3/go.mod h1:s1CFkLG7w9eaTYvctOxosx88fl4spqmixnNpys0JAtM=
|
||||
k8s.io/kube-aggregator v0.34.3 h1:rKsZWTD2As4dKuv+zzdJU0uo5H7bFlAEoSucai4mW6M=
|
||||
k8s.io/kube-aggregator v0.34.3/go.mod h1:d4D8PV2FK4Qlq6u442FSum1tHPhK9tKdKBfH/A3R0I0=
|
||||
k8s.io/kube-aggregator v0.34.2 h1:Nn0Vksj67WHBL2x7bJ6vuxL44RbMTK6uRtXX+3vMVJk=
|
||||
k8s.io/kube-aggregator v0.34.2/go.mod h1:/tp4cc/1p2AvICsS4mjjSJakdrbhcGbRmj0mdHTdR2Q=
|
||||
k8s.io/kube-openapi v0.0.0-20251125145642-4e65d59e963e h1:iW9ChlU0cU16w8MpVYjXk12dqQ4BPFBEgif+ap7/hqQ=
|
||||
k8s.io/kube-openapi v0.0.0-20251125145642-4e65d59e963e/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
|
||||
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
|
||||
|
||||
@@ -24,7 +24,6 @@ require (
|
||||
require (
|
||||
cel.dev/expr v0.25.1 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.1.6 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
|
||||
github.com/apache/arrow-go/v18 v18.4.1 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
@@ -36,21 +35,16 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.38.5 // indirect
|
||||
github.com/aws/smithy-go v1.23.1 // indirect
|
||||
github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/bluele/gcache v0.0.2 // indirect
|
||||
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect
|
||||
github.com/bwmarrin/snowflake v0.3.0 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.6.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/diegoholiveira/jsonlogic/v3 v3.7.4 // indirect
|
||||
github.com/evanphx/json-patch v5.9.11+incompatible // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
@@ -100,7 +94,6 @@ require (
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.284.0 // indirect
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0 // indirect
|
||||
github.com/grafana/grafana/pkg/apiserver v0.0.0 // indirect
|
||||
github.com/grafana/grafana/pkg/semconv v0.0.0-20250804150913-990f1c69ecc2 // indirect
|
||||
github.com/grafana/otel-profiling-go v0.5.1 // indirect
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect
|
||||
github.com/grafana/sqlds/v4 v4.2.7 // indirect
|
||||
@@ -149,15 +142,11 @@ require (
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
|
||||
github.com/nikunjy/rules v1.5.0 // indirect
|
||||
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
|
||||
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/open-feature/go-sdk v1.16.0 // indirect
|
||||
github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.6 // indirect
|
||||
github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.6 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/perimeterx/marshmallow v1.1.5 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
||||
@@ -176,7 +165,6 @@ require (
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.1 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/thomaspoignant/go-feature-flag v1.42.0 // indirect
|
||||
github.com/tjhop/slog-gokit v0.1.5 // indirect
|
||||
github.com/woodsbury/decimal128 v1.4.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
@@ -191,7 +179,6 @@ require (
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.38.0 // indirect
|
||||
go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0 // indirect
|
||||
go.opentelemetry.io/otel v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 // indirect
|
||||
@@ -199,8 +186,6 @@ require (
|
||||
go.opentelemetry.io/otel/sdk v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.39.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/mock v0.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
|
||||
@@ -4,13 +4,9 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||
github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
|
||||
github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@@ -42,18 +38,12 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.38.5 h1:+LVB0xBqEgjQoqr9bGZbRzvg212B
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.38.5/go.mod h1:xoaxeqnnUaZjPjaICgIy5B+MHCSb/ZSOn4MvkFNOUA0=
|
||||
github.com/aws/smithy-go v1.23.1 h1:sLvcH6dfAFwGkHLZ7dGiYF7aK6mg4CgKA/iDKjLDt9M=
|
||||
github.com/aws/smithy-go v1.23.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
|
||||
github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0=
|
||||
github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf h1:TqhNAT4zKbTdLa62d2HDBFdvgSbIGB3eJE8HqhgiL9I=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
||||
github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw=
|
||||
@@ -70,8 +60,6 @@ github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wX
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
||||
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
|
||||
@@ -81,8 +69,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
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/diegoholiveira/jsonlogic/v3 v3.7.4 h1:92HSmB9bwM/o0ZvrCpcvTP2EsPXSkKtAniIr2W/dcIM=
|
||||
github.com/diegoholiveira/jsonlogic/v3 v3.7.4/go.mod h1:OYRb6FSTVmMM+MNQ7ElmMsczyNSepw+OU4Z8emDSi4w=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
|
||||
@@ -233,8 +219,6 @@ github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1 h1:FFcEA01tW+SmuJIuDbHOdgUBL+d
|
||||
github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1/go.mod h1:Oi4anANlCuTCc66jCyqIzfVbgLXFll8Wja+Y4vfANlc=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.284.0 h1:1bK7eWsnPBLUWDcWJWe218Ik5ad0a5JpEL4mH9ry7Ws=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.284.0/go.mod h1:lHPniaSxq3SL5MxDIPy04TYB1jnTp/ivkYO+xn5Rz3E=
|
||||
github.com/grafana/grafana/pkg/semconv v0.0.0-20250804150913-990f1c69ecc2 h1:A65jWgLk4Re28gIuZcpC0aTh71JZ0ey89hKGE9h543s=
|
||||
github.com/grafana/grafana/pkg/semconv v0.0.0-20250804150913-990f1c69ecc2/go.mod h1:2HRzUK/xQEYc+8d5If/XSusMcaYq9IptnBSHACiQcOQ=
|
||||
github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8=
|
||||
github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls=
|
||||
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604 h1:aXfUhVN/Ewfpbko2CCtL65cIiGgwStOo4lWH2b6gw2U=
|
||||
@@ -382,8 +366,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nikunjy/rules v1.5.0 h1:KJDSLOsFhwt7kcXUyZqwkgrQg5YoUwj+TVu6ItCQShw=
|
||||
github.com/nikunjy/rules v1.5.0/go.mod h1:TlZtZdBChrkqi8Lr2AXocme8Z7EsbxtFdDoKeI6neBQ=
|
||||
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=
|
||||
@@ -398,12 +380,6 @@ 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/open-feature/go-sdk v1.16.0 h1:5NCHYv5slvNBIZhYXAzAufo0OI59OACZ5tczVqSE+Tg=
|
||||
github.com/open-feature/go-sdk v1.16.0/go.mod h1:EIF40QcoYT1VbQkMPy2ZJH4kvZeY+qGUXAorzSWgKSo=
|
||||
github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.6 h1:megzzlQGjsRVWDX8oJnLaa5eEcsAHekiL4Uvl3jSAcY=
|
||||
github.com/open-feature/go-sdk-contrib/providers/go-feature-flag v0.2.6/go.mod h1:K1gDKvt76CGFLSUMHUydd5ba2V5Cv69gQZsdbnXhAm8=
|
||||
github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.6 h1:WinefYxeVx5rV0uQmuWbxQf8iACu/JiRubo5w0saToc=
|
||||
github.com/open-feature/go-sdk-contrib/providers/ofrep v0.1.6/go.mod h1:Dwcaoma6lZVqYwyfVlY7eB6RXbG+Ju3b9cnpTlUN+Hc=
|
||||
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
|
||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
@@ -489,10 +465,6 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/thejerf/slogassert v0.3.4 h1:VoTsXixRbXMrRSSxDjYTiEDCM4VWbsYPW5rB/hX24kM=
|
||||
github.com/thejerf/slogassert v0.3.4/go.mod h1:0zn9ISLVKo1aPMTqcGfG1o6dWwt+Rk574GlUxHD4rs8=
|
||||
github.com/thomaspoignant/go-feature-flag v1.42.0 h1:C7embmOTzaLyRki+OoU2RvtVjJE9IrvgBA2C1mRN1lc=
|
||||
github.com/thomaspoignant/go-feature-flag v1.42.0/go.mod h1:y0QiWH7chHWhGATb/+XqwAwErORmPSH2MUsQlCmmWlM=
|
||||
github.com/tjhop/slog-gokit v0.1.5 h1:ayloIUi5EK2QYB8eY4DOPO95/mRtMW42lUkp3quJohc=
|
||||
github.com/tjhop/slog-gokit v0.1.5/go.mod h1:yA48zAHvV+Sg4z4VRyeFyFUNNXd3JY5Zg84u3USICq0=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
|
||||
@@ -541,8 +513,6 @@ go.opentelemetry.io/contrib/samplers/jaegerremote v0.32.0/go.mod h1:B9Oka5QVD0bn
|
||||
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
|
||||
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
|
||||
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4=
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0 h1:in9O8ESIOlwJAEGTkkf34DesGRAc/Pn8qJ7k3r/42LM=
|
||||
@@ -562,12 +532,8 @@ go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6
|
||||
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
|
||||
@@ -5,25 +5,7 @@ metaV0Alpha1: {
|
||||
scope: "Namespaced"
|
||||
schema: {
|
||||
spec: {
|
||||
pluginJson: #JSONData
|
||||
class: "core" | "external"
|
||||
module?: {
|
||||
path: string
|
||||
hash?: string
|
||||
loadingStrategy?: "fetch" | "script"
|
||||
}
|
||||
baseURL?: string
|
||||
signature?: {
|
||||
status: "internal" | "valid" | "invalid" | "modified" | "unsigned"
|
||||
type?: "grafana" | "commercial" | "community" | "private" | "private-glob"
|
||||
org?: string
|
||||
}
|
||||
angular?: {
|
||||
detected: bool
|
||||
}
|
||||
translations?: [string]: string
|
||||
// +listType=atomic
|
||||
children?: [...string]
|
||||
pluginJSON: #JSONData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ pluginV0Alpha1: {
|
||||
id: string
|
||||
version: string
|
||||
url?: string
|
||||
class: "core" | "external"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,21 +208,13 @@ func NewMetaExtensions() *MetaExtensions {
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type MetaSpec struct {
|
||||
PluginJson MetaJSONData `json:"pluginJson"`
|
||||
Class MetaSpecClass `json:"class"`
|
||||
Module *MetaV0alpha1SpecModule `json:"module,omitempty"`
|
||||
BaseURL *string `json:"baseURL,omitempty"`
|
||||
Signature *MetaV0alpha1SpecSignature `json:"signature,omitempty"`
|
||||
Angular *MetaV0alpha1SpecAngular `json:"angular,omitempty"`
|
||||
Translations map[string]string `json:"translations,omitempty"`
|
||||
// +listType=atomic
|
||||
Children []string `json:"children,omitempty"`
|
||||
PluginJSON MetaJSONData `json:"pluginJSON"`
|
||||
}
|
||||
|
||||
// NewMetaSpec creates a new MetaSpec object.
|
||||
func NewMetaSpec() *MetaSpec {
|
||||
return &MetaSpec{
|
||||
PluginJson: *NewMetaJSONData(),
|
||||
PluginJSON: *NewMetaJSONData(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,40 +412,6 @@ func NewMetaV0alpha1ExtensionsExtensionPoints() *MetaV0alpha1ExtensionsExtension
|
||||
return &MetaV0alpha1ExtensionsExtensionPoints{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type MetaV0alpha1SpecModule struct {
|
||||
Path string `json:"path"`
|
||||
Hash *string `json:"hash,omitempty"`
|
||||
LoadingStrategy *MetaV0alpha1SpecModuleLoadingStrategy `json:"loadingStrategy,omitempty"`
|
||||
}
|
||||
|
||||
// NewMetaV0alpha1SpecModule creates a new MetaV0alpha1SpecModule object.
|
||||
func NewMetaV0alpha1SpecModule() *MetaV0alpha1SpecModule {
|
||||
return &MetaV0alpha1SpecModule{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type MetaV0alpha1SpecSignature struct {
|
||||
Status MetaV0alpha1SpecSignatureStatus `json:"status"`
|
||||
Type *MetaV0alpha1SpecSignatureType `json:"type,omitempty"`
|
||||
Org *string `json:"org,omitempty"`
|
||||
}
|
||||
|
||||
// NewMetaV0alpha1SpecSignature creates a new MetaV0alpha1SpecSignature object.
|
||||
func NewMetaV0alpha1SpecSignature() *MetaV0alpha1SpecSignature {
|
||||
return &MetaV0alpha1SpecSignature{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type MetaV0alpha1SpecAngular struct {
|
||||
Detected bool `json:"detected"`
|
||||
}
|
||||
|
||||
// NewMetaV0alpha1SpecAngular creates a new MetaV0alpha1SpecAngular object.
|
||||
func NewMetaV0alpha1SpecAngular() *MetaV0alpha1SpecAngular {
|
||||
return &MetaV0alpha1SpecAngular{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type MetaJSONDataType string
|
||||
|
||||
@@ -506,14 +464,6 @@ const (
|
||||
MetaIncludeRoleViewer MetaIncludeRole = "Viewer"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type MetaSpecClass string
|
||||
|
||||
const (
|
||||
MetaSpecClassCore MetaSpecClass = "core"
|
||||
MetaSpecClassExternal MetaSpecClass = "external"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type MetaV0alpha1DependenciesPluginsType string
|
||||
|
||||
@@ -522,33 +472,3 @@ const (
|
||||
MetaV0alpha1DependenciesPluginsTypeDatasource MetaV0alpha1DependenciesPluginsType = "datasource"
|
||||
MetaV0alpha1DependenciesPluginsTypePanel MetaV0alpha1DependenciesPluginsType = "panel"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type MetaV0alpha1SpecModuleLoadingStrategy string
|
||||
|
||||
const (
|
||||
MetaV0alpha1SpecModuleLoadingStrategyFetch MetaV0alpha1SpecModuleLoadingStrategy = "fetch"
|
||||
MetaV0alpha1SpecModuleLoadingStrategyScript MetaV0alpha1SpecModuleLoadingStrategy = "script"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type MetaV0alpha1SpecSignatureStatus string
|
||||
|
||||
const (
|
||||
MetaV0alpha1SpecSignatureStatusInternal MetaV0alpha1SpecSignatureStatus = "internal"
|
||||
MetaV0alpha1SpecSignatureStatusValid MetaV0alpha1SpecSignatureStatus = "valid"
|
||||
MetaV0alpha1SpecSignatureStatusInvalid MetaV0alpha1SpecSignatureStatus = "invalid"
|
||||
MetaV0alpha1SpecSignatureStatusModified MetaV0alpha1SpecSignatureStatus = "modified"
|
||||
MetaV0alpha1SpecSignatureStatusUnsigned MetaV0alpha1SpecSignatureStatus = "unsigned"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type MetaV0alpha1SpecSignatureType string
|
||||
|
||||
const (
|
||||
MetaV0alpha1SpecSignatureTypeGrafana MetaV0alpha1SpecSignatureType = "grafana"
|
||||
MetaV0alpha1SpecSignatureTypeCommercial MetaV0alpha1SpecSignatureType = "commercial"
|
||||
MetaV0alpha1SpecSignatureTypeCommunity MetaV0alpha1SpecSignatureType = "community"
|
||||
MetaV0alpha1SpecSignatureTypePrivate MetaV0alpha1SpecSignatureType = "private"
|
||||
MetaV0alpha1SpecSignatureTypePrivateGlob MetaV0alpha1SpecSignatureType = "private-glob"
|
||||
)
|
||||
|
||||
@@ -4,12 +4,21 @@ package v0alpha1
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginSpec struct {
|
||||
Id string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Url *string `json:"url,omitempty"`
|
||||
Id string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Url *string `json:"url,omitempty"`
|
||||
Class PluginSpecClass `json:"class"`
|
||||
}
|
||||
|
||||
// NewPluginSpec creates a new PluginSpec object.
|
||||
func NewPluginSpec() *PluginSpec {
|
||||
return &PluginSpec{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginSpecClass string
|
||||
|
||||
const (
|
||||
PluginSpecClassCore PluginSpecClass = "core"
|
||||
PluginSpecClassExternal PluginSpecClass = "external"
|
||||
)
|
||||
|
||||
4
apps/plugins/pkg/apis/plugins_manifest.go
generated
4
apps/plugins/pkg/apis/plugins_manifest.go
generated
File diff suppressed because one or more lines are too long
@@ -15,6 +15,16 @@ const (
|
||||
PluginInstallSourceAnnotation = "plugins.grafana.app/install-source"
|
||||
)
|
||||
|
||||
// Class represents the plugin class type in an unversioned internal format.
|
||||
// This intentionally duplicates the versioned API type (PluginInstallSpecClass) to decouple
|
||||
// internal code from API version changes, making it easier to support multiple API versions.
|
||||
type Class = string
|
||||
|
||||
const (
|
||||
ClassCore Class = "core"
|
||||
ClassExternal Class = "external"
|
||||
)
|
||||
|
||||
type Source = string
|
||||
|
||||
const (
|
||||
@@ -26,6 +36,7 @@ type PluginInstall struct {
|
||||
ID string
|
||||
Version string
|
||||
URL string
|
||||
Class Class
|
||||
Source Source
|
||||
}
|
||||
|
||||
@@ -46,6 +57,7 @@ func (p *PluginInstall) ToPluginInstallV0Alpha1(namespace string) *pluginsv0alph
|
||||
Id: p.ID,
|
||||
Version: p.Version,
|
||||
Url: url,
|
||||
Class: pluginsv0alpha1.PluginSpecClass(p.Class),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -58,6 +70,9 @@ func (p *PluginInstall) ShouldUpdate(existing *pluginsv0alpha1.Plugin) bool {
|
||||
if existing.Spec.Version != update.Spec.Version {
|
||||
return true
|
||||
}
|
||||
if existing.Spec.Class != update.Spec.Class {
|
||||
return true // this should never really happen
|
||||
}
|
||||
if !equalStringPointers(existing.Spec.Url, update.Spec.Url) {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -26,12 +26,14 @@ func TestPluginInstall_ShouldUpdate(t *testing.T) {
|
||||
Spec: pluginsv0alpha1.PluginSpec{
|
||||
Id: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
Class: pluginsv0alpha1.PluginSpecClass(ClassExternal),
|
||||
},
|
||||
}
|
||||
|
||||
baseInstall := PluginInstall{
|
||||
ID: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
}
|
||||
|
||||
@@ -52,6 +54,13 @@ func TestPluginInstall_ShouldUpdate(t *testing.T) {
|
||||
},
|
||||
expectUpdate: true,
|
||||
},
|
||||
{
|
||||
name: "class differs",
|
||||
modifyInstall: func(pi *PluginInstall) {
|
||||
pi.Class = ClassCore
|
||||
},
|
||||
expectUpdate: true,
|
||||
},
|
||||
{
|
||||
name: "url differs",
|
||||
modifyInstall: func(pi *PluginInstall) {
|
||||
@@ -100,6 +109,7 @@ func TestInstallRegistrar_Register(t *testing.T) {
|
||||
install: &PluginInstall{
|
||||
ID: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
existingErr: errorsK8s.NewNotFound(pluginGroupResource(), "plugin-1"),
|
||||
@@ -110,6 +120,7 @@ func TestInstallRegistrar_Register(t *testing.T) {
|
||||
install: &PluginInstall{
|
||||
ID: "plugin-1",
|
||||
Version: "2.0.0",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
existing: &pluginsv0alpha1.Plugin{
|
||||
@@ -124,6 +135,7 @@ func TestInstallRegistrar_Register(t *testing.T) {
|
||||
Spec: pluginsv0alpha1.PluginSpec{
|
||||
Id: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
Class: pluginsv0alpha1.PluginSpecClass(ClassExternal),
|
||||
},
|
||||
},
|
||||
expectedUpdates: 1,
|
||||
@@ -133,6 +145,7 @@ func TestInstallRegistrar_Register(t *testing.T) {
|
||||
install: &PluginInstall{
|
||||
ID: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
existing: &pluginsv0alpha1.Plugin{
|
||||
@@ -147,6 +160,7 @@ func TestInstallRegistrar_Register(t *testing.T) {
|
||||
Spec: pluginsv0alpha1.PluginSpec{
|
||||
Id: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
Class: pluginsv0alpha1.PluginSpecClass(ClassExternal),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -155,6 +169,7 @@ func TestInstallRegistrar_Register(t *testing.T) {
|
||||
install: &PluginInstall{
|
||||
ID: "plugin-err",
|
||||
Version: "1.0.0",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
existingErr: errorsK8s.NewInternalError(errors.New("boom")),
|
||||
@@ -395,6 +410,7 @@ func TestPluginInstall_ToPluginInstallV0Alpha1(t *testing.T) {
|
||||
install: PluginInstall{
|
||||
ID: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
namespace: "org-1",
|
||||
@@ -408,6 +424,7 @@ func TestPluginInstall_ToPluginInstallV0Alpha1(t *testing.T) {
|
||||
ID: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
URL: "https://example.com/plugin.zip",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
namespace: "org-1",
|
||||
@@ -416,11 +433,25 @@ func TestPluginInstall_ToPluginInstallV0Alpha1(t *testing.T) {
|
||||
require.Equal(t, "https://example.com/plugin.zip", *p.Spec.Url)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "core class is mapped correctly",
|
||||
install: PluginInstall{
|
||||
ID: "plugin-core",
|
||||
Version: "2.0.0",
|
||||
Class: ClassCore,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
namespace: "org-2",
|
||||
validate: func(t *testing.T, p *pluginsv0alpha1.Plugin) {
|
||||
require.Equal(t, pluginsv0alpha1.PluginSpecClass(ClassCore), p.Spec.Class)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "source annotation is set correctly",
|
||||
install: PluginInstall{
|
||||
ID: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
Class: ClassExternal,
|
||||
Source: SourceUnknown,
|
||||
},
|
||||
namespace: "org-1",
|
||||
@@ -433,6 +464,7 @@ func TestPluginInstall_ToPluginInstallV0Alpha1(t *testing.T) {
|
||||
install: PluginInstall{
|
||||
ID: "my-plugin",
|
||||
Version: "1.0.0",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
namespace: "my-namespace",
|
||||
@@ -524,6 +556,7 @@ func TestPluginInstall_ShouldUpdate_URLTransitions(t *testing.T) {
|
||||
ID: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
URL: newURL,
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
existingURL: nil,
|
||||
@@ -535,6 +568,7 @@ func TestPluginInstall_ShouldUpdate_URLTransitions(t *testing.T) {
|
||||
ID: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
URL: "",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
existingURL: &existingURL,
|
||||
@@ -546,6 +580,7 @@ func TestPluginInstall_ShouldUpdate_URLTransitions(t *testing.T) {
|
||||
ID: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
URL: "",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
existingURL: nil,
|
||||
@@ -557,6 +592,7 @@ func TestPluginInstall_ShouldUpdate_URLTransitions(t *testing.T) {
|
||||
ID: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
URL: existingURL,
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
existingURL: &existingURL,
|
||||
@@ -578,6 +614,7 @@ func TestPluginInstall_ShouldUpdate_URLTransitions(t *testing.T) {
|
||||
Id: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
Url: tt.existingURL,
|
||||
Class: pluginsv0alpha1.PluginSpecClass(ClassExternal),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -633,6 +670,7 @@ func TestInstallRegistrar_Register_ErrorCases(t *testing.T) {
|
||||
install: &PluginInstall{
|
||||
ID: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
setupClient: func(fc *fakePluginInstallClient) {
|
||||
@@ -650,6 +688,7 @@ func TestInstallRegistrar_Register_ErrorCases(t *testing.T) {
|
||||
install: &PluginInstall{
|
||||
ID: "plugin-1",
|
||||
Version: "2.0.0",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
},
|
||||
setupClient: func(fc *fakePluginInstallClient) {
|
||||
@@ -666,6 +705,7 @@ func TestInstallRegistrar_Register_ErrorCases(t *testing.T) {
|
||||
Spec: pluginsv0alpha1.PluginSpec{
|
||||
Id: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
Class: pluginsv0alpha1.PluginSpecClass(ClassExternal),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -836,6 +876,7 @@ func TestInstallRegistrar_GetClientError(t *testing.T) {
|
||||
install := &PluginInstall{
|
||||
ID: "plugin-1",
|
||||
Version: "1.0.0",
|
||||
Class: ClassExternal,
|
||||
Source: SourcePluginStore,
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/logging"
|
||||
|
||||
pluginsv0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -85,9 +87,45 @@ func (p *CatalogProvider) GetMeta(ctx context.Context, pluginID, version string)
|
||||
return nil, fmt.Errorf("failed to decode response: %w", err)
|
||||
}
|
||||
|
||||
metaSpec := grafanaComPluginVersionMetaToMetaSpec(gcomMeta)
|
||||
return &Result{
|
||||
Meta: metaSpec,
|
||||
Meta: gcomMeta.JSON,
|
||||
TTL: p.ttl,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// grafanaComPluginVersionMeta represents the response from grafana.com API
|
||||
// GET /api/plugins/{pluginId}/versions/{version}
|
||||
type grafanaComPluginVersionMeta struct {
|
||||
PluginID string `json:"pluginSlug"`
|
||||
Version string `json:"version"`
|
||||
URL string `json:"url"`
|
||||
Commit string `json:"commit"`
|
||||
Description string `json:"description"`
|
||||
Keywords []string `json:"keywords"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
JSON pluginsv0alpha1.MetaJSONData `json:"json"`
|
||||
Readme string `json:"readme"`
|
||||
Downloads int `json:"downloads"`
|
||||
Verified bool `json:"verified"`
|
||||
Status string `json:"status"`
|
||||
StatusContext string `json:"statusContext"`
|
||||
DownloadSlug string `json:"downloadSlug"`
|
||||
SignatureType string `json:"signatureType"`
|
||||
SignedByOrg string `json:"signedByOrg"`
|
||||
SignedByOrgName string `json:"signedByOrgName"`
|
||||
Packages struct {
|
||||
Any struct {
|
||||
Md5 string `json:"md5"`
|
||||
Sha256 string `json:"sha256"`
|
||||
PackageName string `json:"packageName"`
|
||||
DownloadURL string `json:"downloadUrl"`
|
||||
} `json:"any"`
|
||||
} `json:"packages"`
|
||||
Links []struct {
|
||||
Rel string `json:"rel"`
|
||||
Href string `json:"href"`
|
||||
} `json:"links"`
|
||||
AngularDetected bool `json:"angularDetected"`
|
||||
Scopes []string `json:"scopes"`
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func TestCatalogProvider_GetMeta(t *testing.T) {
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, result)
|
||||
assert.Equal(t, expectedMeta, result.Meta.PluginJson)
|
||||
assert.Equal(t, expectedMeta, result.Meta)
|
||||
assert.Equal(t, defaultCatalogTTL, result.TTL)
|
||||
})
|
||||
|
||||
|
||||
@@ -1,744 +0,0 @@
|
||||
package meta
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
pluginsv0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
// jsonDataToMetaJSONData converts a plugins.JSONData to a pluginsv0alpha1.MetaJSONData.
|
||||
// nolint:gocyclo
|
||||
func jsonDataToMetaJSONData(jsonData plugins.JSONData) pluginsv0alpha1.MetaJSONData {
|
||||
meta := pluginsv0alpha1.MetaJSONData{
|
||||
Id: jsonData.ID,
|
||||
Name: jsonData.Name,
|
||||
}
|
||||
|
||||
// Map plugin type
|
||||
switch jsonData.Type {
|
||||
case plugins.TypeApp:
|
||||
meta.Type = pluginsv0alpha1.MetaJSONDataTypeApp
|
||||
case plugins.TypeDataSource:
|
||||
meta.Type = pluginsv0alpha1.MetaJSONDataTypeDatasource
|
||||
case plugins.TypePanel:
|
||||
meta.Type = pluginsv0alpha1.MetaJSONDataTypePanel
|
||||
case plugins.TypeRenderer:
|
||||
meta.Type = pluginsv0alpha1.MetaJSONDataTypeRenderer
|
||||
}
|
||||
|
||||
// Map Info
|
||||
meta.Info = pluginsv0alpha1.MetaInfo{
|
||||
Keywords: jsonData.Info.Keywords,
|
||||
Logos: pluginsv0alpha1.MetaV0alpha1InfoLogos{
|
||||
Small: jsonData.Info.Logos.Small,
|
||||
Large: jsonData.Info.Logos.Large,
|
||||
},
|
||||
Updated: jsonData.Info.Updated,
|
||||
Version: jsonData.Info.Version,
|
||||
}
|
||||
|
||||
if jsonData.Info.Description != "" {
|
||||
meta.Info.Description = &jsonData.Info.Description
|
||||
}
|
||||
|
||||
if jsonData.Info.Author.Name != "" || jsonData.Info.Author.URL != "" {
|
||||
author := &pluginsv0alpha1.MetaV0alpha1InfoAuthor{}
|
||||
if jsonData.Info.Author.Name != "" {
|
||||
author.Name = &jsonData.Info.Author.Name
|
||||
}
|
||||
if jsonData.Info.Author.URL != "" {
|
||||
author.Url = &jsonData.Info.Author.URL
|
||||
}
|
||||
meta.Info.Author = author
|
||||
}
|
||||
|
||||
if len(jsonData.Info.Links) > 0 {
|
||||
meta.Info.Links = make([]pluginsv0alpha1.MetaV0alpha1InfoLinks, 0, len(jsonData.Info.Links))
|
||||
for _, link := range jsonData.Info.Links {
|
||||
v0Link := pluginsv0alpha1.MetaV0alpha1InfoLinks{}
|
||||
if link.Name != "" {
|
||||
v0Link.Name = &link.Name
|
||||
}
|
||||
if link.URL != "" {
|
||||
v0Link.Url = &link.URL
|
||||
}
|
||||
meta.Info.Links = append(meta.Info.Links, v0Link)
|
||||
}
|
||||
}
|
||||
|
||||
if len(jsonData.Info.Screenshots) > 0 {
|
||||
meta.Info.Screenshots = make([]pluginsv0alpha1.MetaV0alpha1InfoScreenshots, 0, len(jsonData.Info.Screenshots))
|
||||
for _, screenshot := range jsonData.Info.Screenshots {
|
||||
v0Screenshot := pluginsv0alpha1.MetaV0alpha1InfoScreenshots{}
|
||||
if screenshot.Name != "" {
|
||||
v0Screenshot.Name = &screenshot.Name
|
||||
}
|
||||
if screenshot.Path != "" {
|
||||
v0Screenshot.Path = &screenshot.Path
|
||||
}
|
||||
meta.Info.Screenshots = append(meta.Info.Screenshots, v0Screenshot)
|
||||
}
|
||||
}
|
||||
|
||||
// Map Dependencies
|
||||
meta.Dependencies = pluginsv0alpha1.MetaDependencies{
|
||||
GrafanaDependency: jsonData.Dependencies.GrafanaDependency,
|
||||
}
|
||||
|
||||
if jsonData.Dependencies.GrafanaVersion != "" {
|
||||
meta.Dependencies.GrafanaVersion = &jsonData.Dependencies.GrafanaVersion
|
||||
}
|
||||
|
||||
if len(jsonData.Dependencies.Plugins) > 0 {
|
||||
meta.Dependencies.Plugins = make([]pluginsv0alpha1.MetaV0alpha1DependenciesPlugins, 0, len(jsonData.Dependencies.Plugins))
|
||||
for _, dep := range jsonData.Dependencies.Plugins {
|
||||
var depType pluginsv0alpha1.MetaV0alpha1DependenciesPluginsType
|
||||
switch dep.Type {
|
||||
case "app":
|
||||
depType = pluginsv0alpha1.MetaV0alpha1DependenciesPluginsTypeApp
|
||||
case "datasource":
|
||||
depType = pluginsv0alpha1.MetaV0alpha1DependenciesPluginsTypeDatasource
|
||||
case "panel":
|
||||
depType = pluginsv0alpha1.MetaV0alpha1DependenciesPluginsTypePanel
|
||||
}
|
||||
meta.Dependencies.Plugins = append(meta.Dependencies.Plugins, pluginsv0alpha1.MetaV0alpha1DependenciesPlugins{
|
||||
Id: dep.ID,
|
||||
Type: depType,
|
||||
Name: dep.Name,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(jsonData.Dependencies.Extensions.ExposedComponents) > 0 {
|
||||
meta.Dependencies.Extensions = &pluginsv0alpha1.MetaV0alpha1DependenciesExtensions{
|
||||
ExposedComponents: jsonData.Dependencies.Extensions.ExposedComponents,
|
||||
}
|
||||
}
|
||||
|
||||
// Map optional boolean fields
|
||||
if jsonData.Alerting {
|
||||
meta.Alerting = &jsonData.Alerting
|
||||
}
|
||||
if jsonData.Annotations {
|
||||
meta.Annotations = &jsonData.Annotations
|
||||
}
|
||||
if jsonData.AutoEnabled {
|
||||
meta.AutoEnabled = &jsonData.AutoEnabled
|
||||
}
|
||||
if jsonData.Backend {
|
||||
meta.Backend = &jsonData.Backend
|
||||
}
|
||||
if jsonData.BuiltIn {
|
||||
meta.BuiltIn = &jsonData.BuiltIn
|
||||
}
|
||||
if jsonData.HideFromList {
|
||||
meta.HideFromList = &jsonData.HideFromList
|
||||
}
|
||||
if jsonData.Logs {
|
||||
meta.Logs = &jsonData.Logs
|
||||
}
|
||||
if jsonData.Metrics {
|
||||
meta.Metrics = &jsonData.Metrics
|
||||
}
|
||||
if jsonData.MultiValueFilterOperators {
|
||||
meta.MultiValueFilterOperators = &jsonData.MultiValueFilterOperators
|
||||
}
|
||||
if jsonData.Preload {
|
||||
meta.Preload = &jsonData.Preload
|
||||
}
|
||||
if jsonData.SkipDataQuery {
|
||||
meta.SkipDataQuery = &jsonData.SkipDataQuery
|
||||
}
|
||||
if jsonData.Streaming {
|
||||
meta.Streaming = &jsonData.Streaming
|
||||
}
|
||||
if jsonData.Tracing {
|
||||
meta.Tracing = &jsonData.Tracing
|
||||
}
|
||||
|
||||
// Map category
|
||||
if jsonData.Category != "" {
|
||||
var category pluginsv0alpha1.MetaJSONDataCategory
|
||||
switch jsonData.Category {
|
||||
case "tsdb":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryTsdb
|
||||
case "logging":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryLogging
|
||||
case "cloud":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryCloud
|
||||
case "tracing":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryTracing
|
||||
case "profiling":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryProfiling
|
||||
case "sql":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategorySql
|
||||
case "enterprise":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryEnterprise
|
||||
case "iot":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryIot
|
||||
case "other":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryOther
|
||||
default:
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryOther
|
||||
}
|
||||
meta.Category = &category
|
||||
}
|
||||
|
||||
// Map state
|
||||
if jsonData.State != "" {
|
||||
var state pluginsv0alpha1.MetaJSONDataState
|
||||
switch jsonData.State {
|
||||
case plugins.ReleaseStateAlpha:
|
||||
state = pluginsv0alpha1.MetaJSONDataStateAlpha
|
||||
case plugins.ReleaseStateBeta:
|
||||
state = pluginsv0alpha1.MetaJSONDataStateBeta
|
||||
default:
|
||||
}
|
||||
if state != "" {
|
||||
meta.State = &state
|
||||
}
|
||||
}
|
||||
|
||||
// Map executable
|
||||
if jsonData.Executable != "" {
|
||||
meta.Executable = &jsonData.Executable
|
||||
}
|
||||
|
||||
// Map QueryOptions
|
||||
if len(jsonData.QueryOptions) > 0 {
|
||||
queryOptions := &pluginsv0alpha1.MetaQueryOptions{}
|
||||
if val, ok := jsonData.QueryOptions["maxDataPoints"]; ok {
|
||||
queryOptions.MaxDataPoints = &val
|
||||
}
|
||||
if val, ok := jsonData.QueryOptions["minInterval"]; ok {
|
||||
queryOptions.MinInterval = &val
|
||||
}
|
||||
if val, ok := jsonData.QueryOptions["cacheTimeout"]; ok {
|
||||
queryOptions.CacheTimeout = &val
|
||||
}
|
||||
meta.QueryOptions = queryOptions
|
||||
}
|
||||
|
||||
// Map Includes
|
||||
if len(jsonData.Includes) > 0 {
|
||||
meta.Includes = make([]pluginsv0alpha1.MetaInclude, 0, len(jsonData.Includes))
|
||||
for _, include := range jsonData.Includes {
|
||||
v0Include := pluginsv0alpha1.MetaInclude{}
|
||||
if include.UID != "" {
|
||||
v0Include.Uid = &include.UID
|
||||
}
|
||||
if include.Type != "" {
|
||||
var includeType pluginsv0alpha1.MetaIncludeType
|
||||
switch include.Type {
|
||||
case "dashboard":
|
||||
includeType = pluginsv0alpha1.MetaIncludeTypeDashboard
|
||||
case "page":
|
||||
includeType = pluginsv0alpha1.MetaIncludeTypePage
|
||||
case "panel":
|
||||
includeType = pluginsv0alpha1.MetaIncludeTypePanel
|
||||
case "datasource":
|
||||
includeType = pluginsv0alpha1.MetaIncludeTypeDatasource
|
||||
}
|
||||
v0Include.Type = &includeType
|
||||
}
|
||||
if include.Name != "" {
|
||||
v0Include.Name = &include.Name
|
||||
}
|
||||
if include.Component != "" {
|
||||
v0Include.Component = &include.Component
|
||||
}
|
||||
if include.Role != "" {
|
||||
var role pluginsv0alpha1.MetaIncludeRole
|
||||
switch include.Role {
|
||||
case "Admin":
|
||||
role = pluginsv0alpha1.MetaIncludeRoleAdmin
|
||||
case "Editor":
|
||||
role = pluginsv0alpha1.MetaIncludeRoleEditor
|
||||
case "Viewer":
|
||||
role = pluginsv0alpha1.MetaIncludeRoleViewer
|
||||
}
|
||||
v0Include.Role = &role
|
||||
}
|
||||
if include.Action != "" {
|
||||
v0Include.Action = &include.Action
|
||||
}
|
||||
if include.Path != "" {
|
||||
v0Include.Path = &include.Path
|
||||
}
|
||||
if include.AddToNav {
|
||||
v0Include.AddToNav = &include.AddToNav
|
||||
}
|
||||
if include.DefaultNav {
|
||||
v0Include.DefaultNav = &include.DefaultNav
|
||||
}
|
||||
if include.Icon != "" {
|
||||
v0Include.Icon = &include.Icon
|
||||
}
|
||||
meta.Includes = append(meta.Includes, v0Include)
|
||||
}
|
||||
}
|
||||
|
||||
// Map Routes
|
||||
if len(jsonData.Routes) > 0 {
|
||||
meta.Routes = make([]pluginsv0alpha1.MetaRoute, 0, len(jsonData.Routes))
|
||||
for _, route := range jsonData.Routes {
|
||||
v0Route := pluginsv0alpha1.MetaRoute{}
|
||||
if route.Path != "" {
|
||||
v0Route.Path = &route.Path
|
||||
}
|
||||
if route.Method != "" {
|
||||
v0Route.Method = &route.Method
|
||||
}
|
||||
if route.URL != "" {
|
||||
v0Route.Url = &route.URL
|
||||
}
|
||||
if route.ReqRole != "" {
|
||||
reqRole := string(route.ReqRole)
|
||||
v0Route.ReqRole = &reqRole
|
||||
}
|
||||
if route.ReqAction != "" {
|
||||
v0Route.ReqAction = &route.ReqAction
|
||||
}
|
||||
if len(route.Headers) > 0 {
|
||||
headers := make([]string, 0, len(route.Headers))
|
||||
for _, header := range route.Headers {
|
||||
headers = append(headers, header.Name+": "+header.Content)
|
||||
}
|
||||
v0Route.Headers = headers
|
||||
}
|
||||
if len(route.URLParams) > 0 {
|
||||
v0Route.UrlParams = make([]pluginsv0alpha1.MetaV0alpha1RouteUrlParams, 0, len(route.URLParams))
|
||||
for _, param := range route.URLParams {
|
||||
v0Param := pluginsv0alpha1.MetaV0alpha1RouteUrlParams{}
|
||||
if param.Name != "" {
|
||||
v0Param.Name = ¶m.Name
|
||||
}
|
||||
if param.Content != "" {
|
||||
v0Param.Content = ¶m.Content
|
||||
}
|
||||
v0Route.UrlParams = append(v0Route.UrlParams, v0Param)
|
||||
}
|
||||
}
|
||||
if route.TokenAuth != nil {
|
||||
v0Route.TokenAuth = &pluginsv0alpha1.MetaV0alpha1RouteTokenAuth{}
|
||||
if route.TokenAuth.Url != "" {
|
||||
v0Route.TokenAuth.Url = &route.TokenAuth.Url
|
||||
}
|
||||
if len(route.TokenAuth.Scopes) > 0 {
|
||||
v0Route.TokenAuth.Scopes = route.TokenAuth.Scopes
|
||||
}
|
||||
if len(route.TokenAuth.Params) > 0 {
|
||||
v0Route.TokenAuth.Params = make(map[string]interface{})
|
||||
for k, v := range route.TokenAuth.Params {
|
||||
v0Route.TokenAuth.Params[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
if route.JwtTokenAuth != nil {
|
||||
v0Route.JwtTokenAuth = &pluginsv0alpha1.MetaV0alpha1RouteJwtTokenAuth{}
|
||||
if route.JwtTokenAuth.Url != "" {
|
||||
v0Route.JwtTokenAuth.Url = &route.JwtTokenAuth.Url
|
||||
}
|
||||
if len(route.JwtTokenAuth.Scopes) > 0 {
|
||||
v0Route.JwtTokenAuth.Scopes = route.JwtTokenAuth.Scopes
|
||||
}
|
||||
if len(route.JwtTokenAuth.Params) > 0 {
|
||||
v0Route.JwtTokenAuth.Params = make(map[string]interface{})
|
||||
for k, v := range route.JwtTokenAuth.Params {
|
||||
v0Route.JwtTokenAuth.Params[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(route.Body) > 0 {
|
||||
var bodyMap map[string]interface{}
|
||||
if err := json.Unmarshal(route.Body, &bodyMap); err == nil {
|
||||
v0Route.Body = bodyMap
|
||||
}
|
||||
}
|
||||
meta.Routes = append(meta.Routes, v0Route)
|
||||
}
|
||||
}
|
||||
|
||||
// Map Extensions
|
||||
if len(jsonData.Extensions.AddedLinks) > 0 || len(jsonData.Extensions.AddedComponents) > 0 ||
|
||||
len(jsonData.Extensions.ExposedComponents) > 0 || len(jsonData.Extensions.ExtensionPoints) > 0 {
|
||||
extensions := &pluginsv0alpha1.MetaExtensions{}
|
||||
|
||||
if len(jsonData.Extensions.AddedLinks) > 0 {
|
||||
extensions.AddedLinks = make([]pluginsv0alpha1.MetaV0alpha1ExtensionsAddedLinks, 0, len(jsonData.Extensions.AddedLinks))
|
||||
for _, link := range jsonData.Extensions.AddedLinks {
|
||||
v0Link := pluginsv0alpha1.MetaV0alpha1ExtensionsAddedLinks{
|
||||
Targets: link.Targets,
|
||||
Title: link.Title,
|
||||
}
|
||||
if link.Description != "" {
|
||||
v0Link.Description = &link.Description
|
||||
}
|
||||
extensions.AddedLinks = append(extensions.AddedLinks, v0Link)
|
||||
}
|
||||
}
|
||||
|
||||
if len(jsonData.Extensions.AddedComponents) > 0 {
|
||||
extensions.AddedComponents = make([]pluginsv0alpha1.MetaV0alpha1ExtensionsAddedComponents, 0, len(jsonData.Extensions.AddedComponents))
|
||||
for _, comp := range jsonData.Extensions.AddedComponents {
|
||||
v0Comp := pluginsv0alpha1.MetaV0alpha1ExtensionsAddedComponents{
|
||||
Targets: comp.Targets,
|
||||
Title: comp.Title,
|
||||
}
|
||||
if comp.Description != "" {
|
||||
v0Comp.Description = &comp.Description
|
||||
}
|
||||
extensions.AddedComponents = append(extensions.AddedComponents, v0Comp)
|
||||
}
|
||||
}
|
||||
|
||||
if len(jsonData.Extensions.ExposedComponents) > 0 {
|
||||
extensions.ExposedComponents = make([]pluginsv0alpha1.MetaV0alpha1ExtensionsExposedComponents, 0, len(jsonData.Extensions.ExposedComponents))
|
||||
for _, comp := range jsonData.Extensions.ExposedComponents {
|
||||
v0Comp := pluginsv0alpha1.MetaV0alpha1ExtensionsExposedComponents{
|
||||
Id: comp.Id,
|
||||
}
|
||||
if comp.Title != "" {
|
||||
v0Comp.Title = &comp.Title
|
||||
}
|
||||
if comp.Description != "" {
|
||||
v0Comp.Description = &comp.Description
|
||||
}
|
||||
extensions.ExposedComponents = append(extensions.ExposedComponents, v0Comp)
|
||||
}
|
||||
}
|
||||
|
||||
if len(jsonData.Extensions.ExtensionPoints) > 0 {
|
||||
extensions.ExtensionPoints = make([]pluginsv0alpha1.MetaV0alpha1ExtensionsExtensionPoints, 0, len(jsonData.Extensions.ExtensionPoints))
|
||||
for _, point := range jsonData.Extensions.ExtensionPoints {
|
||||
v0Point := pluginsv0alpha1.MetaV0alpha1ExtensionsExtensionPoints{
|
||||
Id: point.Id,
|
||||
}
|
||||
if point.Title != "" {
|
||||
v0Point.Title = &point.Title
|
||||
}
|
||||
if point.Description != "" {
|
||||
v0Point.Description = &point.Description
|
||||
}
|
||||
extensions.ExtensionPoints = append(extensions.ExtensionPoints, v0Point)
|
||||
}
|
||||
}
|
||||
|
||||
meta.Extensions = extensions
|
||||
}
|
||||
|
||||
// Map Roles
|
||||
if len(jsonData.Roles) > 0 {
|
||||
meta.Roles = make([]pluginsv0alpha1.MetaRole, 0, len(jsonData.Roles))
|
||||
for _, role := range jsonData.Roles {
|
||||
v0Role := pluginsv0alpha1.MetaRole{
|
||||
Grants: role.Grants,
|
||||
}
|
||||
if role.Role.Name != "" || role.Role.Description != "" || len(role.Role.Permissions) > 0 {
|
||||
v0RoleRole := &pluginsv0alpha1.MetaV0alpha1RoleRole{}
|
||||
if role.Role.Name != "" {
|
||||
v0RoleRole.Name = &role.Role.Name
|
||||
}
|
||||
if role.Role.Description != "" {
|
||||
v0RoleRole.Description = &role.Role.Description
|
||||
}
|
||||
if len(role.Role.Permissions) > 0 {
|
||||
v0RoleRole.Permissions = make([]pluginsv0alpha1.MetaV0alpha1RoleRolePermissions, 0, len(role.Role.Permissions))
|
||||
for _, perm := range role.Role.Permissions {
|
||||
v0Perm := pluginsv0alpha1.MetaV0alpha1RoleRolePermissions{}
|
||||
if perm.Action != "" {
|
||||
v0Perm.Action = &perm.Action
|
||||
}
|
||||
if perm.Scope != "" {
|
||||
v0Perm.Scope = &perm.Scope
|
||||
}
|
||||
v0RoleRole.Permissions = append(v0RoleRole.Permissions, v0Perm)
|
||||
}
|
||||
}
|
||||
v0Role.Role = v0RoleRole
|
||||
}
|
||||
meta.Roles = append(meta.Roles, v0Role)
|
||||
}
|
||||
}
|
||||
|
||||
// Map IAM
|
||||
if jsonData.IAM != nil && len(jsonData.IAM.Permissions) > 0 {
|
||||
iam := &pluginsv0alpha1.MetaIAM{
|
||||
Permissions: make([]pluginsv0alpha1.MetaV0alpha1IAMPermissions, 0, len(jsonData.IAM.Permissions)),
|
||||
}
|
||||
for _, perm := range jsonData.IAM.Permissions {
|
||||
v0Perm := pluginsv0alpha1.MetaV0alpha1IAMPermissions{}
|
||||
if perm.Action != "" {
|
||||
v0Perm.Action = &perm.Action
|
||||
}
|
||||
if perm.Scope != "" {
|
||||
v0Perm.Scope = &perm.Scope
|
||||
}
|
||||
iam.Permissions = append(iam.Permissions, v0Perm)
|
||||
}
|
||||
meta.Iam = iam
|
||||
}
|
||||
|
||||
return meta
|
||||
}
|
||||
|
||||
// pluginStorePluginToMeta converts a pluginstore.Plugin to a pluginsv0alpha1.MetaSpec.
|
||||
// This is similar to pluginToPluginMetaSpec but works with the plugin store DTO.
|
||||
// loadingStrategy and moduleHash are optional calculated values that can be provided.
|
||||
func pluginStorePluginToMeta(plugin pluginstore.Plugin, loadingStrategy plugins.LoadingStrategy, moduleHash string) pluginsv0alpha1.MetaSpec {
|
||||
metaSpec := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: jsonDataToMetaJSONData(plugin.JSONData),
|
||||
}
|
||||
|
||||
// Set Class - default to External if not specified
|
||||
var c pluginsv0alpha1.MetaSpecClass
|
||||
if plugin.Class == plugins.ClassCore {
|
||||
c = pluginsv0alpha1.MetaSpecClassCore
|
||||
} else {
|
||||
c = pluginsv0alpha1.MetaSpecClassExternal
|
||||
}
|
||||
metaSpec.Class = c
|
||||
|
||||
if plugin.Module != "" {
|
||||
module := &pluginsv0alpha1.MetaV0alpha1SpecModule{
|
||||
Path: plugin.Module,
|
||||
}
|
||||
if moduleHash != "" {
|
||||
module.Hash = &moduleHash
|
||||
}
|
||||
if loadingStrategy != "" {
|
||||
var ls pluginsv0alpha1.MetaV0alpha1SpecModuleLoadingStrategy
|
||||
switch loadingStrategy {
|
||||
case plugins.LoadingStrategyFetch:
|
||||
ls = pluginsv0alpha1.MetaV0alpha1SpecModuleLoadingStrategyFetch
|
||||
case plugins.LoadingStrategyScript:
|
||||
ls = pluginsv0alpha1.MetaV0alpha1SpecModuleLoadingStrategyScript
|
||||
}
|
||||
module.LoadingStrategy = &ls
|
||||
}
|
||||
metaSpec.Module = module
|
||||
}
|
||||
|
||||
if plugin.BaseURL != "" {
|
||||
metaSpec.BaseURL = &plugin.BaseURL
|
||||
}
|
||||
|
||||
if plugin.Signature != "" {
|
||||
signature := &pluginsv0alpha1.MetaV0alpha1SpecSignature{
|
||||
Status: convertSignatureStatus(plugin.Signature),
|
||||
}
|
||||
|
||||
if plugin.SignatureType != "" {
|
||||
sigType := convertSignatureType(plugin.SignatureType)
|
||||
signature.Type = &sigType
|
||||
}
|
||||
|
||||
if plugin.SignatureOrg != "" {
|
||||
signature.Org = &plugin.SignatureOrg
|
||||
}
|
||||
|
||||
metaSpec.Signature = signature
|
||||
}
|
||||
|
||||
if len(plugin.Children) > 0 {
|
||||
metaSpec.Children = plugin.Children
|
||||
}
|
||||
|
||||
metaSpec.Angular = &pluginsv0alpha1.MetaV0alpha1SpecAngular{
|
||||
Detected: plugin.Angular.Detected,
|
||||
}
|
||||
|
||||
if len(plugin.Translations) > 0 {
|
||||
metaSpec.Translations = plugin.Translations
|
||||
}
|
||||
|
||||
return metaSpec
|
||||
}
|
||||
|
||||
// convertSignatureStatus converts plugins.SignatureStatus to pluginsv0alpha1.MetaV0alpha1SpecSignatureStatus.
|
||||
func convertSignatureStatus(status plugins.SignatureStatus) pluginsv0alpha1.MetaV0alpha1SpecSignatureStatus {
|
||||
switch status {
|
||||
case plugins.SignatureStatusInternal:
|
||||
return pluginsv0alpha1.MetaV0alpha1SpecSignatureStatusInternal
|
||||
case plugins.SignatureStatusValid:
|
||||
return pluginsv0alpha1.MetaV0alpha1SpecSignatureStatusValid
|
||||
case plugins.SignatureStatusInvalid:
|
||||
return pluginsv0alpha1.MetaV0alpha1SpecSignatureStatusInvalid
|
||||
case plugins.SignatureStatusModified:
|
||||
return pluginsv0alpha1.MetaV0alpha1SpecSignatureStatusModified
|
||||
case plugins.SignatureStatusUnsigned:
|
||||
return pluginsv0alpha1.MetaV0alpha1SpecSignatureStatusUnsigned
|
||||
default:
|
||||
return pluginsv0alpha1.MetaV0alpha1SpecSignatureStatusUnsigned
|
||||
}
|
||||
}
|
||||
|
||||
// convertSignatureType converts plugins.SignatureType to pluginsv0alpha1.MetaV0alpha1SpecSignatureType.
|
||||
func convertSignatureType(sigType plugins.SignatureType) pluginsv0alpha1.MetaV0alpha1SpecSignatureType {
|
||||
switch sigType {
|
||||
case plugins.SignatureTypeGrafana:
|
||||
return pluginsv0alpha1.MetaV0alpha1SpecSignatureTypeGrafana
|
||||
case plugins.SignatureTypeCommercial:
|
||||
return pluginsv0alpha1.MetaV0alpha1SpecSignatureTypeCommercial
|
||||
case plugins.SignatureTypeCommunity:
|
||||
return pluginsv0alpha1.MetaV0alpha1SpecSignatureTypeCommunity
|
||||
case plugins.SignatureTypePrivate:
|
||||
return pluginsv0alpha1.MetaV0alpha1SpecSignatureTypePrivate
|
||||
case plugins.SignatureTypePrivateGlob:
|
||||
return pluginsv0alpha1.MetaV0alpha1SpecSignatureTypePrivateGlob
|
||||
default:
|
||||
return pluginsv0alpha1.MetaV0alpha1SpecSignatureTypeGrafana
|
||||
}
|
||||
}
|
||||
|
||||
// pluginToMetaSpec converts a fully loaded *plugins.Plugin to a pluginsv0alpha1.MetaSpec.
|
||||
func pluginToMetaSpec(plugin *plugins.Plugin) pluginsv0alpha1.MetaSpec {
|
||||
metaSpec := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: jsonDataToMetaJSONData(plugin.JSONData),
|
||||
}
|
||||
|
||||
// Set Class - default to External if not specified
|
||||
var c pluginsv0alpha1.MetaSpecClass
|
||||
if plugin.Class == plugins.ClassCore {
|
||||
c = pluginsv0alpha1.MetaSpecClassCore
|
||||
} else {
|
||||
c = pluginsv0alpha1.MetaSpecClassExternal
|
||||
}
|
||||
metaSpec.Class = c
|
||||
|
||||
// Set module information
|
||||
if plugin.Module != "" {
|
||||
module := &pluginsv0alpha1.MetaV0alpha1SpecModule{
|
||||
Path: plugin.Module,
|
||||
}
|
||||
|
||||
loadingStrategy := pluginsv0alpha1.MetaV0alpha1SpecModuleLoadingStrategyScript
|
||||
module.LoadingStrategy = &loadingStrategy
|
||||
|
||||
metaSpec.Module = module
|
||||
}
|
||||
|
||||
// Set BaseURL
|
||||
if plugin.BaseURL != "" {
|
||||
metaSpec.BaseURL = &plugin.BaseURL
|
||||
}
|
||||
|
||||
// Set signature information
|
||||
signature := &pluginsv0alpha1.MetaV0alpha1SpecSignature{
|
||||
Status: convertSignatureStatus(plugin.Signature),
|
||||
}
|
||||
|
||||
if plugin.SignatureType != "" {
|
||||
sigType := convertSignatureType(plugin.SignatureType)
|
||||
signature.Type = &sigType
|
||||
}
|
||||
|
||||
if plugin.SignatureOrg != "" {
|
||||
signature.Org = &plugin.SignatureOrg
|
||||
}
|
||||
|
||||
metaSpec.Signature = signature
|
||||
|
||||
if len(plugin.Children) > 0 {
|
||||
children := make([]string, 0, len(plugin.Children))
|
||||
for _, child := range plugin.Children {
|
||||
children = append(children, child.ID)
|
||||
}
|
||||
metaSpec.Children = children
|
||||
}
|
||||
|
||||
metaSpec.Angular = &pluginsv0alpha1.MetaV0alpha1SpecAngular{
|
||||
Detected: plugin.Angular.Detected,
|
||||
}
|
||||
|
||||
if len(plugin.Translations) > 0 {
|
||||
metaSpec.Translations = plugin.Translations
|
||||
}
|
||||
|
||||
return metaSpec
|
||||
}
|
||||
|
||||
// grafanaComPluginVersionMeta represents the response from grafana.com API
|
||||
// GET /api/plugins/{pluginId}/versions/{version}
|
||||
type grafanaComPluginVersionMeta struct {
|
||||
PluginID string `json:"pluginSlug"`
|
||||
Version string `json:"version"`
|
||||
URL string `json:"url"`
|
||||
Commit string `json:"commit"`
|
||||
Description string `json:"description"`
|
||||
Keywords []string `json:"keywords"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
JSON pluginsv0alpha1.MetaJSONData `json:"json"`
|
||||
Readme string `json:"readme"`
|
||||
Downloads int `json:"downloads"`
|
||||
Verified bool `json:"verified"`
|
||||
Status string `json:"status"`
|
||||
StatusContext string `json:"statusContext"`
|
||||
DownloadSlug string `json:"downloadSlug"`
|
||||
SignatureType string `json:"signatureType"`
|
||||
SignedByOrg string `json:"signedByOrg"`
|
||||
SignedByOrgName string `json:"signedByOrgName"`
|
||||
Packages struct {
|
||||
Any struct {
|
||||
Md5 string `json:"md5"`
|
||||
Sha256 string `json:"sha256"`
|
||||
PackageName string `json:"packageName"`
|
||||
DownloadURL string `json:"downloadUrl"`
|
||||
} `json:"any"`
|
||||
} `json:"packages"`
|
||||
Links []struct {
|
||||
Rel string `json:"rel"`
|
||||
Href string `json:"href"`
|
||||
} `json:"links"`
|
||||
AngularDetected bool `json:"angularDetected"`
|
||||
Scopes []string `json:"scopes"`
|
||||
}
|
||||
|
||||
// grafanaComPluginVersionMetaToMetaSpec converts a grafanaComPluginVersionMeta to a pluginsv0alpha1.MetaSpec.
|
||||
func grafanaComPluginVersionMetaToMetaSpec(gcomMeta grafanaComPluginVersionMeta) pluginsv0alpha1.MetaSpec {
|
||||
metaSpec := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: gcomMeta.JSON,
|
||||
Class: pluginsv0alpha1.MetaSpecClassExternal,
|
||||
}
|
||||
|
||||
if gcomMeta.SignatureType != "" {
|
||||
signature := &pluginsv0alpha1.MetaV0alpha1SpecSignature{
|
||||
Status: pluginsv0alpha1.MetaV0alpha1SpecSignatureStatusValid,
|
||||
}
|
||||
|
||||
switch gcomMeta.SignatureType {
|
||||
case "grafana":
|
||||
sigType := pluginsv0alpha1.MetaV0alpha1SpecSignatureTypeGrafana
|
||||
signature.Type = &sigType
|
||||
case "commercial":
|
||||
sigType := pluginsv0alpha1.MetaV0alpha1SpecSignatureTypeCommercial
|
||||
signature.Type = &sigType
|
||||
case "community":
|
||||
sigType := pluginsv0alpha1.MetaV0alpha1SpecSignatureTypeCommunity
|
||||
signature.Type = &sigType
|
||||
case "private":
|
||||
sigType := pluginsv0alpha1.MetaV0alpha1SpecSignatureTypePrivate
|
||||
signature.Type = &sigType
|
||||
case "private-glob":
|
||||
sigType := pluginsv0alpha1.MetaV0alpha1SpecSignatureTypePrivateGlob
|
||||
signature.Type = &sigType
|
||||
}
|
||||
|
||||
if gcomMeta.SignedByOrg != "" {
|
||||
signature.Org = &gcomMeta.SignedByOrg
|
||||
}
|
||||
|
||||
metaSpec.Signature = signature
|
||||
}
|
||||
|
||||
// Set angular info
|
||||
metaSpec.Angular = &pluginsv0alpha1.MetaV0alpha1SpecAngular{
|
||||
Detected: gcomMeta.AngularDetected,
|
||||
}
|
||||
|
||||
return metaSpec
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package meta
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -12,15 +13,7 @@ import (
|
||||
|
||||
pluginsv0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/config"
|
||||
pluginsLoader "github.com/grafana/grafana/pkg/plugins/manager/loader"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/bootstrap"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/discovery"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/initialization"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/termination"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/pipeline/validation"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/sources"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -30,10 +23,9 @@ const (
|
||||
// CoreProvider retrieves plugin metadata for core plugins.
|
||||
type CoreProvider struct {
|
||||
mu sync.RWMutex
|
||||
loadedPlugins map[string]pluginsv0alpha1.MetaSpec
|
||||
loadedPlugins map[string]pluginsv0alpha1.MetaJSONData
|
||||
initialized bool
|
||||
ttl time.Duration
|
||||
loader pluginsLoader.Service
|
||||
}
|
||||
|
||||
// NewCoreProvider creates a new CoreProvider for core plugins.
|
||||
@@ -43,13 +35,9 @@ func NewCoreProvider() *CoreProvider {
|
||||
|
||||
// NewCoreProviderWithTTL creates a new CoreProvider with a custom TTL.
|
||||
func NewCoreProviderWithTTL(ttl time.Duration) *CoreProvider {
|
||||
cfg := &config.PluginManagementCfg{
|
||||
Features: config.Features{},
|
||||
}
|
||||
return &CoreProvider{
|
||||
loadedPlugins: make(map[string]pluginsv0alpha1.MetaSpec),
|
||||
loadedPlugins: make(map[string]pluginsv0alpha1.MetaJSONData),
|
||||
ttl: ttl,
|
||||
loader: createLoader(cfg),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,9 +76,9 @@ func (p *CoreProvider) GetMeta(ctx context.Context, pluginID, _ string) (*Result
|
||||
p.initialized = true
|
||||
}
|
||||
|
||||
if spec, found := p.loadedPlugins[pluginID]; found {
|
||||
if meta, found := p.loadedPlugins[pluginID]; found {
|
||||
return &Result{
|
||||
Meta: spec,
|
||||
Meta: meta,
|
||||
TTL: p.ttl,
|
||||
}, nil
|
||||
}
|
||||
@@ -98,8 +86,8 @@ func (p *CoreProvider) GetMeta(ctx context.Context, pluginID, _ string) (*Result
|
||||
return nil, ErrMetaNotFound
|
||||
}
|
||||
|
||||
// loadPlugins discovers and caches all core plugins by fully loading them.
|
||||
// Returns an error if the static root path cannot be found or if plugin loading fails.
|
||||
// loadPlugins discovers and caches all core plugins.
|
||||
// Returns an error if the static root path cannot be found or if plugin discovery fails.
|
||||
// This error will be handled gracefully by GetMeta, which will return ErrMetaNotFound
|
||||
// to allow other providers to handle the request.
|
||||
func (p *CoreProvider) loadPlugins(ctx context.Context) error {
|
||||
@@ -120,51 +108,496 @@ func (p *CoreProvider) loadPlugins(ctx context.Context) error {
|
||||
panelPath := filepath.Join(staticRootPath, "app", "plugins", "panel")
|
||||
|
||||
src := sources.NewLocalSource(plugins.ClassCore, []string{datasourcePath, panelPath})
|
||||
loadedPlugins, err := p.loader.Load(ctx, src)
|
||||
ps, err := src.Discover(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(loadedPlugins) == 0 {
|
||||
logging.DefaultLogger.Warn("CoreProvider: no core plugins found during loading")
|
||||
if len(ps) == 0 {
|
||||
logging.DefaultLogger.Warn("CoreProvider: no core plugins found during discovery")
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, plugin := range loadedPlugins {
|
||||
metaSpec := pluginToMetaSpec(plugin)
|
||||
p.loadedPlugins[plugin.ID] = metaSpec
|
||||
for _, bundle := range ps {
|
||||
meta := jsonDataToMetaJSONData(bundle.Primary.JSONData)
|
||||
p.loadedPlugins[bundle.Primary.JSONData.ID] = meta
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// createLoader creates a loader service configured for core plugins.
|
||||
func createLoader(cfg *config.PluginManagementCfg) pluginsLoader.Service {
|
||||
d := discovery.New(cfg, discovery.Opts{
|
||||
FilterFuncs: []discovery.FilterFunc{
|
||||
// Allow all plugin types for core plugins
|
||||
},
|
||||
})
|
||||
b := bootstrap.New(cfg, bootstrap.Opts{
|
||||
DecorateFuncs: []bootstrap.DecorateFunc{}, // no decoration required for metadata
|
||||
})
|
||||
v := validation.New(cfg, validation.Opts{
|
||||
ValidateFuncs: []validation.ValidateFunc{
|
||||
// Skip validation for core plugins - they're trusted
|
||||
},
|
||||
})
|
||||
i := initialization.New(cfg, initialization.Opts{
|
||||
InitializeFuncs: []initialization.InitializeFunc{
|
||||
// Skip initialization - we only need metadata, not running plugins
|
||||
},
|
||||
})
|
||||
t, _ := termination.New(cfg, termination.Opts{
|
||||
TerminateFuncs: []termination.TerminateFunc{
|
||||
// No termination needed for metadata-only loading
|
||||
},
|
||||
})
|
||||
// jsonDataToMetaJSONData converts a plugins.JSONData to a pluginsv0alpha1.MetaJSONData.
|
||||
// nolint:gocyclo
|
||||
func jsonDataToMetaJSONData(jsonData plugins.JSONData) pluginsv0alpha1.MetaJSONData {
|
||||
meta := pluginsv0alpha1.MetaJSONData{
|
||||
Id: jsonData.ID,
|
||||
Name: jsonData.Name,
|
||||
}
|
||||
|
||||
et := pluginerrs.ProvideErrorTracker()
|
||||
// Map plugin type
|
||||
switch jsonData.Type {
|
||||
case plugins.TypeApp:
|
||||
meta.Type = pluginsv0alpha1.MetaJSONDataTypeApp
|
||||
case plugins.TypeDataSource:
|
||||
meta.Type = pluginsv0alpha1.MetaJSONDataTypeDatasource
|
||||
case plugins.TypePanel:
|
||||
meta.Type = pluginsv0alpha1.MetaJSONDataTypePanel
|
||||
case plugins.TypeRenderer:
|
||||
meta.Type = pluginsv0alpha1.MetaJSONDataTypeRenderer
|
||||
}
|
||||
|
||||
return pluginsLoader.New(cfg, d, b, v, i, t, et)
|
||||
// Map Info
|
||||
meta.Info = pluginsv0alpha1.MetaInfo{
|
||||
Keywords: jsonData.Info.Keywords,
|
||||
Logos: pluginsv0alpha1.MetaV0alpha1InfoLogos{
|
||||
Small: jsonData.Info.Logos.Small,
|
||||
Large: jsonData.Info.Logos.Large,
|
||||
},
|
||||
Updated: jsonData.Info.Updated,
|
||||
Version: jsonData.Info.Version,
|
||||
}
|
||||
|
||||
if jsonData.Info.Description != "" {
|
||||
meta.Info.Description = &jsonData.Info.Description
|
||||
}
|
||||
|
||||
if jsonData.Info.Author.Name != "" || jsonData.Info.Author.URL != "" {
|
||||
author := &pluginsv0alpha1.MetaV0alpha1InfoAuthor{}
|
||||
if jsonData.Info.Author.Name != "" {
|
||||
author.Name = &jsonData.Info.Author.Name
|
||||
}
|
||||
if jsonData.Info.Author.URL != "" {
|
||||
author.Url = &jsonData.Info.Author.URL
|
||||
}
|
||||
meta.Info.Author = author
|
||||
}
|
||||
|
||||
if len(jsonData.Info.Links) > 0 {
|
||||
meta.Info.Links = make([]pluginsv0alpha1.MetaV0alpha1InfoLinks, 0, len(jsonData.Info.Links))
|
||||
for _, link := range jsonData.Info.Links {
|
||||
v0Link := pluginsv0alpha1.MetaV0alpha1InfoLinks{}
|
||||
if link.Name != "" {
|
||||
v0Link.Name = &link.Name
|
||||
}
|
||||
if link.URL != "" {
|
||||
v0Link.Url = &link.URL
|
||||
}
|
||||
meta.Info.Links = append(meta.Info.Links, v0Link)
|
||||
}
|
||||
}
|
||||
|
||||
if len(jsonData.Info.Screenshots) > 0 {
|
||||
meta.Info.Screenshots = make([]pluginsv0alpha1.MetaV0alpha1InfoScreenshots, 0, len(jsonData.Info.Screenshots))
|
||||
for _, screenshot := range jsonData.Info.Screenshots {
|
||||
v0Screenshot := pluginsv0alpha1.MetaV0alpha1InfoScreenshots{}
|
||||
if screenshot.Name != "" {
|
||||
v0Screenshot.Name = &screenshot.Name
|
||||
}
|
||||
if screenshot.Path != "" {
|
||||
v0Screenshot.Path = &screenshot.Path
|
||||
}
|
||||
meta.Info.Screenshots = append(meta.Info.Screenshots, v0Screenshot)
|
||||
}
|
||||
}
|
||||
|
||||
// Map Dependencies
|
||||
meta.Dependencies = pluginsv0alpha1.MetaDependencies{
|
||||
GrafanaDependency: jsonData.Dependencies.GrafanaDependency,
|
||||
}
|
||||
|
||||
if jsonData.Dependencies.GrafanaVersion != "" {
|
||||
meta.Dependencies.GrafanaVersion = &jsonData.Dependencies.GrafanaVersion
|
||||
}
|
||||
|
||||
if len(jsonData.Dependencies.Plugins) > 0 {
|
||||
meta.Dependencies.Plugins = make([]pluginsv0alpha1.MetaV0alpha1DependenciesPlugins, 0, len(jsonData.Dependencies.Plugins))
|
||||
for _, dep := range jsonData.Dependencies.Plugins {
|
||||
var depType pluginsv0alpha1.MetaV0alpha1DependenciesPluginsType
|
||||
switch dep.Type {
|
||||
case "app":
|
||||
depType = pluginsv0alpha1.MetaV0alpha1DependenciesPluginsTypeApp
|
||||
case "datasource":
|
||||
depType = pluginsv0alpha1.MetaV0alpha1DependenciesPluginsTypeDatasource
|
||||
case "panel":
|
||||
depType = pluginsv0alpha1.MetaV0alpha1DependenciesPluginsTypePanel
|
||||
}
|
||||
meta.Dependencies.Plugins = append(meta.Dependencies.Plugins, pluginsv0alpha1.MetaV0alpha1DependenciesPlugins{
|
||||
Id: dep.ID,
|
||||
Type: depType,
|
||||
Name: dep.Name,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(jsonData.Dependencies.Extensions.ExposedComponents) > 0 {
|
||||
meta.Dependencies.Extensions = &pluginsv0alpha1.MetaV0alpha1DependenciesExtensions{
|
||||
ExposedComponents: jsonData.Dependencies.Extensions.ExposedComponents,
|
||||
}
|
||||
}
|
||||
|
||||
// Map optional boolean fields
|
||||
if jsonData.Alerting {
|
||||
meta.Alerting = &jsonData.Alerting
|
||||
}
|
||||
if jsonData.Annotations {
|
||||
meta.Annotations = &jsonData.Annotations
|
||||
}
|
||||
if jsonData.AutoEnabled {
|
||||
meta.AutoEnabled = &jsonData.AutoEnabled
|
||||
}
|
||||
if jsonData.Backend {
|
||||
meta.Backend = &jsonData.Backend
|
||||
}
|
||||
if jsonData.BuiltIn {
|
||||
meta.BuiltIn = &jsonData.BuiltIn
|
||||
}
|
||||
if jsonData.HideFromList {
|
||||
meta.HideFromList = &jsonData.HideFromList
|
||||
}
|
||||
if jsonData.Logs {
|
||||
meta.Logs = &jsonData.Logs
|
||||
}
|
||||
if jsonData.Metrics {
|
||||
meta.Metrics = &jsonData.Metrics
|
||||
}
|
||||
if jsonData.MultiValueFilterOperators {
|
||||
meta.MultiValueFilterOperators = &jsonData.MultiValueFilterOperators
|
||||
}
|
||||
if jsonData.Preload {
|
||||
meta.Preload = &jsonData.Preload
|
||||
}
|
||||
if jsonData.SkipDataQuery {
|
||||
meta.SkipDataQuery = &jsonData.SkipDataQuery
|
||||
}
|
||||
if jsonData.Streaming {
|
||||
meta.Streaming = &jsonData.Streaming
|
||||
}
|
||||
if jsonData.Tracing {
|
||||
meta.Tracing = &jsonData.Tracing
|
||||
}
|
||||
|
||||
// Map category
|
||||
if jsonData.Category != "" {
|
||||
var category pluginsv0alpha1.MetaJSONDataCategory
|
||||
switch jsonData.Category {
|
||||
case "tsdb":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryTsdb
|
||||
case "logging":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryLogging
|
||||
case "cloud":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryCloud
|
||||
case "tracing":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryTracing
|
||||
case "profiling":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryProfiling
|
||||
case "sql":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategorySql
|
||||
case "enterprise":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryEnterprise
|
||||
case "iot":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryIot
|
||||
case "other":
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryOther
|
||||
default:
|
||||
category = pluginsv0alpha1.MetaJSONDataCategoryOther
|
||||
}
|
||||
meta.Category = &category
|
||||
}
|
||||
|
||||
// Map state
|
||||
if jsonData.State != "" {
|
||||
var state pluginsv0alpha1.MetaJSONDataState
|
||||
switch jsonData.State {
|
||||
case plugins.ReleaseStateAlpha:
|
||||
state = pluginsv0alpha1.MetaJSONDataStateAlpha
|
||||
case plugins.ReleaseStateBeta:
|
||||
state = pluginsv0alpha1.MetaJSONDataStateBeta
|
||||
default:
|
||||
}
|
||||
if state != "" {
|
||||
meta.State = &state
|
||||
}
|
||||
}
|
||||
|
||||
// Map executable
|
||||
if jsonData.Executable != "" {
|
||||
meta.Executable = &jsonData.Executable
|
||||
}
|
||||
|
||||
// Map QueryOptions
|
||||
if len(jsonData.QueryOptions) > 0 {
|
||||
queryOptions := &pluginsv0alpha1.MetaQueryOptions{}
|
||||
if val, ok := jsonData.QueryOptions["maxDataPoints"]; ok {
|
||||
queryOptions.MaxDataPoints = &val
|
||||
}
|
||||
if val, ok := jsonData.QueryOptions["minInterval"]; ok {
|
||||
queryOptions.MinInterval = &val
|
||||
}
|
||||
if val, ok := jsonData.QueryOptions["cacheTimeout"]; ok {
|
||||
queryOptions.CacheTimeout = &val
|
||||
}
|
||||
meta.QueryOptions = queryOptions
|
||||
}
|
||||
|
||||
// Map Includes
|
||||
if len(jsonData.Includes) > 0 {
|
||||
meta.Includes = make([]pluginsv0alpha1.MetaInclude, 0, len(jsonData.Includes))
|
||||
for _, include := range jsonData.Includes {
|
||||
v0Include := pluginsv0alpha1.MetaInclude{}
|
||||
if include.UID != "" {
|
||||
v0Include.Uid = &include.UID
|
||||
}
|
||||
if include.Type != "" {
|
||||
var includeType pluginsv0alpha1.MetaIncludeType
|
||||
switch include.Type {
|
||||
case "dashboard":
|
||||
includeType = pluginsv0alpha1.MetaIncludeTypeDashboard
|
||||
case "page":
|
||||
includeType = pluginsv0alpha1.MetaIncludeTypePage
|
||||
case "panel":
|
||||
includeType = pluginsv0alpha1.MetaIncludeTypePanel
|
||||
case "datasource":
|
||||
includeType = pluginsv0alpha1.MetaIncludeTypeDatasource
|
||||
}
|
||||
v0Include.Type = &includeType
|
||||
}
|
||||
if include.Name != "" {
|
||||
v0Include.Name = &include.Name
|
||||
}
|
||||
if include.Component != "" {
|
||||
v0Include.Component = &include.Component
|
||||
}
|
||||
if include.Role != "" {
|
||||
var role pluginsv0alpha1.MetaIncludeRole
|
||||
switch include.Role {
|
||||
case "Admin":
|
||||
role = pluginsv0alpha1.MetaIncludeRoleAdmin
|
||||
case "Editor":
|
||||
role = pluginsv0alpha1.MetaIncludeRoleEditor
|
||||
case "Viewer":
|
||||
role = pluginsv0alpha1.MetaIncludeRoleViewer
|
||||
}
|
||||
v0Include.Role = &role
|
||||
}
|
||||
if include.Action != "" {
|
||||
v0Include.Action = &include.Action
|
||||
}
|
||||
if include.Path != "" {
|
||||
v0Include.Path = &include.Path
|
||||
}
|
||||
if include.AddToNav {
|
||||
v0Include.AddToNav = &include.AddToNav
|
||||
}
|
||||
if include.DefaultNav {
|
||||
v0Include.DefaultNav = &include.DefaultNav
|
||||
}
|
||||
if include.Icon != "" {
|
||||
v0Include.Icon = &include.Icon
|
||||
}
|
||||
meta.Includes = append(meta.Includes, v0Include)
|
||||
}
|
||||
}
|
||||
|
||||
// Map Routes
|
||||
if len(jsonData.Routes) > 0 {
|
||||
meta.Routes = make([]pluginsv0alpha1.MetaRoute, 0, len(jsonData.Routes))
|
||||
for _, route := range jsonData.Routes {
|
||||
v0Route := pluginsv0alpha1.MetaRoute{}
|
||||
if route.Path != "" {
|
||||
v0Route.Path = &route.Path
|
||||
}
|
||||
if route.Method != "" {
|
||||
v0Route.Method = &route.Method
|
||||
}
|
||||
if route.URL != "" {
|
||||
v0Route.Url = &route.URL
|
||||
}
|
||||
if route.ReqRole != "" {
|
||||
reqRole := string(route.ReqRole)
|
||||
v0Route.ReqRole = &reqRole
|
||||
}
|
||||
if route.ReqAction != "" {
|
||||
v0Route.ReqAction = &route.ReqAction
|
||||
}
|
||||
if len(route.Headers) > 0 {
|
||||
headers := make([]string, 0, len(route.Headers))
|
||||
for _, header := range route.Headers {
|
||||
headers = append(headers, header.Name+": "+header.Content)
|
||||
}
|
||||
v0Route.Headers = headers
|
||||
}
|
||||
if len(route.URLParams) > 0 {
|
||||
v0Route.UrlParams = make([]pluginsv0alpha1.MetaV0alpha1RouteUrlParams, 0, len(route.URLParams))
|
||||
for _, param := range route.URLParams {
|
||||
v0Param := pluginsv0alpha1.MetaV0alpha1RouteUrlParams{}
|
||||
if param.Name != "" {
|
||||
v0Param.Name = ¶m.Name
|
||||
}
|
||||
if param.Content != "" {
|
||||
v0Param.Content = ¶m.Content
|
||||
}
|
||||
v0Route.UrlParams = append(v0Route.UrlParams, v0Param)
|
||||
}
|
||||
}
|
||||
if route.TokenAuth != nil {
|
||||
v0Route.TokenAuth = &pluginsv0alpha1.MetaV0alpha1RouteTokenAuth{}
|
||||
if route.TokenAuth.Url != "" {
|
||||
v0Route.TokenAuth.Url = &route.TokenAuth.Url
|
||||
}
|
||||
if len(route.TokenAuth.Scopes) > 0 {
|
||||
v0Route.TokenAuth.Scopes = route.TokenAuth.Scopes
|
||||
}
|
||||
if len(route.TokenAuth.Params) > 0 {
|
||||
v0Route.TokenAuth.Params = make(map[string]interface{})
|
||||
for k, v := range route.TokenAuth.Params {
|
||||
v0Route.TokenAuth.Params[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
if route.JwtTokenAuth != nil {
|
||||
v0Route.JwtTokenAuth = &pluginsv0alpha1.MetaV0alpha1RouteJwtTokenAuth{}
|
||||
if route.JwtTokenAuth.Url != "" {
|
||||
v0Route.JwtTokenAuth.Url = &route.JwtTokenAuth.Url
|
||||
}
|
||||
if len(route.JwtTokenAuth.Scopes) > 0 {
|
||||
v0Route.JwtTokenAuth.Scopes = route.JwtTokenAuth.Scopes
|
||||
}
|
||||
if len(route.JwtTokenAuth.Params) > 0 {
|
||||
v0Route.JwtTokenAuth.Params = make(map[string]interface{})
|
||||
for k, v := range route.JwtTokenAuth.Params {
|
||||
v0Route.JwtTokenAuth.Params[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(route.Body) > 0 {
|
||||
var bodyMap map[string]interface{}
|
||||
if err := json.Unmarshal(route.Body, &bodyMap); err == nil {
|
||||
v0Route.Body = bodyMap
|
||||
}
|
||||
}
|
||||
meta.Routes = append(meta.Routes, v0Route)
|
||||
}
|
||||
}
|
||||
|
||||
// Map Extensions
|
||||
if len(jsonData.Extensions.AddedLinks) > 0 || len(jsonData.Extensions.AddedComponents) > 0 ||
|
||||
len(jsonData.Extensions.ExposedComponents) > 0 || len(jsonData.Extensions.ExtensionPoints) > 0 {
|
||||
extensions := &pluginsv0alpha1.MetaExtensions{}
|
||||
|
||||
if len(jsonData.Extensions.AddedLinks) > 0 {
|
||||
extensions.AddedLinks = make([]pluginsv0alpha1.MetaV0alpha1ExtensionsAddedLinks, 0, len(jsonData.Extensions.AddedLinks))
|
||||
for _, link := range jsonData.Extensions.AddedLinks {
|
||||
v0Link := pluginsv0alpha1.MetaV0alpha1ExtensionsAddedLinks{
|
||||
Targets: link.Targets,
|
||||
Title: link.Title,
|
||||
}
|
||||
if link.Description != "" {
|
||||
v0Link.Description = &link.Description
|
||||
}
|
||||
extensions.AddedLinks = append(extensions.AddedLinks, v0Link)
|
||||
}
|
||||
}
|
||||
|
||||
if len(jsonData.Extensions.AddedComponents) > 0 {
|
||||
extensions.AddedComponents = make([]pluginsv0alpha1.MetaV0alpha1ExtensionsAddedComponents, 0, len(jsonData.Extensions.AddedComponents))
|
||||
for _, comp := range jsonData.Extensions.AddedComponents {
|
||||
v0Comp := pluginsv0alpha1.MetaV0alpha1ExtensionsAddedComponents{
|
||||
Targets: comp.Targets,
|
||||
Title: comp.Title,
|
||||
}
|
||||
if comp.Description != "" {
|
||||
v0Comp.Description = &comp.Description
|
||||
}
|
||||
extensions.AddedComponents = append(extensions.AddedComponents, v0Comp)
|
||||
}
|
||||
}
|
||||
|
||||
if len(jsonData.Extensions.ExposedComponents) > 0 {
|
||||
extensions.ExposedComponents = make([]pluginsv0alpha1.MetaV0alpha1ExtensionsExposedComponents, 0, len(jsonData.Extensions.ExposedComponents))
|
||||
for _, comp := range jsonData.Extensions.ExposedComponents {
|
||||
v0Comp := pluginsv0alpha1.MetaV0alpha1ExtensionsExposedComponents{
|
||||
Id: comp.Id,
|
||||
}
|
||||
if comp.Title != "" {
|
||||
v0Comp.Title = &comp.Title
|
||||
}
|
||||
if comp.Description != "" {
|
||||
v0Comp.Description = &comp.Description
|
||||
}
|
||||
extensions.ExposedComponents = append(extensions.ExposedComponents, v0Comp)
|
||||
}
|
||||
}
|
||||
|
||||
if len(jsonData.Extensions.ExtensionPoints) > 0 {
|
||||
extensions.ExtensionPoints = make([]pluginsv0alpha1.MetaV0alpha1ExtensionsExtensionPoints, 0, len(jsonData.Extensions.ExtensionPoints))
|
||||
for _, point := range jsonData.Extensions.ExtensionPoints {
|
||||
v0Point := pluginsv0alpha1.MetaV0alpha1ExtensionsExtensionPoints{
|
||||
Id: point.Id,
|
||||
}
|
||||
if point.Title != "" {
|
||||
v0Point.Title = &point.Title
|
||||
}
|
||||
if point.Description != "" {
|
||||
v0Point.Description = &point.Description
|
||||
}
|
||||
extensions.ExtensionPoints = append(extensions.ExtensionPoints, v0Point)
|
||||
}
|
||||
}
|
||||
|
||||
meta.Extensions = extensions
|
||||
}
|
||||
|
||||
// Map Roles
|
||||
if len(jsonData.Roles) > 0 {
|
||||
meta.Roles = make([]pluginsv0alpha1.MetaRole, 0, len(jsonData.Roles))
|
||||
for _, role := range jsonData.Roles {
|
||||
v0Role := pluginsv0alpha1.MetaRole{
|
||||
Grants: role.Grants,
|
||||
}
|
||||
if role.Role.Name != "" || role.Role.Description != "" || len(role.Role.Permissions) > 0 {
|
||||
v0RoleRole := &pluginsv0alpha1.MetaV0alpha1RoleRole{}
|
||||
if role.Role.Name != "" {
|
||||
v0RoleRole.Name = &role.Role.Name
|
||||
}
|
||||
if role.Role.Description != "" {
|
||||
v0RoleRole.Description = &role.Role.Description
|
||||
}
|
||||
if len(role.Role.Permissions) > 0 {
|
||||
v0RoleRole.Permissions = make([]pluginsv0alpha1.MetaV0alpha1RoleRolePermissions, 0, len(role.Role.Permissions))
|
||||
for _, perm := range role.Role.Permissions {
|
||||
v0Perm := pluginsv0alpha1.MetaV0alpha1RoleRolePermissions{}
|
||||
if perm.Action != "" {
|
||||
v0Perm.Action = &perm.Action
|
||||
}
|
||||
if perm.Scope != "" {
|
||||
v0Perm.Scope = &perm.Scope
|
||||
}
|
||||
v0RoleRole.Permissions = append(v0RoleRole.Permissions, v0Perm)
|
||||
}
|
||||
}
|
||||
v0Role.Role = v0RoleRole
|
||||
}
|
||||
meta.Roles = append(meta.Roles, v0Role)
|
||||
}
|
||||
}
|
||||
|
||||
// Map IAM
|
||||
if jsonData.IAM != nil && len(jsonData.IAM.Permissions) > 0 {
|
||||
iam := &pluginsv0alpha1.MetaIAM{
|
||||
Permissions: make([]pluginsv0alpha1.MetaV0alpha1IAMPermissions, 0, len(jsonData.IAM.Permissions)),
|
||||
}
|
||||
for _, perm := range jsonData.IAM.Permissions {
|
||||
v0Perm := pluginsv0alpha1.MetaV0alpha1IAMPermissions{}
|
||||
if perm.Action != "" {
|
||||
v0Perm.Action = &perm.Action
|
||||
}
|
||||
if perm.Scope != "" {
|
||||
v0Perm.Scope = &perm.Scope
|
||||
}
|
||||
iam.Permissions = append(iam.Permissions, v0Perm)
|
||||
}
|
||||
meta.Iam = iam
|
||||
}
|
||||
|
||||
return meta
|
||||
}
|
||||
|
||||
@@ -22,12 +22,10 @@ func TestCoreProvider_GetMeta(t *testing.T) {
|
||||
t.Run("returns cached plugin when available", func(t *testing.T) {
|
||||
provider := NewCoreProvider()
|
||||
|
||||
expectedMeta := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
},
|
||||
expectedMeta := pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
}
|
||||
|
||||
provider.mu.Lock()
|
||||
@@ -60,12 +58,10 @@ func TestCoreProvider_GetMeta(t *testing.T) {
|
||||
t.Run("ignores version parameter", func(t *testing.T) {
|
||||
provider := NewCoreProvider()
|
||||
|
||||
expectedMeta := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
},
|
||||
expectedMeta := pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
}
|
||||
|
||||
provider.mu.Lock()
|
||||
@@ -85,12 +81,10 @@ func TestCoreProvider_GetMeta(t *testing.T) {
|
||||
customTTL := 2 * time.Hour
|
||||
provider := NewCoreProviderWithTTL(customTTL)
|
||||
|
||||
expectedMeta := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
},
|
||||
expectedMeta := pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
}
|
||||
|
||||
provider.mu.Lock()
|
||||
@@ -232,8 +226,8 @@ func TestCoreProvider_loadPlugins(t *testing.T) {
|
||||
if loaded {
|
||||
result, err := provider.GetMeta(ctx, "test-datasource", "1.0.0")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "test-datasource", result.Meta.PluginJson.Id)
|
||||
assert.Equal(t, "Test Datasource", result.Meta.PluginJson.Name)
|
||||
assert.Equal(t, "test-datasource", result.Meta.Id)
|
||||
assert.Equal(t, "Test Datasource", result.Meta.Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package meta
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultLocalTTL = 1 * time.Hour
|
||||
)
|
||||
|
||||
// PluginAssetsCalculator is an interface for calculating plugin asset information.
|
||||
// LocalProvider requires this to calculate loading strategy and module hash.
|
||||
type PluginAssetsCalculator interface {
|
||||
LoadingStrategy(ctx context.Context, p pluginstore.Plugin) plugins.LoadingStrategy
|
||||
ModuleHash(ctx context.Context, p pluginstore.Plugin) string
|
||||
}
|
||||
|
||||
// LocalProvider retrieves plugin metadata for locally installed plugins.
|
||||
// It uses the plugin store to access plugins that have already been loaded.
|
||||
type LocalProvider struct {
|
||||
store pluginstore.Store
|
||||
pluginAssets PluginAssetsCalculator
|
||||
}
|
||||
|
||||
// NewLocalProvider creates a new LocalProvider for locally installed plugins.
|
||||
// pluginAssets is required for calculating loading strategy and module hash.
|
||||
func NewLocalProvider(pluginStore pluginstore.Store, pluginAssets PluginAssetsCalculator) *LocalProvider {
|
||||
return &LocalProvider{
|
||||
store: pluginStore,
|
||||
pluginAssets: pluginAssets,
|
||||
}
|
||||
}
|
||||
|
||||
// GetMeta retrieves plugin metadata for locally installed plugins.
|
||||
func (p *LocalProvider) GetMeta(ctx context.Context, pluginID, version string) (*Result, error) {
|
||||
plugin, exists := p.store.Plugin(ctx, pluginID)
|
||||
if !exists {
|
||||
return nil, ErrMetaNotFound
|
||||
}
|
||||
|
||||
loadingStrategy := p.pluginAssets.LoadingStrategy(ctx, plugin)
|
||||
moduleHash := p.pluginAssets.ModuleHash(ctx, plugin)
|
||||
|
||||
spec := pluginStorePluginToMeta(plugin, loadingStrategy, moduleHash)
|
||||
return &Result{
|
||||
Meta: spec,
|
||||
TTL: defaultLocalTTL,
|
||||
}, nil
|
||||
}
|
||||
@@ -16,7 +16,7 @@ const (
|
||||
|
||||
// cachedMeta represents a cached metadata entry with expiration time
|
||||
type cachedMeta struct {
|
||||
meta pluginsv0alpha1.MetaSpec
|
||||
meta pluginsv0alpha1.MetaJSONData
|
||||
ttl time.Duration
|
||||
expiresAt time.Time
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func (pm *ProviderManager) GetMeta(ctx context.Context, pluginID, version string
|
||||
if err == nil {
|
||||
// Don't cache results with a zero TTL
|
||||
if result.TTL == 0 {
|
||||
return result, nil
|
||||
continue
|
||||
}
|
||||
|
||||
pm.cacheMu.Lock()
|
||||
|
||||
@@ -35,12 +35,10 @@ func TestProviderManager_GetMeta(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("returns cached result when available and not expired", func(t *testing.T) {
|
||||
cachedMeta := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
},
|
||||
cachedMeta := pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
}
|
||||
|
||||
provider := &mockProvider{
|
||||
@@ -62,10 +60,8 @@ func TestProviderManager_GetMeta(t *testing.T) {
|
||||
|
||||
provider.getMetaFunc = func(ctx context.Context, pluginID, version string) (*Result, error) {
|
||||
return &Result{
|
||||
Meta: pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: pluginsv0alpha1.MetaJSONData{Id: "different"},
|
||||
},
|
||||
TTL: time.Hour,
|
||||
Meta: pluginsv0alpha1.MetaJSONData{Id: "different"},
|
||||
TTL: time.Hour,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -77,12 +73,10 @@ func TestProviderManager_GetMeta(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("fetches from provider when not cached", func(t *testing.T) {
|
||||
expectedMeta := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
},
|
||||
expectedMeta := pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
}
|
||||
expectedTTL := 2 * time.Hour
|
||||
|
||||
@@ -113,16 +107,19 @@ func TestProviderManager_GetMeta(t *testing.T) {
|
||||
assert.Equal(t, expectedTTL, cached.ttl)
|
||||
})
|
||||
|
||||
t.Run("does not cache result with zero TTL", func(t *testing.T) {
|
||||
zeroTTLMeta := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Zero TTL Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
},
|
||||
t.Run("does not cache result with zero TTL and tries next provider", func(t *testing.T) {
|
||||
zeroTTLMeta := pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Zero TTL Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
}
|
||||
expectedMeta := pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
}
|
||||
|
||||
provider := &mockProvider{
|
||||
provider1 := &mockProvider{
|
||||
getMetaFunc: func(ctx context.Context, pluginID, version string) (*Result, error) {
|
||||
return &Result{
|
||||
Meta: zeroTTLMeta,
|
||||
@@ -130,30 +127,37 @@ func TestProviderManager_GetMeta(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
provider2 := &mockProvider{
|
||||
getMetaFunc: func(ctx context.Context, pluginID, version string) (*Result, error) {
|
||||
return &Result{
|
||||
Meta: expectedMeta,
|
||||
TTL: time.Hour,
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
pm := NewProviderManager(provider)
|
||||
pm := NewProviderManager(provider1, provider2)
|
||||
|
||||
result, err := pm.GetMeta(ctx, "test-plugin", "1.0.0")
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, result)
|
||||
assert.Equal(t, zeroTTLMeta, result.Meta)
|
||||
assert.Equal(t, time.Duration(0), result.TTL)
|
||||
assert.Equal(t, expectedMeta, result.Meta)
|
||||
|
||||
pm.cacheMu.RLock()
|
||||
_, exists := pm.cache["test-plugin:1.0.0"]
|
||||
cached, exists := pm.cache["test-plugin:1.0.0"]
|
||||
pm.cacheMu.RUnlock()
|
||||
|
||||
assert.False(t, exists, "zero TTL results should not be cached")
|
||||
assert.True(t, exists)
|
||||
assert.Equal(t, expectedMeta, cached.meta)
|
||||
assert.Equal(t, time.Hour, cached.ttl)
|
||||
})
|
||||
|
||||
t.Run("tries next provider when first returns ErrMetaNotFound", func(t *testing.T) {
|
||||
expectedMeta := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
},
|
||||
expectedMeta := pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
}
|
||||
|
||||
provider1 := &mockProvider{
|
||||
@@ -225,19 +229,15 @@ func TestProviderManager_GetMeta(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("skips expired cache entries", func(t *testing.T) {
|
||||
expiredMeta := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Expired Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
},
|
||||
expiredMeta := pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Expired Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
}
|
||||
expectedMeta := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
},
|
||||
expectedMeta := pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Test Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
}
|
||||
|
||||
callCount := 0
|
||||
@@ -272,19 +272,15 @@ func TestProviderManager_GetMeta(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("uses first successful provider", func(t *testing.T) {
|
||||
expectedMeta1 := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Provider 1 Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
},
|
||||
expectedMeta1 := pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Provider 1 Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
}
|
||||
expectedMeta2 := pluginsv0alpha1.MetaSpec{
|
||||
PluginJson: pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Provider 2 Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
},
|
||||
expectedMeta2 := pluginsv0alpha1.MetaJSONData{
|
||||
Id: "test-plugin",
|
||||
Name: "Provider 2 Plugin",
|
||||
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
|
||||
}
|
||||
|
||||
provider1 := &mockProvider{
|
||||
@@ -335,9 +331,9 @@ func TestProviderManager_Run(t *testing.T) {
|
||||
|
||||
func TestProviderManager_cleanupExpired(t *testing.T) {
|
||||
t.Run("removes expired entries", func(t *testing.T) {
|
||||
validMeta := pluginsv0alpha1.MetaSpec{PluginJson: pluginsv0alpha1.MetaJSONData{Id: "valid"}}
|
||||
expiredMeta1 := pluginsv0alpha1.MetaSpec{PluginJson: pluginsv0alpha1.MetaJSONData{Id: "expired1"}}
|
||||
expiredMeta2 := pluginsv0alpha1.MetaSpec{PluginJson: pluginsv0alpha1.MetaJSONData{Id: "expired2"}}
|
||||
validMeta := pluginsv0alpha1.MetaJSONData{Id: "valid"}
|
||||
expiredMeta1 := pluginsv0alpha1.MetaJSONData{Id: "expired1"}
|
||||
expiredMeta2 := pluginsv0alpha1.MetaJSONData{Id: "expired2"}
|
||||
|
||||
provider := &mockProvider{
|
||||
getMetaFunc: func(ctx context.Context, pluginID, version string) (*Result, error) {
|
||||
|
||||
@@ -14,7 +14,7 @@ var (
|
||||
|
||||
// Result contains plugin metadata along with its recommended TTL.
|
||||
type Result struct {
|
||||
Meta pluginsv0alpha1.MetaSpec
|
||||
Meta pluginsv0alpha1.MetaJSONData
|
||||
TTL time.Duration
|
||||
}
|
||||
|
||||
|
||||
@@ -121,19 +121,8 @@ func (s *MetaStorage) List(ctx context.Context, options *internalversion.ListOpt
|
||||
continue
|
||||
}
|
||||
|
||||
pluginMeta := pluginsv0alpha1.Meta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: plugin.Name,
|
||||
Namespace: plugin.Namespace,
|
||||
},
|
||||
Spec: result.Meta,
|
||||
}
|
||||
pluginMeta.SetGroupVersionKind(schema.GroupVersionKind{
|
||||
Group: pluginsv0alpha1.APIGroup,
|
||||
Version: pluginsv0alpha1.APIVersion,
|
||||
Kind: pluginsv0alpha1.MetaKind().Kind(),
|
||||
})
|
||||
metaItems = append(metaItems, pluginMeta)
|
||||
pluginMeta := createMetaFromMetaJSONData(result.Meta, plugin.Name, plugin.Namespace)
|
||||
metaItems = append(metaItems, *pluginMeta)
|
||||
}
|
||||
|
||||
list := &pluginsv0alpha1.MetaList{
|
||||
@@ -180,18 +169,27 @@ func (s *MetaStorage) Get(ctx context.Context, name string, options *metav1.GetO
|
||||
return nil, apierrors.NewInternalError(fmt.Errorf("failed to fetch plugin metadata: %w", err))
|
||||
}
|
||||
|
||||
return createMetaFromMetaJSONData(result.Meta, name, ns.Value), nil
|
||||
}
|
||||
|
||||
// createMetaFromMetaJSONData creates a Meta k8s object from MetaJSONData and plugin metadata.
|
||||
func createMetaFromMetaJSONData(pluginJSON pluginsv0alpha1.MetaJSONData, name, namespace string) *pluginsv0alpha1.Meta {
|
||||
pluginMeta := &pluginsv0alpha1.Meta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: plugin.Name,
|
||||
Namespace: plugin.Namespace,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: pluginsv0alpha1.MetaSpec{
|
||||
PluginJSON: pluginJSON,
|
||||
},
|
||||
Spec: result.Meta,
|
||||
}
|
||||
|
||||
// Set the GroupVersionKind
|
||||
pluginMeta.SetGroupVersionKind(schema.GroupVersionKind{
|
||||
Group: pluginsv0alpha1.APIGroup,
|
||||
Version: pluginsv0alpha1.APIVersion,
|
||||
Kind: pluginsv0alpha1.MetaKind().Kind(),
|
||||
})
|
||||
|
||||
return pluginMeta, nil
|
||||
return pluginMeta
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ require (
|
||||
github.com/google/go-github/v70 v70.0.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f
|
||||
github.com/grafana/grafana-app-sdk v0.48.7
|
||||
github.com/grafana/grafana-app-sdk/logging v0.48.7
|
||||
github.com/grafana/grafana/apps/secret v0.0.0-20250902093454-b56b7add012f
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2
|
||||
@@ -29,7 +28,6 @@ require (
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
github.com/getkin/kin-openapi v0.133.0 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
@@ -56,20 +54,13 @@ require (
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 // indirect
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect
|
||||
github.com/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/grafana/grafana-app-sdk v0.48.7 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.1 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
|
||||
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/perimeterx/marshmallow v1.1.5 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
@@ -77,7 +68,6 @@ require (
|
||||
github.com/prometheus/procfs v0.19.2 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/woodsbury/decimal128 v1.4.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel v1.39.0 // indirect
|
||||
|
||||
@@ -14,8 +14,6 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ=
|
||||
github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE=
|
||||
github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
|
||||
github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
|
||||
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
|
||||
@@ -61,8 +59,6 @@ github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6
|
||||
github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
|
||||
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=
|
||||
@@ -102,13 +98,6 @@ github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2 h
|
||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2/go.mod h1:RRvSjHH12/PnQaXraMO65jUhVu8n59mzvhfIMBETnV4=
|
||||
github.com/grafana/nanogit v0.3.0 h1:XNEef+4Vi+465ZITJs/g/xgnDRJbWhhJ7iQrAnWZ0oQ=
|
||||
github.com/grafana/nanogit v0.3.0/go.mod h1:6s6CCTpyMOHPpcUZaLGI+rgBEKdmxVbhqSGgCK13j7Y=
|
||||
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=
|
||||
@@ -121,8 +110,6 @@ 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.1 h1:LbtsOm5WAswyWbvTEOqhypdPeZzHavpZx96/n553mR8=
|
||||
github.com/mailru/easyjson v0.9.1/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/migueleliasweb/go-github-mock v1.1.0 h1:GKaOBPsrPGkAKgtfuWY8MclS1xR6MInkx1SexJucMwE=
|
||||
github.com/migueleliasweb/go-github-mock v1.1.0/go.mod h1:pYe/XlGs4BGMfRY4vmeixVsODHnVDDhJ9zoi0qzSMHc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@@ -131,22 +118,14 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
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/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/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=
|
||||
@@ -171,10 +150,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/woodsbury/decimal128 v1.4.0 h1:xJATj7lLu4f2oObouMt2tgGiElE5gO6mSWUjQsBgUlc=
|
||||
github.com/woodsbury/decimal128 v1.4.0/go.mod h1:BP46FUrVjVhdTbKT+XuQh2xfQaGki9LMIRJSFuh6THU=
|
||||
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=
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package repository
|
||||
|
||||
manifest: {
|
||||
appName: "provisioning"
|
||||
groupOverride: "provisioning.grafana.app"
|
||||
preferredVersion: "v0alpha1"
|
||||
kinds: [
|
||||
appName: "provisioning"
|
||||
groupOverride: "provisioning.grafana.app"
|
||||
kinds: [
|
||||
repository,
|
||||
connection
|
||||
]
|
||||
|
||||
@@ -80,7 +80,7 @@ repository: {
|
||||
// Enabled must be saved as true before any sync job will run
|
||||
enabled: bool
|
||||
// Where values should be saved
|
||||
target: "instance" | "folder"
|
||||
target: "unified" | "legacy"
|
||||
// When non-zero, the sync will run periodically
|
||||
intervalSeconds?: int
|
||||
}
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
//
|
||||
// This file is generated by grafana-app-sdk
|
||||
// DO NOT EDIT
|
||||
//
|
||||
|
||||
package manifestdata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana-app-sdk/app"
|
||||
"github.com/grafana/grafana-app-sdk/resource"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
var appManifestData = app.ManifestData{
|
||||
AppName: "provisioning",
|
||||
Group: "provisioning.grafana.app",
|
||||
PreferredVersion: "v0alpha1",
|
||||
Versions: []app.ManifestVersion{},
|
||||
}
|
||||
|
||||
func LocalManifest() app.Manifest {
|
||||
return app.NewEmbeddedManifest(appManifestData)
|
||||
}
|
||||
|
||||
func RemoteManifest() app.Manifest {
|
||||
return app.NewAPIServerManifest("provisioning")
|
||||
}
|
||||
|
||||
var kindVersionToGoType = map[string]resource.Kind{}
|
||||
|
||||
// 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.
|
||||
// Resource routes (those without a kind) should prefix their route with "<namespace>/" if the route is namespaced (otherwise the route is assumed to be cluster-scope)
|
||||
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
|
||||
}
|
||||
|
||||
var customRouteToGoParamsType = map[string]runtime.Object{}
|
||||
|
||||
func ManifestCustomRouteQueryAssociator(kind, version, path, verb string) (goType runtime.Object, exists bool) {
|
||||
if len(path) > 0 && path[0] == '/' {
|
||||
path = path[1:]
|
||||
}
|
||||
goType, exists = customRouteToGoParamsType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))]
|
||||
return goType, exists
|
||||
}
|
||||
|
||||
var customRouteToGoRequestBodyType = map[string]any{}
|
||||
|
||||
func ManifestCustomRouteRequestBodyAssociator(kind, version, path, verb string) (goType any, exists bool) {
|
||||
if len(path) > 0 && path[0] == '/' {
|
||||
path = path[1:]
|
||||
}
|
||||
goType, exists = customRouteToGoRequestBodyType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))]
|
||||
return goType, exists
|
||||
}
|
||||
|
||||
type GoTypeAssociator struct{}
|
||||
|
||||
func NewGoTypeAssociator() *GoTypeAssociator {
|
||||
return &GoTypeAssociator{}
|
||||
}
|
||||
|
||||
func (g *GoTypeAssociator) KindToGoType(kind, version string) (goType resource.Kind, exists bool) {
|
||||
return ManifestGoTypeAssociator(kind, version)
|
||||
}
|
||||
func (g *GoTypeAssociator) CustomRouteReturnGoType(kind, version, path, verb string) (goType any, exists bool) {
|
||||
return ManifestCustomRouteResponsesAssociator(kind, version, path, verb)
|
||||
}
|
||||
func (g *GoTypeAssociator) CustomRouteQueryGoType(kind, version, path, verb string) (goType runtime.Object, exists bool) {
|
||||
return ManifestCustomRouteQueryAssociator(kind, version, path, verb)
|
||||
}
|
||||
func (g *GoTypeAssociator) CustomRouteRequestBodyGoType(kind, version, path, verb string) (goType any, exists bool) {
|
||||
return ManifestCustomRouteRequestBodyAssociator(kind, version, path, verb)
|
||||
}
|
||||
@@ -136,6 +136,9 @@ type ExportJobOptions struct {
|
||||
}
|
||||
|
||||
type MigrateJobOptions struct {
|
||||
// Preserve history (if possible)
|
||||
History bool `json:"history,omitempty"`
|
||||
|
||||
// Message to use when committing the changes in a single commit
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
@@ -9,6 +9,11 @@ import (
|
||||
type RepositoryViewList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// The backend is using legacy storage
|
||||
// FIXME: Not sure where this should be exposed... but we need it somewhere
|
||||
// The UI should force the onboarding workflow when this is true
|
||||
LegacyStorage bool `json:"legacyStorage,omitempty"`
|
||||
|
||||
// The valid targets (can disable instance or folder types)
|
||||
AllowedTargets []SyncTargetType `json:"allowedTargets,omitempty"`
|
||||
|
||||
|
||||
@@ -1495,6 +1495,13 @@ func schema_pkg_apis_provisioning_v0alpha1_MigrateJobOptions(ref common.Referenc
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"history": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Preserve history (if possible)",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"message": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Message to use when committing the changes in a single commit",
|
||||
@@ -2112,6 +2119,13 @@ func schema_pkg_apis_provisioning_v0alpha1_RepositoryViewList(ref common.Referen
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"legacyStorage": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "The backend is using legacy storage FIXME: Not sure where this should be exposed... but we need it somewhere The UI should force the onboarding workflow when this is true",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"allowedTargets": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "The valid targets (can disable instance or folder types)",
|
||||
|
||||
@@ -7,6 +7,7 @@ package v0alpha1
|
||||
// MigrateJobOptionsApplyConfiguration represents a declarative configuration of the MigrateJobOptions type for use
|
||||
// with apply.
|
||||
type MigrateJobOptionsApplyConfiguration struct {
|
||||
History *bool `json:"history,omitempty"`
|
||||
Message *string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
@@ -16,6 +17,14 @@ func MigrateJobOptions() *MigrateJobOptionsApplyConfiguration {
|
||||
return &MigrateJobOptionsApplyConfiguration{}
|
||||
}
|
||||
|
||||
// WithHistory sets the History field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the History field is set to the value of the last call.
|
||||
func (b *MigrateJobOptionsApplyConfiguration) WithHistory(value bool) *MigrateJobOptionsApplyConfiguration {
|
||||
b.History = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithMessage sets the Message field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Message field is set to the value of the last call.
|
||||
|
||||
@@ -384,7 +384,8 @@ func TestValidateJob(t *testing.T) {
|
||||
Action: provisioning.JobActionMigrate,
|
||||
Repository: "test-repo",
|
||||
Migrate: &provisioning.MigrateJobOptions{
|
||||
Message: "Migrate from unified",
|
||||
History: true,
|
||||
Message: "Migrate from legacy",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -238,8 +238,6 @@ func (r *gitRepository) Read(ctx context.Context, filePath, ref string) (*reposi
|
||||
|
||||
// Check if the path represents a directory
|
||||
if safepath.IsDir(filePath) {
|
||||
// Strip trailing slash for git tree lookup to avoid empty path components
|
||||
finalPath = strings.TrimSuffix(finalPath, "/")
|
||||
tree, err := r.client.GetTreeByPath(ctx, commit.Tree, finalPath)
|
||||
if err != nil {
|
||||
if errors.Is(err, nanogit.ErrObjectNotFound) {
|
||||
|
||||
@@ -261,7 +261,18 @@ 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.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY=
|
||||
k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw=
|
||||
k8s.io/api v0.34.3/go.mod h1:PyVQBF886Q5RSQZOim7DybQjAbVs8g7gwJNhGtY5MBk=
|
||||
k8s.io/apiextensions-apiserver v0.34.2 h1:WStKftnGeoKP4AZRz/BaAAEJvYp4mlZGN0UCv+uvsqo=
|
||||
k8s.io/apiextensions-apiserver v0.34.2/go.mod h1:398CJrsgXF1wytdaanynDpJ67zG4Xq7yj91GrmYN2SE=
|
||||
k8s.io/apiextensions-apiserver v0.34.3/go.mod h1:aujxvqGFRdb/cmXYfcRTeppN7S2XV/t7WMEc64zB5A0=
|
||||
k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4=
|
||||
k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
|
||||
k8s.io/apimachinery v0.34.3/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
|
||||
k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M=
|
||||
k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE=
|
||||
k8s.io/client-go v0.34.3/go.mod h1:OxxeYagaP9Kdf78UrKLa3YZixMCfP6bgPwPwNBQBzpM=
|
||||
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-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
|
||||
|
||||
@@ -335,9 +335,6 @@ rudderstack_data_plane_url =
|
||||
# Rudderstack SDK url, optional, only valid if rudderstack_write_key and rudderstack_data_plane_url is also set
|
||||
rudderstack_sdk_url =
|
||||
|
||||
# Rudderstack v3 SDK, optional, defaults to false. If set, Rudderstack v3 SDK will be used instead of v1
|
||||
rudderstack_v3_sdk_url =
|
||||
|
||||
# Rudderstack Config url, optional, used by Rudderstack SDK to fetch source config
|
||||
rudderstack_config_url =
|
||||
|
||||
|
||||
@@ -322,9 +322,6 @@
|
||||
# Rudderstack SDK url, optional, only valid if rudderstack_write_key and rudderstack_data_plane_url is also set
|
||||
;rudderstack_sdk_url =
|
||||
|
||||
# Rudderstack v3 SDK, optional, defaults to false. If set, Rudderstack v3 SDK will be used instead of v1
|
||||
;rudderstack_v3_sdk_url =
|
||||
|
||||
# Rudderstack Config url, optional, used by Rudderstack SDK to fetch source config
|
||||
;rudderstack_config_url =
|
||||
|
||||
|
||||
@@ -299,9 +299,15 @@
|
||||
"y": 0
|
||||
},
|
||||
"id": 6,
|
||||
"options": {},
|
||||
"content": "# Graph panel >> Timeseries panel\n\nKnown issues:\n* hiding null/empty series\n* time regions",
|
||||
"mode": "markdown",
|
||||
"options": {
|
||||
"code": {
|
||||
"language": "plaintext",
|
||||
"showLineNumbers": false,
|
||||
"showMiniMap": false
|
||||
},
|
||||
"content": "# Graph panel >> Timeseries panel\n\nKnown issues:\n* hiding null/empty series\n* time regions",
|
||||
"mode": "markdown"
|
||||
},
|
||||
"pluginVersion": "11.0.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
|
||||
@@ -7,15 +7,7 @@
|
||||
MYSQL_PASSWORD: password
|
||||
ports:
|
||||
- "3306:3306"
|
||||
command:
|
||||
- mysqld
|
||||
- --character-set-server=utf8mb4
|
||||
- --collation-server=utf8mb4_unicode_ci
|
||||
- --innodb_monitor_enable=all
|
||||
- --default-authentication-plugin=mysql_native_password
|
||||
# Please keep sql-require-primary-key option enabled, to make sure we don't accidentally introduce migration
|
||||
# adding new table without PK.
|
||||
- --sql-require-primary-key=ON
|
||||
command: [mysqld, --character-set-server=utf8mb4, --collation-server=utf8mb4_unicode_ci, --innodb_monitor_enable=all, --default-authentication-plugin=mysql_native_password]
|
||||
|
||||
fake-mysql-data:
|
||||
image: grafana/fake-data-gen
|
||||
|
||||
@@ -48,6 +48,23 @@ scopes:
|
||||
operator: equals
|
||||
value: kids
|
||||
|
||||
# This scope appears in multiple places in the tree.
|
||||
# The defaultPath determines which path is shown when this scope is selected
|
||||
# (e.g., from a URL or programmatically), even if another path also links to it.
|
||||
shared-service:
|
||||
title: Shared Service
|
||||
# Path from the root node down to the direct scopeNode.
|
||||
# Node names are hierarchical (parent-child), so use the full names.
|
||||
# This points to: gdev-scopes > production > shared-service-prod
|
||||
defaultPath:
|
||||
- gdev-scopes
|
||||
- gdev-scopes-production
|
||||
- gdev-scopes-production-shared-service-prod
|
||||
filters:
|
||||
- key: service
|
||||
operator: equals
|
||||
value: shared
|
||||
|
||||
tree:
|
||||
gdev-scopes:
|
||||
title: gdev-scopes
|
||||
@@ -68,6 +85,13 @@ tree:
|
||||
nodeType: leaf
|
||||
linkId: app2
|
||||
linkType: scope
|
||||
# This node links to 'shared-service' scope.
|
||||
# The scope's defaultPath points here (production > gdev-scopes).
|
||||
shared-service-prod:
|
||||
title: Shared Service
|
||||
nodeType: leaf
|
||||
linkId: shared-service
|
||||
linkType: scope
|
||||
test-cases:
|
||||
title: Test cases
|
||||
nodeType: container
|
||||
@@ -83,6 +107,15 @@ tree:
|
||||
nodeType: leaf
|
||||
linkId: test-case-2
|
||||
linkType: scope
|
||||
# This node also links to the same 'shared-service' scope.
|
||||
# However, the scope's defaultPath points to the production path,
|
||||
# so selecting this scope will expand the tree to production > shared-service-prod.
|
||||
shared-service-test:
|
||||
title: Shared Service (also in Production)
|
||||
subTitle: defaultPath points to Production
|
||||
nodeType: leaf
|
||||
linkId: shared-service
|
||||
linkType: scope
|
||||
test-case-redirect:
|
||||
title: Test case with redirect
|
||||
nodeType: leaf
|
||||
|
||||
@@ -51,8 +51,9 @@ type Config struct {
|
||||
|
||||
// ScopeConfig is used for YAML parsing - converts to v0alpha1.ScopeSpec
|
||||
type ScopeConfig struct {
|
||||
Title string `yaml:"title"`
|
||||
Filters []ScopeFilterConfig `yaml:"filters"`
|
||||
Title string `yaml:"title"`
|
||||
DefaultPath []string `yaml:"defaultPath,omitempty"`
|
||||
Filters []ScopeFilterConfig `yaml:"filters"`
|
||||
}
|
||||
|
||||
// ScopeFilterConfig is used for YAML parsing - converts to v0alpha1.ScopeFilter
|
||||
@@ -116,9 +117,20 @@ func convertScopeSpec(cfg ScopeConfig) v0alpha1.ScopeSpec {
|
||||
for i, f := range cfg.Filters {
|
||||
filters[i] = convertFilter(f)
|
||||
}
|
||||
|
||||
// Prefix defaultPath elements with the gdev prefix
|
||||
var defaultPath []string
|
||||
if len(cfg.DefaultPath) > 0 {
|
||||
defaultPath = make([]string, len(cfg.DefaultPath))
|
||||
for i, p := range cfg.DefaultPath {
|
||||
defaultPath[i] = prefix + "-" + p
|
||||
}
|
||||
}
|
||||
|
||||
return v0alpha1.ScopeSpec{
|
||||
Title: cfg.Title,
|
||||
Filters: filters,
|
||||
Title: cfg.Title,
|
||||
DefaultPath: defaultPath,
|
||||
Filters: filters,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,11 +105,6 @@ refs:
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/panels-visualizations/visualizations/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/visualizations/panels-visualizations/visualizations/
|
||||
cloudwatch-troubleshooting:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/datasources/aws-cloudwatch/troubleshooting/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/datasources/aws-cloudwatch/troubleshooting/
|
||||
---
|
||||
|
||||
# Amazon CloudWatch data source
|
||||
@@ -124,7 +119,6 @@ The following documents will help you get started working with the CloudWatch da
|
||||
- [CloudWatch query editor](ref:cloudwatch-query-editor)
|
||||
- [Templates and variables](ref:cloudwatch-template-variables)
|
||||
- [Configure AWS authentication](ref:cloudwatch-aws-authentication)
|
||||
- [Troubleshoot CloudWatch issues](ref:cloudwatch-troubleshooting)
|
||||
|
||||
## Import pre-configured dashboards
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user