datasources-provisioning

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Workflow

工作流程

1. Ask the starting point: from scratch, or from an existing data source?

1. 确认起始方式:从零开始,还是基于现有数据源?

Ask this before anything else (skip only if the user already made it clear):
  • From scratch — the user names a plugin type to provision → continue with step 2.
  • From an existing data source in a running instance → jump to Convert an existing data source, then return to step 6.
在开始任何操作前先询问此问题(仅当用户已明确说明时可跳过):
  • 从零开始 — 用户指定要配置的插件类型 → 继续步骤2。
  • 基于运行实例中的现有数据源 → 跳转至转换现有数据源,完成后返回步骤6。

2. Resolve the full plugin id

2. 获取完整的插件ID

Provisioning needs the canonical plugin id (
<org>-<name>-datasource
), not the short name a user might say.
  • Already canonical (contains
    -datasource
    or
    -app
    )? Use as-is:
    yesoreyeram-infinity-datasource
    .
  • Short name only (e.g.
    infinity
    ,
    clickhouse
    )? Search the catalog API with
    filter=<keyword>
    :
    bash
    curl -s "https://grafana.com/api/plugins?filter=infinity" \
      | jq -r '.items[] | "\(.slug)\t\(.name)"'
    # → yesoreyeram-infinity-datasource    Infinity
    Multiple matches → show the candidates and ask which one.
The snippets below use Infinity (
yesoreyeram-infinity-datasource
) as the worked example — substitute the id resolved here (and the version from step 3) in every command and output.
配置需要标准的插件ID(
<org>-<name>-datasource
格式),而非用户可能提到的简称。
  • 已为标准格式(包含
    -datasource
    -app
    )?直接使用:
    yesoreyeram-infinity-datasource
  • 仅提供简称(如
    infinity
    clickhouse
    )?使用
    filter=<keyword>
    调用目录API搜索:
    bash
    curl -s "https://grafana.com/api/plugins?filter=infinity" \
      | jq -r '.items[] | "\(.slug)\t\(.name)"'
    # → yesoreyeram-infinity-datasource    Infinity
    存在多个匹配结果时 → 列出候选选项并询问用户选择哪一个。
以下示例将使用Infinity(
yesoreyeram-infinity-datasource
)作为演示——请将此处获取的ID(以及步骤3获取的版本)替换到所有命令和输出中。

3. Resolve the latest version

3. 获取最新版本

bash
curl -s "https://grafana.com/api/plugins/yesoreyeram-infinity-datasource" | jq -r '.version'
Never hardcode a version — the CDN path is version-pinned and a stale version 404s.
bash
curl -s "https://grafana.com/api/plugins/yesoreyeram-infinity-datasource" | jq -r '.version'
切勿硬编码版本——CDN路径与版本绑定,过时版本会返回404错误。

4. Fetch the settings schema (primary structured source)

4. 获取设置Schema(主要结构化来源)

