add grafana role
This commit is contained in:
19
roles/grafana/.ansible-lint
Normal file
19
roles/grafana/.ansible-lint
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
profile: production
|
||||||
|
strict: true
|
||||||
|
|
||||||
|
# Enable checking of loop variable prefixes in roles
|
||||||
|
loop_var_prefix: "^(__|{role}_)"
|
||||||
|
|
||||||
|
skip_list:
|
||||||
|
- var-naming[no-role-prefix]
|
||||||
|
|
||||||
|
warn_list:
|
||||||
|
- role-name[path]
|
||||||
|
- var-naming[no-role-prefix]
|
||||||
|
|
||||||
|
exclude_paths:
|
||||||
|
- .github/
|
||||||
|
- molecule/default/secrets/
|
||||||
|
- molecule/default/datasources/
|
||||||
|
- molecule/default/dashboards/
|
||||||
8
roles/grafana/.yamllint
Normal file
8
roles/grafana/.yamllint
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
rules:
|
||||||
|
brackets:
|
||||||
|
forbid: false
|
||||||
|
min-spaces-inside: 0
|
||||||
|
max-spaces-inside: 2
|
||||||
|
min-spaces-inside-empty: -1
|
||||||
|
max-spaces-inside-empty: 2
|
||||||
107
roles/grafana/README.md
Normal file
107
roles/grafana/README.md
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
genlab.grafana
|
||||||
|
=========
|
||||||
|
|
||||||
|
This ansible role installs [Grafana](https://github.com/grafana/grafana) - the open-source platform for monitoring and observability. It can produce charts, graphs, and alerts for the web when connected to supported data sources.
|
||||||
|
|
||||||
|
This role installs and configures Grafana from a binary distribution. It also:
|
||||||
|
|
||||||
|
- Uploads custom dashboards
|
||||||
|
|
||||||
|
- Installs plugins
|
||||||
|
|
||||||
|
- Imports public dashboards and data sources
|
||||||
|
|
||||||
|
- Allows admin password changes
|
||||||
|
|
||||||
|
Supports user creation
|
||||||
|
Grafana service requires an environment file at startup, where you can set custom paths for logs (`log_dir`), data (`data_dir`), and plugins (`plugins_dir`). This allows flexible control over Grafana's data storage.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
You need `community.grafana` module.
|
||||||
|
|
||||||
|
Role Variables
|
||||||
|
--------------
|
||||||
|
|
||||||
|
```
|
||||||
|
grafana_user: "grafana" # user name
|
||||||
|
grafana_group: "grafana" # group name
|
||||||
|
grafana_version: 11.5.0 # version
|
||||||
|
grafana_port: 3000 # port
|
||||||
|
|
||||||
|
# Directory paths
|
||||||
|
dashboard_dir: "/tmp/grafana/dashboards" # where to copy dashboards from source
|
||||||
|
plugins_dir: "/var/lib/grafana/plugins" # where to store plugins on target
|
||||||
|
datasource_dir: "/etc/grafana/provisioning/datasources" # where to store data sources on target
|
||||||
|
log_dir: "/var/log/grafana" # where to write logs
|
||||||
|
data_dir: "/var/lib/grafana" # where to store Grafana DB
|
||||||
|
|
||||||
|
# Optional configurations
|
||||||
|
grafana_users: [] # array of user names, passwords, and statuses
|
||||||
|
grafana_plugins: [] # array of plugins to install
|
||||||
|
grafana_public_dashboards: [] # array of public dashboards to import
|
||||||
|
|
||||||
|
# Admin credentials
|
||||||
|
admin_api_username: "secret" # Grafana admin username
|
||||||
|
admin_api_password: "secret" # Grafana admin password
|
||||||
|
|
||||||
|
# Source paths
|
||||||
|
dashboard_source_path: "mydir/dashboards" # path to dashboards on source server
|
||||||
|
datasource_source_path: "mydir/datasources" # path to data sources on source server
|
||||||
|
```
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
Example Playbook
|
||||||
|
----------------
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
- name: Converge
|
||||||
|
hosts: all
|
||||||
|
vars:
|
||||||
|
grafana_users:
|
||||||
|
- name: "test"
|
||||||
|
user_login: "test"
|
||||||
|
user_password: "test"
|
||||||
|
user_email: "test@mail.ru"
|
||||||
|
is_admin: false
|
||||||
|
grafana_plugins:
|
||||||
|
version: 2.1.8
|
||||||
|
- name: aceiot-svg-panel
|
||||||
|
version: 0.1.5
|
||||||
|
grafana_public_dashboards:
|
||||||
|
- name: Node Full Exporter
|
||||||
|
id: 1860
|
||||||
|
revision: 36
|
||||||
|
vars_files:
|
||||||
|
- secrets/admin_cred.yml
|
||||||
|
|
||||||
|
roles:
|
||||||
|
- role: genlab.grafana
|
||||||
|
grafana_version: 11.5.0
|
||||||
|
admin_api_username: "{{ grafana.admin_api_username }}"
|
||||||
|
admin_api_password: "{{ grafana.admin_api_password }}"
|
||||||
|
users: "{{ grafana_users }}"
|
||||||
|
plugins: "{{ grafana_plugins }}"
|
||||||
|
public_dashboards: "{{ grafana_public_dashboards }}"
|
||||||
|
dashboard_source_path: "molecule/default/dashboards"
|
||||||
|
datasource_source_path: "molecule/default/datasources"
|
||||||
|
log_dir: "/opt/grafana/data"
|
||||||
|
data_dir: "/opt/grafana/lib"
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
BSD
|
||||||
|
|
||||||
|
Author Information
|
||||||
|
------------------
|
||||||
|
|
||||||
|
corvus-migratorius@proton.me
|
||||||
0
roles/grafana/ansible-navigator.log
Normal file
0
roles/grafana/ansible-navigator.log
Normal file
11
roles/grafana/conda.dev.yml
Normal file
11
roles/grafana/conda.dev.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
name: ansible-role-template
|
||||||
|
channels:
|
||||||
|
- conda-forge
|
||||||
|
dependencies:
|
||||||
|
- python~=3.12.0
|
||||||
|
- pip>=24.2
|
||||||
|
- actionlint
|
||||||
|
- pip:
|
||||||
|
- -r requirements.txt
|
||||||
|
- -r requirements.ci.txt
|
||||||
9
roles/grafana/conda.prod.yml
Normal file
9
roles/grafana/conda.prod.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
name: ansible-role-template
|
||||||
|
channels:
|
||||||
|
- conda-forge
|
||||||
|
dependencies:
|
||||||
|
- python~=3.12.0
|
||||||
|
- pip>=24.2
|
||||||
|
- pip:
|
||||||
|
- -r requirements.txt
|
||||||
10
roles/grafana/defaults/main.yml
Normal file
10
roles/grafana/defaults/main.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
grafana_user: "grafana"
|
||||||
|
grafana_group: "grafana"
|
||||||
|
grafana_version: 11.5.0
|
||||||
|
grafana_port: 3000
|
||||||
|
dashboard_dir: "/tmp/grafana/dashboards"
|
||||||
|
plugins_dir: "/var/lib/grafana/plugins"
|
||||||
|
datasource_dir: "/etc/grafana/provisioning/datasources"
|
||||||
|
log_dir: "/var/log/grafana"
|
||||||
|
data_dir: "/var/lib/grafana"
|
||||||
7
roles/grafana/handlers/main.yml
Normal file
7
roles/grafana/handlers/main.yml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
- name: "(Re)start and enable Grafana"
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
name: grafana-server
|
||||||
|
state: restarted
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
17
roles/grafana/meta/main.yml
Normal file
17
roles/grafana/meta/main.yml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
role_name: "grafana"
|
||||||
|
namespace: genlab
|
||||||
|
author: "Alexander Gorelyshev"
|
||||||
|
company: "Genlab, LLC"
|
||||||
|
description: ""
|
||||||
|
license: "MIT"
|
||||||
|
min_ansible_version: "2.1"
|
||||||
|
|
||||||
|
platforms:
|
||||||
|
- name: "Ubuntu"
|
||||||
|
versions: [ "focal", "jammy", "noble" ]
|
||||||
|
|
||||||
|
galaxy_tags: [ ]
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
44
roles/grafana/molecule/default/converge.yml
Normal file
44
roles/grafana/molecule/default/converge.yml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
- name: Converge
|
||||||
|
hosts: all
|
||||||
|
vars:
|
||||||
|
grafana_users:
|
||||||
|
- name: "test"
|
||||||
|
user_login: "test"
|
||||||
|
# kics-scan ignore-line
|
||||||
|
user_password: "test"
|
||||||
|
user_email: "test@mail.ru"
|
||||||
|
is_admin: false
|
||||||
|
- name: "test2"
|
||||||
|
user_login: "test2"
|
||||||
|
# kics-scan ignore-line
|
||||||
|
user_password: "test2"
|
||||||
|
user_email: "test2@mail.ru"
|
||||||
|
is_admin: true
|
||||||
|
grafana_plugins:
|
||||||
|
- name: grafana-metricsdrilldown-app
|
||||||
|
version: 1.0.0
|
||||||
|
- name: grafana-clock-panel
|
||||||
|
version: 2.1.8
|
||||||
|
- name: aceiot-svg-panel
|
||||||
|
version: 0.1.5
|
||||||
|
grafana_public_dashboards:
|
||||||
|
- name: Node Full Exporter
|
||||||
|
id: 1860
|
||||||
|
revision: 36
|
||||||
|
vars_files:
|
||||||
|
- secrets/admin_cred.yml
|
||||||
|
|
||||||
|
roles:
|
||||||
|
# kics-scan ignore-block
|
||||||
|
- role: genlab.grafana
|
||||||
|
grafana_version: 11.5.0
|
||||||
|
admin_api_username: "{{ grafana.admin_api_username }}"
|
||||||
|
admin_api_password: "{{ grafana.admin_api_password }}"
|
||||||
|
users: "{{ grafana_users }}"
|
||||||
|
plugins: "{{ grafana_plugins }}"
|
||||||
|
public_dashboards: "{{ grafana_public_dashboards }}"
|
||||||
|
dashboard_source_path: "molecule/default/dashboards"
|
||||||
|
datasource_source_path: "molecule/default/datasources"
|
||||||
|
log_dir: "/opt/grafana/data"
|
||||||
|
data_dir: "/opt/grafana/lib"
|
||||||
700
roles/grafana/molecule/default/dashboards/test_dashboard.json
Normal file
700
roles/grafana/molecule/default/dashboards/test_dashboard.json
Normal file
@@ -0,0 +1,700 @@
|
|||||||
|
{
|
||||||
|
"__inputs": [
|
||||||
|
{
|
||||||
|
"name": "DS_PROMETHEUS",
|
||||||
|
"label": "Prometheus",
|
||||||
|
"description": "",
|
||||||
|
"type": "datasource",
|
||||||
|
"pluginId": "prometheus",
|
||||||
|
"pluginName": "Prometheus"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"__requires": [
|
||||||
|
{
|
||||||
|
"type": "panel",
|
||||||
|
"id": "bargauge",
|
||||||
|
"name": "Bar gauge",
|
||||||
|
"version": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "grafana",
|
||||||
|
"id": "grafana",
|
||||||
|
"name": "Grafana",
|
||||||
|
"version": "7.1.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "panel",
|
||||||
|
"id": "graph",
|
||||||
|
"name": "Graph",
|
||||||
|
"version": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "datasource",
|
||||||
|
"id": "prometheus",
|
||||||
|
"name": "Prometheus",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "panel",
|
||||||
|
"id": "stat",
|
||||||
|
"name": "Stat",
|
||||||
|
"version": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "panel",
|
||||||
|
"id": "table",
|
||||||
|
"name": "Table",
|
||||||
|
"version": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"builtIn": 1,
|
||||||
|
"datasource": {
|
||||||
|
"type": "datasource",
|
||||||
|
"uid": "grafana"
|
||||||
|
},
|
||||||
|
"enable": true,
|
||||||
|
"hide": true,
|
||||||
|
"iconColor": "rgba(0, 211, 255, 1)",
|
||||||
|
"name": "Annotations & Alerts",
|
||||||
|
"type": "dashboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": 29,
|
||||||
|
"links": [],
|
||||||
|
"liveNow": false,
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"decimals": 0,
|
||||||
|
"mappings": [],
|
||||||
|
"min": 0,
|
||||||
|
"noValue": "0",
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#EAB839",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "none"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 15,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 4,
|
||||||
|
"options": {
|
||||||
|
"displayMode": "gradient",
|
||||||
|
"minVizHeight": 10,
|
||||||
|
"minVizWidth": 0,
|
||||||
|
"orientation": "horizontal",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"last"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"showUnfilled": true,
|
||||||
|
"valueMode": "color"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.1.5",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"expr": "sum(policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", namespace=~\"$namespace\", status=~\"fail|error\" } > 0) by (namespace)",
|
||||||
|
"instant": true,
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{namespace}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Failing Policies by Namespace",
|
||||||
|
"type": "bargauge"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"decimals": 0,
|
||||||
|
"mappings": [],
|
||||||
|
"min": 0,
|
||||||
|
"noValue": "0",
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "#EAB839",
|
||||||
|
"value": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 9,
|
||||||
|
"x": 15,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 5,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "center",
|
||||||
|
"orientation": "vertical",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"last"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.1.5",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=~\"fail|error\" } > 0) by (status)",
|
||||||
|
"format": "time_series",
|
||||||
|
"interval": "",
|
||||||
|
"intervalFactor": 1,
|
||||||
|
"legendFormat": "{{ status }}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Failing ClusterPolicies",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aliasColors": {},
|
||||||
|
"bars": false,
|
||||||
|
"dashLength": 10,
|
||||||
|
"dashes": false,
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fill": 1,
|
||||||
|
"fillGradient": 0,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 10,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"hiddenSeries": false,
|
||||||
|
"id": 11,
|
||||||
|
"legend": {
|
||||||
|
"alignAsTable": true,
|
||||||
|
"avg": false,
|
||||||
|
"current": true,
|
||||||
|
"hideEmpty": true,
|
||||||
|
"hideZero": true,
|
||||||
|
"max": false,
|
||||||
|
"min": false,
|
||||||
|
"rightSide": true,
|
||||||
|
"show": true,
|
||||||
|
"total": false,
|
||||||
|
"values": true
|
||||||
|
},
|
||||||
|
"lines": true,
|
||||||
|
"linewidth": 1,
|
||||||
|
"nullPointMode": "null as zero",
|
||||||
|
"options": {
|
||||||
|
"alertThreshold": true
|
||||||
|
},
|
||||||
|
"percentage": false,
|
||||||
|
"pluginVersion": "10.1.5",
|
||||||
|
"pointradius": 2,
|
||||||
|
"points": false,
|
||||||
|
"renderer": "flot",
|
||||||
|
"seriesOverrides": [],
|
||||||
|
"spaceLength": 10,
|
||||||
|
"stack": false,
|
||||||
|
"steppedLine": false,
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=~\"fail|error\" } > 0) by (policy)",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{ policy }}",
|
||||||
|
"refId": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"expr": "sum(policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", namespace=~\"$namespace\", status=~\"fail|error\" } > 0) by (policy)",
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{ policy }}",
|
||||||
|
"refId": "B"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"thresholds": [],
|
||||||
|
"timeRegions": [],
|
||||||
|
"title": "Failing Policies Graph",
|
||||||
|
"tooltip": {
|
||||||
|
"shared": true,
|
||||||
|
"sort": 0,
|
||||||
|
"value_type": "individual"
|
||||||
|
},
|
||||||
|
"type": "graph",
|
||||||
|
"xaxis": {
|
||||||
|
"mode": "time",
|
||||||
|
"show": true,
|
||||||
|
"values": []
|
||||||
|
},
|
||||||
|
"yaxes": [
|
||||||
|
{
|
||||||
|
"decimals": 0,
|
||||||
|
"format": "short",
|
||||||
|
"logBase": 1,
|
||||||
|
"min": "0",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": "short",
|
||||||
|
"logBase": 1,
|
||||||
|
"show": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"yaxis": {
|
||||||
|
"align": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {
|
||||||
|
"cellOptions": {
|
||||||
|
"type": "auto"
|
||||||
|
},
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 10,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 18
|
||||||
|
},
|
||||||
|
"id": 7,
|
||||||
|
"options": {
|
||||||
|
"cellHeight": "sm",
|
||||||
|
"footer": {
|
||||||
|
"countRows": false,
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"showHeader": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.1.5",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"expr": "sum(policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", namespace=~\"$namespace\", status=~\"fail|error\" }) by (namespace,policy,rule,kind,name,status,category,severity,source)",
|
||||||
|
"format": "table",
|
||||||
|
"instant": true,
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{namespace}}: {{ policy }}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Failing PolicyRules",
|
||||||
|
"transformations": [
|
||||||
|
{
|
||||||
|
"id": "organize",
|
||||||
|
"options": {
|
||||||
|
"excludeByName": {
|
||||||
|
"Time": true,
|
||||||
|
"Value": true
|
||||||
|
},
|
||||||
|
"indexByName": {
|
||||||
|
"category": 1,
|
||||||
|
"kind": 4,
|
||||||
|
"name": 5,
|
||||||
|
"namespace": 3,
|
||||||
|
"policy": 6,
|
||||||
|
"rule": 7,
|
||||||
|
"severity": 2,
|
||||||
|
"source": 0,
|
||||||
|
"status": 8
|
||||||
|
},
|
||||||
|
"renameByName": {
|
||||||
|
"namespace": "namespace"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"custom": {
|
||||||
|
"cellOptions": {
|
||||||
|
"type": "auto"
|
||||||
|
},
|
||||||
|
"inspect": false
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 80
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 10,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 28
|
||||||
|
},
|
||||||
|
"id": 9,
|
||||||
|
"options": {
|
||||||
|
"cellHeight": "sm",
|
||||||
|
"footer": {
|
||||||
|
"countRows": false,
|
||||||
|
"fields": "",
|
||||||
|
"reducer": [
|
||||||
|
"sum"
|
||||||
|
],
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"showHeader": true
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.1.5",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=~\"fail|error\" }) by (policy,rule,kind,name,status,category,severity,source)",
|
||||||
|
"format": "table",
|
||||||
|
"instant": true,
|
||||||
|
"interval": "",
|
||||||
|
"legendFormat": "{{ kind }}: {{ name }} - {{ policy }}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Failing ClusterPolicyRules",
|
||||||
|
"transformations": [
|
||||||
|
{
|
||||||
|
"id": "organize",
|
||||||
|
"options": {
|
||||||
|
"excludeByName": {
|
||||||
|
"Time": true,
|
||||||
|
"Value": true,
|
||||||
|
"__name__": true,
|
||||||
|
"container": true,
|
||||||
|
"endpoint": true,
|
||||||
|
"instance": true,
|
||||||
|
"job": true,
|
||||||
|
"namespace": true,
|
||||||
|
"pod": true,
|
||||||
|
"report": true,
|
||||||
|
"service": true
|
||||||
|
},
|
||||||
|
"indexByName": {
|
||||||
|
"category": 1,
|
||||||
|
"kind": 3,
|
||||||
|
"name": 4,
|
||||||
|
"policy": 5,
|
||||||
|
"rule": 6,
|
||||||
|
"severity": 2,
|
||||||
|
"source": 0,
|
||||||
|
"status": 7
|
||||||
|
},
|
||||||
|
"renameByName": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "table"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refresh": "",
|
||||||
|
"schemaVersion": 38,
|
||||||
|
"style": "dark",
|
||||||
|
"tags": [
|
||||||
|
"Policy Reporter"
|
||||||
|
],
|
||||||
|
"templating": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"current": {
|
||||||
|
"selected": false,
|
||||||
|
"text": "Prometheus",
|
||||||
|
"value": "prometheus"
|
||||||
|
},
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": false,
|
||||||
|
"label": "Datasource",
|
||||||
|
"multi": false,
|
||||||
|
"name": "DS_PROMETHEUS",
|
||||||
|
"options": [],
|
||||||
|
"query": "prometheus",
|
||||||
|
"refresh": 1,
|
||||||
|
"regex": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"type": "datasource"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allValue": ".*",
|
||||||
|
"current": {
|
||||||
|
"selected": false,
|
||||||
|
"text": "All",
|
||||||
|
"value": "$__all"
|
||||||
|
},
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"definition": "label_values({__name__=~ \"policy_report_result|cluster_policy_report_result\", status=~\"fail|error\"}, policy)",
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": true,
|
||||||
|
"label": "Policy",
|
||||||
|
"multi": true,
|
||||||
|
"name": "policy",
|
||||||
|
"options": [],
|
||||||
|
"query": "label_values({__name__=~ \"policy_report_result|cluster_policy_report_result\", status=~\"fail|error\"}, policy)",
|
||||||
|
"refresh": 2,
|
||||||
|
"regex": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"sort": 5,
|
||||||
|
"tagValuesQuery": "",
|
||||||
|
"tagsQuery": "",
|
||||||
|
"type": "query",
|
||||||
|
"useTags": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allValue": ".*",
|
||||||
|
"current": {
|
||||||
|
"selected": false,
|
||||||
|
"text": "All",
|
||||||
|
"value": "$__all"
|
||||||
|
},
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"definition": "label_values({__name__=~ \"policy_report_result|cluster_policy_report_result\", status=~\"fail|error\"}, category)",
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": true,
|
||||||
|
"label": "Category",
|
||||||
|
"multi": true,
|
||||||
|
"name": "category",
|
||||||
|
"options": [],
|
||||||
|
"query": "label_values({__name__=~ \"policy_report_result|cluster_policy_report_result\", status=~\"fail|error\"}, category)",
|
||||||
|
"refresh": 2,
|
||||||
|
"regex": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"sort": 5,
|
||||||
|
"tagValuesQuery": "",
|
||||||
|
"tagsQuery": "",
|
||||||
|
"type": "query",
|
||||||
|
"useTags": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allValue": ".*",
|
||||||
|
"current": {
|
||||||
|
"selected": false,
|
||||||
|
"text": "All",
|
||||||
|
"value": "$__all"
|
||||||
|
},
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"definition": "label_values({__name__=~ \"policy_report_result|cluster_policy_report_result\", status=~\"fail|error\"}, severity)",
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": true,
|
||||||
|
"label": "Severity",
|
||||||
|
"multi": true,
|
||||||
|
"name": "severity",
|
||||||
|
"options": [],
|
||||||
|
"query": "label_values({__name__=~ \"policy_report_result|cluster_policy_report_result\", status=~\"fail|error\"}, severity)",
|
||||||
|
"refresh": 2,
|
||||||
|
"regex": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"sort": 5,
|
||||||
|
"tagValuesQuery": "",
|
||||||
|
"tagsQuery": "",
|
||||||
|
"type": "query",
|
||||||
|
"useTags": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allValue": ".*",
|
||||||
|
"current": {
|
||||||
|
"selected": false,
|
||||||
|
"text": "All",
|
||||||
|
"value": "$__all"
|
||||||
|
},
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"definition": "label_values({__name__= \"policy_report_result\", status=~\"fail|error\"}, namespace)",
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": true,
|
||||||
|
"label": "Namespace",
|
||||||
|
"multi": true,
|
||||||
|
"name": "namespace",
|
||||||
|
"options": [],
|
||||||
|
"query": "label_values({__name__= \"policy_report_result\", status=~\"fail|error\"}, namespace)",
|
||||||
|
"refresh": 2,
|
||||||
|
"regex": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"sort": 5,
|
||||||
|
"tagValuesQuery": "",
|
||||||
|
"tagsQuery": "",
|
||||||
|
"type": "query",
|
||||||
|
"useTags": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allValue": ".*",
|
||||||
|
"current": {
|
||||||
|
"selected": false,
|
||||||
|
"text": "All",
|
||||||
|
"value": "$__all"
|
||||||
|
},
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"definition": "label_values({__name__=~ \"policy_report_result|cluster_policy_report_result\", status=~\"fail|error\"}, kind)",
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": true,
|
||||||
|
"label": "Kind",
|
||||||
|
"multi": true,
|
||||||
|
"name": "kind",
|
||||||
|
"options": [],
|
||||||
|
"query": "label_values({__name__=~ \"policy_report_result|cluster_policy_report_result\", status=~\"fail|error\"}, kind)",
|
||||||
|
"refresh": 2,
|
||||||
|
"regex": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"sort": 5,
|
||||||
|
"tagValuesQuery": "",
|
||||||
|
"tagsQuery": "",
|
||||||
|
"type": "query",
|
||||||
|
"useTags": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allValue": ".*",
|
||||||
|
"current": {
|
||||||
|
"selected": false,
|
||||||
|
"text": "All",
|
||||||
|
"value": "$__all"
|
||||||
|
},
|
||||||
|
"datasource": {
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"definition": "label_values({__name__=~ \"policy_report_result|cluster_policy_report_result\", status=~\"fail|error\"}, source)",
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": true,
|
||||||
|
"label": "Source",
|
||||||
|
"multi": true,
|
||||||
|
"name": "source",
|
||||||
|
"options": [],
|
||||||
|
"query": "label_values({__name__=~ \"policy_report_result|cluster_policy_report_result\", status=~\"fail|error\"}, source)",
|
||||||
|
"refresh": 2,
|
||||||
|
"regex": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"sort": 5,
|
||||||
|
"tagValuesQuery": "",
|
||||||
|
"tagsQuery": "",
|
||||||
|
"type": "query",
|
||||||
|
"useTags": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-30m",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {
|
||||||
|
"refresh_intervals": [
|
||||||
|
"5s",
|
||||||
|
"10s",
|
||||||
|
"30s",
|
||||||
|
"1m",
|
||||||
|
"5m",
|
||||||
|
"15m",
|
||||||
|
"30m",
|
||||||
|
"1h",
|
||||||
|
"2h",
|
||||||
|
"1d"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"timezone": "",
|
||||||
|
"title": "PolicyReports",
|
||||||
|
"uid": "ZkwXrUMnk",
|
||||||
|
"version": 1,
|
||||||
|
"gnetId": 13968
|
||||||
|
}
|
||||||
2081
roles/grafana/molecule/default/dashboards/test_dashboard2.json
Normal file
2081
roles/grafana/molecule/default/dashboards/test_dashboard2.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
datasources:
|
||||||
|
- name: Loki
|
||||||
|
type: loki
|
||||||
|
access: proxy
|
||||||
|
basicAuth: false
|
||||||
|
basicAuthPassword: false
|
||||||
|
url: http://localhost:3100
|
||||||
|
jsonData:
|
||||||
|
maxLines: 1000
|
||||||
|
httpHeaderName1: "Authorization"
|
||||||
|
secureJsonData:
|
||||||
|
httpHeaderValue1: "Bearer your_token_here"
|
||||||
|
version: 1
|
||||||
|
editable: false
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# config file version
|
||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
# list of datasources that should be deleted from the database
|
||||||
|
# deleteDatasources:
|
||||||
|
# - name: Prometheus
|
||||||
|
# orgId: 1
|
||||||
|
|
||||||
|
# list of datasources to insert/update depending
|
||||||
|
# whats available in the database
|
||||||
|
datasources:
|
||||||
|
# <string, required> name of the datasource. Required
|
||||||
|
- name: Prometheus
|
||||||
|
# <string, required> datasource type. Required
|
||||||
|
type: prometheus
|
||||||
|
# <string, required> access mode. direct or proxy. Required
|
||||||
|
access: proxy
|
||||||
|
# <int> org id. will default to orgId 1 if not specified
|
||||||
|
orgId: 1
|
||||||
|
# <string> url
|
||||||
|
url: http://localhost:9090
|
||||||
|
# <string> database password, if used
|
||||||
|
password:
|
||||||
|
# <string> database user, if used
|
||||||
|
user:
|
||||||
|
# <string> database name, if used
|
||||||
|
database:
|
||||||
|
# <bool> enable/disable basic auth
|
||||||
|
basicAuth: false
|
||||||
|
# <string> basic auth username, if used
|
||||||
|
basicAuthUser:
|
||||||
|
# <string> basic auth password, if used
|
||||||
|
basicAuthPassword:
|
||||||
|
# <bool> enable/disable with credentials headers
|
||||||
|
withCredentials:
|
||||||
|
# <bool> mark as default datasource. Max one per org
|
||||||
|
isDefault: true
|
||||||
|
# <map> fields that will be converted to json and stored in json_data
|
||||||
|
jsonData:
|
||||||
|
graphiteVersion: "1.1"
|
||||||
|
tlsAuth: false
|
||||||
|
tlsAuthWithCACert: false
|
||||||
|
# <string> json object of data that will be encrypted.
|
||||||
|
secureJsonData:
|
||||||
|
tlsCACert: "..."
|
||||||
|
tlsClientCert: "..."
|
||||||
|
tlsClientKey: "..."
|
||||||
|
version: 1
|
||||||
|
# <bool> allow users to edit datasources from the UI.
|
||||||
|
editable: true
|
||||||
29
roles/grafana/molecule/default/molecule.yml
Normal file
29
roles/grafana/molecule/default/molecule.yml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
dependency:
|
||||||
|
name: galaxy
|
||||||
|
|
||||||
|
driver:
|
||||||
|
name: docker
|
||||||
|
|
||||||
|
platforms:
|
||||||
|
- name: ubuntu
|
||||||
|
image: geerlingguy/docker-${MOLECULE_DISTRO:-ubuntu2404}-ansible:latest
|
||||||
|
pre_build_image: true
|
||||||
|
command: ${MOLECULE_DOCKER_COMMAND:-""}
|
||||||
|
published_ports:
|
||||||
|
- 127.0.0.1:3001:3000
|
||||||
|
volumes:
|
||||||
|
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||||
|
cgroupns_mode: host
|
||||||
|
privileged: true
|
||||||
|
|
||||||
|
provisioner:
|
||||||
|
name: ansible
|
||||||
|
|
||||||
|
verifier:
|
||||||
|
name: ansible
|
||||||
|
|
||||||
|
lint: |
|
||||||
|
set -e
|
||||||
|
yamllint .
|
||||||
|
ansible-lint .
|
||||||
3
roles/grafana/molecule/default/secrets/admin_cred.yml
Normal file
3
roles/grafana/molecule/default/secrets/admin_cred.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
grafana:
|
||||||
|
admin_api_username: "admin"
|
||||||
|
admin_api_password: "changme23"
|
||||||
41
roles/grafana/molecule/default/verify.yml
Normal file
41
roles/grafana/molecule/default/verify.yml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
- name: Verify
|
||||||
|
hosts: all
|
||||||
|
gather_facts: false
|
||||||
|
any_errors_fatal: true
|
||||||
|
vars_files:
|
||||||
|
- admin_cred.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
|
||||||
|
- name: "Include default vars"
|
||||||
|
ansible.builtin.include_vars:
|
||||||
|
dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/defaults/"
|
||||||
|
extensions: [ 'yml' ]
|
||||||
|
|
||||||
|
- name: "Check if Grafana is installed"
|
||||||
|
changed_when: false
|
||||||
|
ansible.builtin.command: "grafana-server -v"
|
||||||
|
register: grafana_installed_version
|
||||||
|
|
||||||
|
- name: "Check Grafana version"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: "grafana_installed_version.stdout is regex('{{ grafana_version }}')"
|
||||||
|
success_msg: "grafana version {{ grafana_version }} is installed and working"
|
||||||
|
fail_msg: "grafana version {{ grafana_version }} is not installed or not working correctly"
|
||||||
|
|
||||||
|
# kics-scan ignore-block
|
||||||
|
- name: "Check if Grafana login page is reachable"
|
||||||
|
ansible.builtin.uri:
|
||||||
|
url: "http://localhost:{{ grafana_port }}/api/health"
|
||||||
|
return_content: true
|
||||||
|
status_code: 200
|
||||||
|
method: GET
|
||||||
|
body_format: json
|
||||||
|
register: grafana_health
|
||||||
|
|
||||||
|
- name: "Debug Grafana health status"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: grafana_health.json.database == "ok"
|
||||||
|
success_msg: "Grafana is healthy"
|
||||||
|
fail_msg: "Grafana is not healthy"
|
||||||
6
roles/grafana/renovate.json
Normal file
6
roles/grafana/renovate.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
|
"extends": [
|
||||||
|
"config:recommended"
|
||||||
|
]
|
||||||
|
}
|
||||||
6
roles/grafana/requirements.ci.txt
Normal file
6
roles/grafana/requirements.ci.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
ansible-lint
|
||||||
|
molecule==24.12.0
|
||||||
|
molecule-plugins[docker]
|
||||||
|
docker~=7.1.0
|
||||||
|
requests==2.31.0 # pinned to the latest version not breaking Docker SDK
|
||||||
|
yamllint
|
||||||
1
roles/grafana/requirements.txt
Normal file
1
roles/grafana/requirements.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ansible~=11.2.0
|
||||||
4
roles/grafana/requirements.yml
Normal file
4
roles/grafana/requirements.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# requirements file
|
||||||
|
---
|
||||||
|
collections:
|
||||||
|
- name: community.grafana
|
||||||
40
roles/grafana/tasks/dashboards.yml
Normal file
40
roles/grafana/tasks/dashboards.yml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
- name: "Create dashboard directory"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ dashboard_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ grafana_user }}"
|
||||||
|
group: "{{ grafana_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: "Copy dashboard files from source to target"
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ item }}"
|
||||||
|
dest: "{{ dashboard_dir }}/{{ item | basename }}"
|
||||||
|
mode: "0644"
|
||||||
|
owner: "{{ grafana_user }}"
|
||||||
|
group: "{{ grafana_group }}"
|
||||||
|
with_fileglob:
|
||||||
|
- "{{ dashboard_source_path }}/*.json"
|
||||||
|
|
||||||
|
- name: "Import Grafana dashboards to Grafana"
|
||||||
|
community.grafana.grafana_dashboard:
|
||||||
|
grafana_url: "http://127.0.0.1:{{ grafana_port }}"
|
||||||
|
url_username: "{{ admin_api_username }}"
|
||||||
|
url_password: "{{ admin_api_password }}"
|
||||||
|
state: present
|
||||||
|
commit_message: Updated by ansible
|
||||||
|
overwrite: false
|
||||||
|
path: "{{ dashboard_dir }}/{{ item | basename }}"
|
||||||
|
with_fileglob:
|
||||||
|
- "{{ dashboard_source_path }}/*.json"
|
||||||
|
|
||||||
|
- name: "Run | reload Grafana provisioned dashboard configurations"
|
||||||
|
ansible.builtin.uri:
|
||||||
|
# kics-scan ignore-line
|
||||||
|
url: "http://127.0.0.1:{{ grafana_port }}/api/admin/provisioning/dashboards/reload"
|
||||||
|
method: POST
|
||||||
|
force_basic_auth: true
|
||||||
|
user: "{{ admin_api_username }}"
|
||||||
|
password: "{{ admin_api_password }}"
|
||||||
|
status_code: 200
|
||||||
28
roles/grafana/tasks/datasources.yml
Normal file
28
roles/grafana/tasks/datasources.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
- name: "Create datasource directory"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ datasource_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ grafana_user }}"
|
||||||
|
group: "{{ grafana_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: "Configure | provision datasources for Grafana"
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ datasource_source_path }}/{{ item | basename }}"
|
||||||
|
dest: "{{ datasource_dir }}/{{ item | basename }}"
|
||||||
|
owner: "{{ grafana_user }}"
|
||||||
|
group: "{{ grafana_group }}"
|
||||||
|
mode: "0660"
|
||||||
|
with_fileglob:
|
||||||
|
"{{ datasource_source_path }}/*.y*ml"
|
||||||
|
|
||||||
|
- name: "Run | reload Grafana datasource provisioned configurations"
|
||||||
|
ansible.builtin.uri:
|
||||||
|
# kics-scan ignore-line
|
||||||
|
url: "http://127.0.0.1:{{ grafana_port }}/api/admin/provisioning/datasources/reload"
|
||||||
|
method: POST
|
||||||
|
force_basic_auth: true
|
||||||
|
user: "{{ admin_api_username }}"
|
||||||
|
password: "{{ admin_api_password }}"
|
||||||
|
status_code: 200
|
||||||
11
roles/grafana/tasks/import_pub_dashboard.yml
Normal file
11
roles/grafana/tasks/import_pub_dashboard.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
- name: "Import public dashboard - '{{ public_dashboard.name }}''"
|
||||||
|
community.grafana.grafana_dashboard:
|
||||||
|
grafana_url: "http://127.0.0.1:{{ grafana_port }}"
|
||||||
|
state: "{{ public_dashboard.state | default('present') }}"
|
||||||
|
overwrite: false
|
||||||
|
dashboard_id: "{{ public_dashboard.id }}"
|
||||||
|
dashboard_revision: "{{ public_dashboard.revision }}"
|
||||||
|
commit_message: "Add public dashboard '{{ public_dashboard.name }}''"
|
||||||
|
url_username: "{{ admin_api_username }}"
|
||||||
|
url_password: "{{ admin_api_password }}"
|
||||||
78
roles/grafana/tasks/install.yml
Normal file
78
roles/grafana/tasks/install.yml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
---
|
||||||
|
- name: "Create Grafana system group"
|
||||||
|
ansible.builtin.group:
|
||||||
|
name: grafana
|
||||||
|
system: true
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: "Create Grafana system user"
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: grafana
|
||||||
|
group: grafana
|
||||||
|
system: true
|
||||||
|
shell: "/sbin/nologin"
|
||||||
|
create_home: false
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: "Install Grafana deb package"
|
||||||
|
block:
|
||||||
|
- name: "Check Grafana version"
|
||||||
|
changed_when: false
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "grafana-server --version"
|
||||||
|
register: grafana_ver
|
||||||
|
|
||||||
|
- name: "Assert version correctness"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: "grafana_ver.stdout is regex('{{ grafana_version }}')"
|
||||||
|
success_msg: "grafana version {{ grafana_version }} is installed and working"
|
||||||
|
fail_msg: "grafana version {{ grafana_version }} is not installed or not working correctly"
|
||||||
|
|
||||||
|
rescue:
|
||||||
|
- name: "Ensure that directories exist"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ grafana_user }}"
|
||||||
|
group: "{{ grafana_group }}"
|
||||||
|
mode: '0775'
|
||||||
|
with_items:
|
||||||
|
- "{{ log_dir }}"
|
||||||
|
- "{{ data_dir }}"
|
||||||
|
- "{{ plugins_dir }}"
|
||||||
|
|
||||||
|
- name: "Download Grafana DEB package"
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: "https://dl.grafana.com/oss/release/grafana_{{ grafana_version }}_amd64.deb"
|
||||||
|
dest: "/tmp/grafana-{{ grafana_version }}_amd64.deb"
|
||||||
|
owner: "{{ grafana_user }}"
|
||||||
|
group: "{{ grafana_group }}"
|
||||||
|
mode: "0644"
|
||||||
|
register: package_tmp
|
||||||
|
|
||||||
|
- name: "Install DEB package"
|
||||||
|
notify: "(Re)start and enable Grafana"
|
||||||
|
ansible.builtin.apt:
|
||||||
|
deb: "{{ package_tmp.dest }}"
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
|
||||||
|
- name: "Cleanup downloaded file"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/tmp/grafana-{{ grafana_version }}_amd64.deb"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: "Create env file for systemd service unit"
|
||||||
|
notify: "(Re)start and enable Grafana"
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: grafana-server.env.j2
|
||||||
|
dest: "{{ item }}"
|
||||||
|
owner: "{{ grafana_user }}"
|
||||||
|
group: "{{ grafana_group }}"
|
||||||
|
mode: "0660"
|
||||||
|
with_items:
|
||||||
|
- "/etc/default/grafana-server"
|
||||||
|
- "/etc/default/grafana"
|
||||||
|
|
||||||
|
- name: "Flush handlers"
|
||||||
|
ansible.builtin.meta: "flush_handlers"
|
||||||
39
roles/grafana/tasks/main.yml
Normal file
39
roles/grafana/tasks/main.yml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
- name: "Include grafana installation tasks"
|
||||||
|
ansible.builtin.include_tasks: install.yml
|
||||||
|
|
||||||
|
- name: "Wait for the Grafana server to become available"
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
host: "127.0.0.1"
|
||||||
|
port: "{{ grafana_port }}"
|
||||||
|
state: started
|
||||||
|
delay: 10
|
||||||
|
|
||||||
|
- name: "Include user creation tasks"
|
||||||
|
when: users is defined
|
||||||
|
loop: "{{ users }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: user
|
||||||
|
ansible.builtin.include_tasks: user.yml
|
||||||
|
|
||||||
|
- name: "Configure custom dashboards"
|
||||||
|
when: dashboard_source_path is defined
|
||||||
|
ansible.builtin.include_tasks: dashboards.yml
|
||||||
|
|
||||||
|
- name: "Configure public dashboards"
|
||||||
|
when: public_dashboards is defined
|
||||||
|
loop: "{{ public_dashboards }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: public_dashboard
|
||||||
|
ansible.builtin.include_tasks: import_pub_dashboard.yml
|
||||||
|
|
||||||
|
- name: "Configure plugins"
|
||||||
|
when: plugins is defined
|
||||||
|
loop: "{{ plugins }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: plugin
|
||||||
|
ansible.builtin.include_tasks: plugins.yml
|
||||||
|
|
||||||
|
- name: "Configure datasources"
|
||||||
|
when: datasource_source_path is defined
|
||||||
|
ansible.builtin.include_tasks: datasources.yml
|
||||||
16
roles/grafana/tasks/plugins.yml
Normal file
16
roles/grafana/tasks/plugins.yml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
- name: "Create plugin directory"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ plugins_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ grafana_user }}"
|
||||||
|
group: "{{ grafana_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: "Install Grafana plugins"
|
||||||
|
community.grafana.grafana_plugin:
|
||||||
|
name: "{{ plugin.name }}"
|
||||||
|
version: "{{ plugin.version }}"
|
||||||
|
grafana_plugins_dir: "{{ plugins_dir }}"
|
||||||
|
state: "{{ plugin.state | default('present') }}"
|
||||||
|
notify: "(Re)start and enable Grafana"
|
||||||
19
roles/grafana/tasks/user.yml
Normal file
19
roles/grafana/tasks/user.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: "Reset default admin password"
|
||||||
|
ansible.builtin.command: >
|
||||||
|
grafana-cli admin reset-admin-password "{{ admin_api_password }}"
|
||||||
|
no_log: true
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: "Create | update a Grafana user"
|
||||||
|
community.grafana.grafana_user:
|
||||||
|
url: "http://127.0.0.1:{{ grafana_port }}"
|
||||||
|
url_username: "{{ admin_api_username }}"
|
||||||
|
url_password: "{{ admin_api_password }}"
|
||||||
|
name: "{{ user.name }}"
|
||||||
|
email: "{{ user.user_email }}"
|
||||||
|
login: "{{ user.user_login }}"
|
||||||
|
password: "{{ user.user_password }}"
|
||||||
|
is_admin: "{{ user.is_admin | default(false) }}"
|
||||||
|
state: present
|
||||||
24
roles/grafana/templates/grafana-server.env.j2
Normal file
24
roles/grafana/templates/grafana-server.env.j2
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
GRAFANA_USER=grafana
|
||||||
|
|
||||||
|
GRAFANA_GROUP=grafana
|
||||||
|
|
||||||
|
GRAFANA_HOME=/usr/share/grafana
|
||||||
|
|
||||||
|
LOG_DIR={{ log_dir }}
|
||||||
|
|
||||||
|
DATA_DIR={{ data_dir }}
|
||||||
|
|
||||||
|
MAX_OPEN_FILES=10000
|
||||||
|
|
||||||
|
CONF_DIR=/etc/grafana
|
||||||
|
|
||||||
|
CONF_FILE=/etc/grafana/grafana.ini
|
||||||
|
|
||||||
|
RESTART_ON_UPGRADE=true
|
||||||
|
|
||||||
|
PLUGINS_DIR={{ plugins_dir }}
|
||||||
|
|
||||||
|
PROVISIONING_CFG_DIR=/etc/grafana/provisioning
|
||||||
|
|
||||||
|
# Only used on systemd systems
|
||||||
|
PID_FILE_DIR=/run/grafana
|
||||||
1
roles/grafana/vars/main.yml
Normal file
1
roles/grafana/vars/main.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
---
|
||||||
Reference in New Issue
Block a user