Open gbolo opened 10 months ago
Dashboard import is not functional without this feature. Did you manage to tie a dashboard to Prometheus otherwise @gbolo ?
@kosssi, I've come up with an (overly complicated) workaround, but it's the only way I'm able to set up/update the dashboard. Also, I'm really new into Prometheus and Grafana, so I might be missing some concepts, but still, it works for my use case.
The following tasks import Prometheus datasource and then sets up a dashboard for Blackbox Exporter (uid: xtkCtBkiz
, see the grafana_dashboard_uid
variable), which is defined in template dashboard.json.j2
. This template is not directly downloaded from Grafana.com, but I've first imported it manually in one Grafana instance and then copied the JSON Model into the Jinja2 template.
main.yml
:
- name: Update Prometheus datasource in Grafana
community.grafana.grafana_datasource:
grafana_url: "https://{{ prometheus_grafana_domain }}"
grafana_user: "admin"
grafana_password: "{{ vaulted_grafana_user_passwords['admin'] }}"
name: prometheus
ds_type: prometheus
ds_url: http://prometheus:9090/
access: proxy
register: grafana_prometheus_datasource
changed_when: false # https://github.com/ansible-collections/community.grafana/issues/127
tags: grafana
- name: Update Grafana dashboards
ansible.builtin.include_tasks: grafana-dashboard.yml
loop:
- {
uid: blackbox-exporter-j4da,
# The template has to have 'uid' in all 'datasource' replaced by '{{ datasource_uid }}', for example:
# ...
# "datasource": {
# "type": "prometheus",
# "uid": "{{ datasource_uid }}"
# }
# ...
template: grafana-dashboards/blackbox-exporter-j4da.json.j2,
datasource_uid: "{{ grafana_prometheus_datasource.datasource.uid }}"
}
- {
uid: fcb1bdc8-fa9d-4bfd-b725-003b174473ad,
template: grafana-dashboards/fcb1bdc8-fa9d-4bfd-b725-003b174473ad.json.j2,
datasource_uid: "{{ grafana_prometheus_datasource.datasource.uid }}"
}
- {
uid: xtkCtBkis,
template: grafana-dashboards/xtkCtBkis.json.j2,
datasource_uid: "{{ grafana_prometheus_datasource.datasource.uid }}"
}
- {
uid: xtkCtBkiz,
template: grafana-dashboards/xtkCtBkiz.json.j2,
datasource_uid: "{{ grafana_prometheus_datasource.datasource.uid }}"
}
loop_control:
loop_var: dashboard
tags: grafana
grafana-dashboard.yml
:
---
- name: Get current dashboard configuration
block:
- name: Create a temporary file for current dashboard JSON
ansible.builtin.tempfile:
state: file
suffix: .dashboard-current.json
register: temp_dashboard_json_current_file
changed_when: false
tags: grafana
- name: Export current dashboard
community.grafana.grafana_dashboard:
grafana_url: "https://{{ prometheus_grafana_domain }}"
grafana_user: "admin"
grafana_password: "{{ vaulted_grafana_user_passwords['admin'] }}"
state: export
uid: "{{ dashboard.uid }}"
path: "{{ temp_dashboard_json_current_file.path }}"
register: grafana_dashboard_current_uid
changed_when: false
when: not ansible_check_mode
tags: grafana
- name: Read the current dashboard into variable
ansible.builtin.set_fact:
dashboard_json_current: "{{ lookup('file', temp_dashboard_json_current_file.path) | from_json }}"
when:
- grafana_dashboard_current_uid.msg is defined
- not (grafana_dashboard_current_uid.msg is search("does not exist."))
tags: grafana
- name: Remove the 'id' key from current dashboard
ansible.builtin.set_fact:
dashboard_json_current_without_id: "{{ dashboard_json_current.dashboard | combine({'id': omit}, recursive=True) }}"
when:
- grafana_dashboard_current_uid.msg is defined
- not (grafana_dashboard_current_uid.msg is search("does not exist."))
tags: grafana
- name: Prepare new dashboard configuration
block:
- name: Create a temporary file for new dashboard JSON
ansible.builtin.tempfile:
state: file
suffix: .dashboard-new.json
register: temp_dashboard_json_new_file
changed_when: false
tags: grafana
- name: Generate dashboard JSON with correct datasource UID
ansible.builtin.template:
src: "{{ dashboard.template }}"
dest: "{{ temp_dashboard_json_new_file.path }}"
owner: root
group: root
mode: "600"
vars:
datasource_uid: "{{ dashboard.datasource_uid }}"
changed_when: false
when: not ansible_check_mode
tags: grafana
- name: Read the new dashboard
ansible.builtin.set_fact:
dashboard_json_new: "{{ lookup('file', temp_dashboard_json_new_file.path) | from_json }}"
when: dashboard_json_current_without_id is defined
tags: grafana
- name: Remove the 'id' key from new dashboard
ansible.builtin.set_fact:
dashboard_json_new_without_id: "{{ dashboard_json_new | combine({'id': omit}, recursive=True) }}"
when: dashboard_json_current_without_id is defined
tags: grafana
- name: Remove current dashboard from Grafana
community.grafana.grafana_dashboard:
grafana_url: "https://{{ prometheus_grafana_domain }}"
grafana_user: "admin"
grafana_password: "{{ vaulted_grafana_user_passwords['admin'] }}"
uid: "{{ dashboard.uid }}"
state: absent
when:
- dashboard_json_current_without_id is defined
- dashboard_json_current_without_id != dashboard_json_new_without_id
tags: grafana
- name: Import Blackbox Exporter dashboard to Grafana
community.grafana.grafana_dashboard:
grafana_url: "https://{{ prometheus_grafana_domain }}"
grafana_user: "admin"
grafana_password: "{{ vaulted_grafana_user_passwords['admin'] }}"
state: present
commit_message: Updated by Ansible
path: "{{ temp_dashboard_json_new_file.path }}"
when:
- dashboard_json_current_without_id is not defined or dashboard_json_current_without_id != dashboard_json_new_without_id
- temp_dashboard_json_new_file.path is defined
tags: grafana
- name: Clean up temporary files
ansible.builtin.file:
path: "{{ item }}"
state: absent
loop:
- "{{ temp_dashboard_json_new_file.path }}"
- "{{ temp_dashboard_json_current_file.path }}"
changed_when: false
when: not ansible_check_mode
tags: grafana
...
SUMMARY
Currently, the web UI in Grafana supports providing inputs when importing dashboards. for example, a dashboard json may have a body containing:
In the same body it can reference those inputs like:
"datasource": "${DS_PROMETHEUS}"
.When using the web UI in Grafana, it interprets these inputs and allows you to fill them in with a drop down menu. Then when it makes the
POST /api/dashboards/import
call, it will have the values for those inputs in the body like:ISSUE TYPE
community.grafana.grafana_dashboard
module to support supplying theinput
part of the request body.COMPONENT NAME
community.grafana.grafana_dashboard
ADDITIONAL INFORMATION
For example, see this dashboard: https://grafana.com/grafana/dashboards/405-node-exporter-server-metrics/