https://plugins-cdn.grafana.net/<PLUGIN_ID>/<VERSION>/public/plugins/<PLUGIN_ID>/schema/dsconfig.json
bash
ID=yesoreyeram-infinity-datasource
VER=$(curl -s "https://grafana.com/api/plugins/$ID" | jq -r '.version')
curl -sf "https://plugins-cdn.grafana.net/$ID/$VER/public/plugins/$ID/schema/dsconfig.json"
This file conforms to the dsconfig schema spec — the source of truth for how to interpret it. Don't re-derive field semantics from memory (
valueType
alone spans
string
,
number
,
boolean
,
array
,
object
,
map
,
any
); consult the spec when a field isn't a plain scalar:
What you need from each field to provision:
key
(the provisioning key),
valueType
,
target
(
root
|
jsonData
|
secureJsonData
), and
validations
(honor
allowedValues
for selectors like
auth_method
). Orientation example (
schemaVersion: "v1"
):
json
{
  "pluginType": "yesoreyeram-infinity-datasource",
  "fields": [
    {
      "key": "auth_method",
      "valueType": "string",
      "target": "jsonData",
      "validations": [
        {
          "type": "allowedValues",
          "values": [
            "none",
            "basicAuth",
            "apiKey",
            "bearerToken",
            "oauth2",
            "aws",
            "azureBlob"
          ]
        }
      ]
    }
  ]
}
Select only the fields relevant to what the user asked for (chosen auth method + connection), not all of them. Each field's
description
tells you which auth method it belongs to.
For ready-made example configs, fetch
v0alpha1.json
:
https://plugins-cdn.grafana.net/<PLUGIN_ID>/<VERSION>/public/plugins/<PLUGIN_ID>/schema/v0alpha1.json
bash
ID=yesoreyeram-infinity-datasource
VER=$(curl -s "https://grafana.com/api/plugins/$ID" | jq -r '.version')
curl -sf "https://plugins-cdn.grafana.net/$ID/$VER/public/plugins/$ID/schema/v0alpha1.json"
Worked examples live under
settingsExamples.examples
, an object keyed by scenario (e.g.
apiKey
,
oauth2ClientCredentials
). Each entry has a
summary
/
description
(the scenario) and a
value
holding the
jsonData
/
secureJsonData
payload to lift straight into the file:
bash
undefined
https://plugins-cdn.grafana.net/<PLUGIN_ID>/<VERSION>/public/plugins/<PLUGIN_ID>/schema/dsconfig.json
bash
ID=yesoreyeram-infinity-datasource
VER=$(curl -s "https://grafana.com/api/plugins/$ID" | jq -r '.version')
curl -sf "https://plugins-cdn.grafana.net/$ID/$VER/public/plugins/$ID/schema/dsconfig.json"
此文件符合dsconfig schema规范——这是解读文件内容的权威依据。不要凭记忆推导字段语义(
valueType
涵盖
string
number
boolean
array
object
map
any
);当字段不是普通标量时,请参考规范:
配置所需的字段信息包括:
key
(配置项键名)、
valueType
target
root
|
jsonData
|
secureJsonData
)以及
validations
(遵循
allowedValues
,例如
auth_method
的可选值)。示例说明(
schemaVersion: "v1"
):
json
{
  "pluginType": "yesoreyeram-infinity-datasource",
  "fields": [
    {
      "key": "auth_method",
      "valueType": "string",
      "target": "jsonData",
      "validations": [
        {
          "type": "allowedValues",
          "values": [
            "none",
            "basicAuth",
            "apiKey",
            "bearerToken",
            "oauth2",
            "aws",
            "azureBlob"
          ]
        }
      ]
    }
  ]
}
仅选择与用户需求相关的字段(所选认证方式 + 连接信息),而非全部字段。每个字段的
description
会说明其所属的认证方式。
如需现成的示例配置,可获取
v0alpha1.json
https://plugins-cdn.grafana.net/<PLUGIN_ID>/<VERSION>/public/plugins/<PLUGIN_ID>/schema/v0alpha1.json
bash
ID=yesoreyeram-infinity-datasource
VER=$(curl -s "https://grafana.com/api/plugins/$ID" | jq -r '.version')
curl -sf "https://plugins-cdn.grafana.net/$ID/$VER/public/plugins/$ID/schema/v0alpha1.json"
可用示例位于
settingsExamples.examples
下,这是一个按场景(如
apiKey
oauth2ClientCredentials
)分类的对象。每个条目包含
summary
/
description
(场景说明)和
value
(可直接提取到配置文件中的
jsonData
/
secureJsonData
内容):
bash
undefined

list scenarios, then pull one payload

列出场景,然后提取其中一个配置内容

... | jq -r '.settingsExamples.examples | keys[]' ... | jq '.settingsExamples.examples.apiKey.value'
undefined
... | jq -r '.settingsExamples.examples | keys[]' ... | jq '.settingsExamples.examples.apiKey.value'
undefined

5. Fallback when no schema is published

5. 无已发布Schema时的备选方案

If
schema/dsconfig.json
404s (older plugins):
  • Last resort: the generic structure in grafana-oss skill (§ Data source provisioning) can also tell the user the field names are best-effort, not plugin-authoritative.
NOTE: grafana-oss skill is available in
grafana-core
plugin and also available as a standalone skill from the https://github.com/grafana/skills repository
如果
schema/dsconfig.json
返回404(旧版插件):
  • 最后手段:grafana-oss技能中的通用结构(§ 数据源配置)也可告知用户字段名称为尽力获取,并非插件官方定义。
注意:grafana-oss技能包含在
grafana-core
插件中,也可从https://github.com/grafana/skills仓库单独获取

6. Map each field by its
target

6. 根据
target
映射每个字段

target
YAMLTerraform (
grafana_data_source
)
root
top-level key on the datasource (
url
,
basicAuth
,
basicAuthUser
)
top-level argument (
url
) / inside
json_data_encoded
jsonData
under
jsonData:
key inside
json_data_encoded = jsonencode({ … })
secureJsonData
under
secureJsonData:
as
${ENV_VAR}
key inside
secure_json_data_encoded = jsonencode({ … })
via a
sensitive
variable
Use each field's
valueType
for the scalar (
string
quoted in YAML,
boolean
true
/
false
,
number
bare). Never inline a real secret. Nested objects (
oauth2
,
aws
) and arrays (
allowedHosts
,
scopes
) map directly.
Always set
access
(
root
target) and default it to
proxy
— queries route through the Grafana server (the secure default); only use
direct
(browser → data source) if the user explicitly asks for it. In Terraform the argument is
access_mode
.
target
YAMLTerraform (
grafana_data_source
)
root
数据源的顶级键(
url
basicAuth
basicAuthUser
顶级参数(
url
) / 位于
json_data_encoded
jsonData
位于
jsonData:
json_data_encoded = jsonencode({ … })
内的键
secureJsonData
位于
secureJsonData:
下,格式为
${ENV_VAR}
通过敏感变量放入
secure_json_data_encoded = jsonencode({ … })
内的键
根据字段的
valueType
设置标量类型(YAML中
string
需加引号,
boolean
true
/
false
number
直接写数值)。切勿直接嵌入真实密钥。嵌套对象(
oauth2
aws
)和数组(
allowedHosts
scopes
)直接映射即可。
务必设置
access
root
目标),默认值为
proxy
——查询通过Grafana服务器路由(安全默认值);仅当用户明确要求时才使用
direct
(浏览器直接连接数据源)。在Terraform中对应的参数是
access_mode

7. Ask the format, then emit the file

7. 确认格式后生成文件

Now ask: YAML or Terraform? Same fields, different output file and syntax. Don't assume: "provision X" may mean either; skip the question only if the user already named a format ("terraform for X"). YAML file provisioning is the native, zero-dependency path; Terraform needs the official
grafana/grafana
provider.
ChoiceProduces
YAML config file
provisioning/datasources/<name>.yaml
Terraform
<name>.tf
(
grafana_data_source
resource)
<name>
is just the file's basename — cosmetic, since both loaders read every file in the directory regardless of name. Default it to the plugin name.
YAML
provisioning/datasources/<name>.yaml
:
yaml
apiVersion: 1
datasources:
  - name: Infinity # must be unique across the instance — collides even with a different datasource type
    type: yesoreyeram-infinity-datasource # = pluginType from the schema
    access: proxy # always set; default proxy (route queries through the Grafana server)
    uid: infinity-ds # also unique and immutable so dashboards can reference it
    jsonData:
      auth_method: apiKey # value from validations.allowedValues
      apiKeyKey: X-API-Key
      apiKeyType: header
      allowedHosts:
        - https://api.example.com
    secureJsonData:
      apiKeyValue: ${API_KEY} # env var ref, never a literal secret
    editable: false
Terraform
<name>.tf
:
hcl
variable "api_key" {
  type      = string
  sensitive = true
}

resource "grafana_data_source" "infinity" {
  type        = "yesoreyeram-infinity-datasource"
  name        = "Infinity"
  uid         = "infinity-ds"
  access_mode = "proxy" # always set; default proxy (route queries through the Grafana server)

  json_data_encoded = jsonencode({
    auth_method  = "apiKey"
    apiKeyKey    = "X-API-Key"
    apiKeyType   = "header"
    allowedHosts = ["https://api.example.com"]
  })

  secure_json_data_encoded = jsonencode({
    apiKeyValue = var.api_key
  })
}
grafana_data_source
is from the
grafana/grafana
provider — the authoritative reference for argument names (
access_mode
,
json_data_encoded
,
secure_json_data_encoded
). This file is only the resource; the user supplies the
required_providers
+
provider "grafana"
block and credentials.
现在询问用户:选择YAML还是Terraform? 两者字段相同,但输出文件和语法不同。不要自行假设:“配置X”可能指任意一种格式;仅当用户已指定格式(如“X的terraform配置”)时可跳过此问题。YAML文件配置是原生、零依赖的方式;Terraform需要官方的
grafana/grafana
provider。
选择生成文件类型
YAML配置文件
provisioning/datasources/<name>.yaml
Terraform
<name>.tf
grafana_data_source
资源)
<name>
仅为文件的基础名称——仅作标识用,因为两种加载器都会读取目录中的所有文件,与名称无关。默认使用插件名称作为文件名。
YAML
provisioning/datasources/<name>.yaml
:
yaml
apiVersion: 1
datasources:
  - name: Infinity # 必须在实例中唯一——即使数据源类型不同也不能重名
    type: yesoreyeram-infinity-datasource # = schema中的pluginType
    access: proxy # 务必设置;默认proxy(查询通过Grafana服务器路由)
    uid: infinity-ds # 同样唯一且不可变,以便仪表盘引用
    jsonData:
      auth_method: apiKey # 来自validations.allowedValues的值
      apiKeyKey: X-API-Key
      apiKeyType: header
      allowedHosts:
        - https://api.example.com
    secureJsonData:
      apiKeyValue: ${API_KEY} # 环境变量引用,切勿使用明文密钥
    editable: false
Terraform
<name>.tf
:
hcl
variable "api_key" {
  type      = string
  sensitive = true
}

resource "grafana_data_source" "infinity" {
  type        = "yesoreyeram-infinity-datasource"
  name        = "Infinity"
  uid         = "infinity-ds"
  access_mode = "proxy" # 务必设置;默认proxy(查询通过Grafana服务器路由)

  json_data_encoded = jsonencode({
    auth_method  = "apiKey"
    apiKeyKey    = "X-API-Key"
    apiKeyType   = "header"
    allowedHosts = ["https://api.example.com"]
  })

  secure_json_data_encoded = jsonencode({
    apiKeyValue = var.api_key
  })
}
grafana_data_source
来自
grafana/grafana
provider——参数名称(
access_mode
json_data_encoded
secure_json_data_encoded
)的权威参考。此文件仅包含资源定义;用户需自行提供
required_providers
+
provider "grafana"
块及凭据。

8. Return the file to the user

8. 将文件返回给用户

Present the complete file in a single code block for the user to copy and paste into their environment — note where it goes:
  • YAML
    provisioning/datasources/<name>.yaml
    (apply on Grafana start or a provisioning reload).
  • Terraform → their Terraform config, applied with
    terraform apply
    .
Optionally, tell them how to confirm it worked once applied:
bash
curl -s https://grafana.example.com/api/datasources/uid/<uid>/health \
  -H "Authorization: Bearer <token>"
将完整文件放在单个代码块中供用户复制粘贴到其环境中——注明文件存放路径:
  • YAML
    provisioning/datasources/<name>.yaml
    (Grafana启动时或配置重载时生效)。
  • Terraform → 用户的Terraform配置中,通过
    terraform apply
    生效。
可选:告知用户配置生效后如何验证是否成功:
bash
curl -s https://grafana.example.com/api/datasources/uid/<uid>/health \
  -H "Authorization: Bearer <token>"

{ "status": "OK" } → working

{ "status": "OK" } → 配置成功

{ "status": "ERROR" } → URL unreachable or auth misconfigured

{ "status": "ERROR" } → URL不可达或认证配置错误


Or verify in the UI: visit `<https://grafana.example.com>/connections/datasources/edit/<uid>` and click **Test**.

或在UI中验证:访问`<https://grafana.example.com>/connections/datasources/edit/<uid>`并点击**测试**。

Convert an existing data source

转换现有数据源

To codify a data source already configured in a running instance, read its config through the Grafana MCP server (grafana/mcp-grafana).
Precondition: the Grafana MCP server is connected with its Datasources toolset enabled (it holds the instance credentials). If it isn't available, do not support this path — never ask the user to paste a Grafana token into chat. Fall back to the from-scratch Workflow instead.
  1. Find the data source with the MCP tools —
    list_datasources
    to browse, then
    get_datasource
    (by
    uid
    or
    name
    ) for the full config.
  2. The result carries every non-secret field directly:
    type
    ,
    uid
    ,
    url
    ,
    access
    ,
    basicAuth
    ,
    basicAuthUser
    , and the full
    jsonData
    object. Copy them as-is.
  3. Secrets are never returned. The
    secureJsonFields
    map lists which secret keys are set (e.g.
    {"apiKeyValue": true}
    ) without their values. Emit an
    ${ENV_VAR}
    placeholder in
    secureJsonData
    for each key it reports
    true
    .
  4. Cross-check against the schema (step 4) to confirm secret key names and
    target
    placement, then continue at step 6 (map) and step 7 (emit) as normal.
要将已在运行实例中配置的数据源转换为代码形式,可通过Grafana MCP服务器(grafana/mcp-grafana)读取其配置。
前提条件: Grafana MCP服务器已连接且已启用Datasources工具集(持有实例凭据)。若不可用,则不支持此方式——切勿要求用户在聊天中粘贴Grafana令牌。请退回到从零开始的工作流程。
  1. 使用MCP工具查找数据源——通过
    list_datasources
    浏览,然后通过
    get_datasource
    (按
    uid
    name
    )获取完整配置。
  2. 返回结果直接包含所有非机密字段:
    type
    uid
    url
    access
    basicAuth
    basicAuthUser
    以及完整的
    jsonData
    对象。直接复制这些内容即可。
  3. 机密信息永远不会返回
    secureJsonFields
    映射列出了已设置的机密键名(如
    {"apiKeyValue": true}
    )但不包含值。为每个标记为
    true
    的键在
    secureJsonData
    中生成
    ${ENV_VAR}
    占位符。
  4. 与步骤4中的schema交叉核对,确认机密键名和
    target
    位置,然后继续步骤6(映射)和步骤7(生成文件)。

Related

相关内容

  • grafana-oss — generic data source / dashboard provisioning structure and provisioning paths.
  • grafana-oss — 通用数据源/仪表盘配置结构及配置路径。