feat: add grafana server role (#48)

Signed-off-by: gardar <gardar@users.noreply.github.com>
This commit is contained in:
gardar 2023-05-31 03:01:26 +00:00 committed by GitHub
parent a817b1a8ff
commit 126c45e646
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 1676 additions and 2 deletions

View File

@ -0,0 +1,80 @@
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: almalinux-8
image: dokken/almalinux-8
pre_build_image: true
privileged: true
cgroup_parent: docker.slice
command: /lib/systemd/systemd
- name: almalinux-9
image: dokken/almalinux-9
pre_build_image: true
privileged: true
cgroup_parent: docker.slice
command: /lib/systemd/systemd
- name: centos-7
image: dokken/centos-7
pre_build_image: true
privileged: true
cgroup_parent: docker.slice
command: /usr/lib/systemd/systemd
- name: centos-stream-8
image: dokken/centos-stream-8
pre_build_image: true
privileged: true
cgroup_parent: docker.slice
command: /lib/systemd/systemd
- name: centos-stream-9
image: dokken/centos-stream-9
pre_build_image: true
privileged: true
cgroup_parent: docker.slice
command: /lib/systemd/systemd
- name: debian-10
image: dokken/debian-10
pre_build_image: true
privileged: true
cgroup_parent: docker.slice
command: /lib/systemd/systemd
- name: debian-11
image: dokken/debian-11
pre_build_image: true
privileged: true
cgroup_parent: docker.slice
command: /lib/systemd/systemd
- name: fedora-36
image: dokken/fedora-36
pre_build_image: true
privileged: true
cgroup_parent: docker.slice
command: /lib/systemd/systemd
- name: fedora-37
image: dokken/fedora-37
pre_build_image: true
privileged: true
cgroup_parent: docker.slice
command: /lib/systemd/systemd
- name: ubuntu-18.04
image: dokken/ubuntu-18.04
pre_build_image: true
privileged: true
cgroup_parent: docker.slice
command: /lib/systemd/systemd
- name: ubuntu-20.04
image: dokken/ubuntu-20.04
pre_build_image: true
privileged: true
cgroup_parent: docker.slice
command: /lib/systemd/systemd
- name: ubuntu-22.04
image: dokken/ubuntu-22.04
pre_build_image: true
privileged: true
cgroup_parent: docker.slice
command: /lib/systemd/systemd
verifier:
name: testinfra

View File

@ -124,7 +124,7 @@ To use the Grafana Agent Ansible role:
``` ```
The playbook calls the `grafana_agent` role from the `grafana.grafana` Ansible collection. The playbook calls the `grafana_agent` role from the `grafana.grafana` Ansible collection.
The Agent configuration in this playbook send metrics and logs from the linux hosts to your prometheus and Loki data sources. The Agent configuration in this playbook send metrics and logs from the linux hosts to your Prometheus and Loki data sources.
Refer to the [Grafana Ansible documentation](https://github.com/grafana/grafana-ansible-collection/tree/main/roles/grafana_agent#role-variables) to understand the other variables you can pass to the `grafana_agent` role. Refer to the [Grafana Ansible documentation](https://github.com/grafana/grafana-ansible-collection/tree/main/roles/grafana_agent#role-variables) to understand the other variables you can pass to the `grafana_agent` role.

6
requirements.yml Normal file
View File

@ -0,0 +1,6 @@
---
collections:
- name: https://github.com/ansible-collections/community.general.git
type: git
- name: https://github.com/ansible-collections/community.grafana.git
type: git

139
roles/grafana/README.md Normal file
View File

@ -0,0 +1,139 @@
<p><img src="https://grafana.com/blog/assets/img/blog/timeshift/grafana_release_icon.png" alt="grafana logo" title="grafana" align="right" height="60" /></p>
# Ansible Role: grafana.grafana.grafana
[![License](https://img.shields.io/badge/license-MIT%20License-brightgreen.svg)](https://opensource.org/licenses/MIT)
Provision and manage [Grafana](https://github.com/grafana/grafana) - platform for analytics and monitoring
## Requirements
- Ansible >= 2.9 (It might work on previous versions, but we cannot guarantee it)
- libselinux-python on deployer host (only when deployer machine has SELinux)
- Grafana >= 5.1 (for older Grafana versions use this role in version 0.10.1 or earlier)
- jmespath on deployer machine. If you are using Ansible from a Python virtualenv, install *jmespath* to the same virtualenv via pip.
## Role Variables
All variables which can be overridden are stored in [defaults/main.yml](defaults/main.yml) file as well as in table below.
| Name | Default Value | Description |
| -------------- | ------------- | -----------------------------------|
| `grafana_use_provisioning` | true | Use Grafana provisioning capability when possible (**grafana_version=latest will assume >= 5.0**). |
| `grafana_provisioning_synced` | false | Ensure no previously provisioned dashboards are kept if not referenced anymore. |
| `grafana_version` | latest | Grafana package version |
| `grafana_manage_repo` | true | Manage package repository (or don't) |
| `grafana_yum_repo` | https://packages.grafana.com/oss/rpm | Yum repository URL |
| `grafana_yum_key` | https://packages.grafana.com/gpg.key | Yum repository gpg key |
| `grafana_rhsm_subscription` | | rhsm subscription name (redhat subscription-manager) |
| `grafana_rhsm_repo` | | rhsm repository name (redhat subscription-manager) |
| `grafana_apt_repo` | deb https://packages.grafana.com/oss/deb stable main | Apt repository string |
| `grafana_apt_key` | https://packages.grafana.com/gpg.key | Apt repository gpg key |
| `grafana_instance` | {{ ansible_fqdn \| default(ansible_host) \| default(inventory_hostname) }} | Grafana instance name |
| `grafana_logs_dir` | /var/log/grafana | Path to logs directory |
| `grafana_data_dir` | /var/lib/grafana | Path to database directory |
| `grafana_address` | 0.0.0.0 | Address on which Grafana listens |
| `grafana_port` | 3000 | port on which Grafana listens |
| `grafana_cap_net_bind_service` | false | Enables the use of ports below 1024 without root privileges by leveraging the 'capabilities' of the linux kernel. read: http://man7.org/linux/man-pages/man7/capabilities.7.html |
| `grafana_url` | "http://{{ grafana_address }}:{{ grafana_port }}" | Full URL used to access Grafana from a web browser |
| `grafana_api_url` | "{{ grafana_url }}" | URL used for API calls in provisioning if different from public URL. See [this issue](https://github.com/cloudalchemy/ansible-grafana/issues/70). |
| `grafana_domain` | "{{ ansible_fqdn \| default(ansible_host) \| default('localhost') }}" | setting is only used in as a part of the `root_url` option. Useful when using GitHub or Google OAuth |
| `grafana_server` | { protocol: http, enforce_domain: false, socket: "", cert_key: "", cert_file: "", enable_gzip: false, static_root_path: public, router_logging: false } | [server](http://docs.grafana.org/installation/configuration/#server) configuration section |
| `grafana_security` | { admin_user: admin, admin_password: "" } | [security](http://docs.grafana.org/installation/configuration/#security) configuration section |
| `grafana_database` | { type: sqlite3 } | [database](http://docs.grafana.org/installation/configuration/#database) configuration section |
| `grafana_welcome_email_on_sign_up` | false | Send welcome email after signing up |
| `grafana_users` | { allow_sign_up: false, auto_assign_org_role: Viewer, default_theme: dark } | [users](http://docs.grafana.org/installation/configuration/#users) configuration section |
| `grafana_auth` | {} | [authorization](http://docs.grafana.org/installation/configuration/#auth) configuration section |
| `grafana_ldap` | {} | [ldap](http://docs.grafana.org/installation/ldap/) configuration section. group_mappings are expanded, see defaults for example |
| `grafana_session` | {} | [session](http://docs.grafana.org/installation/configuration/#session) management configuration section |
| `grafana_analytics` | {} | Google [analytics](http://docs.grafana.org/installation/configuration/#analytics) configuration section |
| `grafana_smtp` | {} | [smtp](http://docs.grafana.org/installation/configuration/#smtp) configuration section |
| `grafana_alerting` | {} | [alerting](http://docs.grafana.org/installation/configuration/#alerting) configuration section |
| `grafana_log` | {} | [log](http://docs.grafana.org/installation/configuration/#log) configuration section |
| `grafana_metrics` | {} | [metrics](http://docs.grafana.org/installation/configuration/#metrics) configuration section |
| `grafana_tracing` | {} | [tracing](http://docs.grafana.org/installation/configuration/#tracing) configuration section |
| `grafana_snapshots` | {} | [snapshots](http://docs.grafana.org/installation/configuration/#snapshots) configuration section |
| `grafana_image_storage` | {} | [image storage](http://docs.grafana.org/installation/configuration/#external-image-storage) configuration section |
| `grafana_dashboards` | [] | List of dashboards which should be imported |
| `grafana_dashboards_dir` | "dashboards" | Path to a local directory containing dashboards files in `json` format |
| `grafana_datasources` | [] | List of datasources which should be configured |
| `grafana_environment` | {} | Optional Environment param for Grafana installation, useful ie for setting http_proxy |
| `grafana_plugins` | [] | List of Grafana plugins which should be installed |
| `grafana_alert_notifications` | [] | List of alert notification channels to be created, updated, or deleted |
Data source example:
```yaml
grafana_datasources:
- name: prometheus
type: prometheus
access: proxy
url: 'http://{{ prometheus_web_listen_address }}'
basicAuth: false
```
Dashboard example:
```yaml
grafana_dashboards:
- dashboard_id: 111
revision_id: 1
datasource: prometheus
```
Alert notification channel example:
**NOTE**: setting the variable `grafana_alert_notifications` will only come into
effect when `grafana_use_provisioning` is `true`. That means the new
provisioning system using config files, which is available starting from Grafana
v5.0, needs to be in use.
```yaml
grafana_alert_notifications:
notifiers:
- name: Channel 1
type: email
uid: channel1
is_default: false
send_reminder: false
settings:
addresses: "example@example.com"
autoResolve: true
delete_notifiers:
- name: Channel 2
uid: channel2
```
## Supported CPU Architectures
Historically packages were taken from different channels according to CPU architecture. Specifically, armv6/armv7 and aarch64/arm64 packages were via [unofficial packages distributed by fg2it](https://github.com/fg2it/grafana-on-raspberry). Now that Grafana publishes official ARM builds, all packages are taken from the official [Debian/Ubuntu](http://docs.grafana.org/installation/debian/#installing-on-debian-ubuntu) or [RPM](http://docs.grafana.org/installation/rpm/) packages.
## Example
### Playbook
Fill in the admin password field with your choice, the Grafana web page won't ask to change it at the first login.
```yaml
- hosts: all
roles:
- role: grafana.grafana.grafana
vars:
grafana_security:
admin_user: admin
admin_password: enter_your_secure_password
```
## Local Testing
The preferred way of locally testing the role is to use Docker and [molecule](https://github.com/ansible-community/molecule). You will have to install Docker on your system.
For more information about molecule go to their [docs](http://molecule.readthedocs.io/en/latest/).
## License
This project is licensed under MIT License. See [LICENSE](/LICENSE) for more details.
## Credits
This role was migrated from [cloudalchemy.grafana](https://github.com/cloudalchemy/ansible-grafana).

View File

@ -0,0 +1,262 @@
---
grafana_version: latest
grafana_manage_repo: true
grafana_yum_repo: "https://packages.grafana.com/oss/rpm"
grafana_yum_key: "https://packages.grafana.com/gpg.key"
grafana_rhsm_subscription: ""
grafana_rhsm_repo: ""
grafana_apt_repo: "deb https://packages.grafana.com/oss/deb stable main"
grafana_apt_key: "https://packages.grafana.com/gpg.key"
# Should we use the provisioning capability when possible (provisioning require grafana >= 5.0)
grafana_use_provisioning: true
# Should the provisioning be kept synced. If true, previous provisioned objects will be removed if not referenced anymore.
grafana_provisioning_synced: false
grafana_instance: "{{ ansible_fqdn | default(ansible_host) | default(inventory_hostname) }}"
grafana_logs_dir: "/var/log/grafana"
grafana_data_dir: "/var/lib/grafana"
grafana_address: "0.0.0.0"
grafana_port: 3000
# To enable the use of ports below 1024 for unprivileged processes linux needs to set CAP_NET_BIND_SERVICE.
# This has some security implications, and should be a conscious choice.
# Get informed by reading: http://man7.org/linux/man-pages/man7/capabilities.7.html
grafana_cap_net_bind_service: false
# External Grafana address. Variable maps to "root_url" in grafana server section
grafana_url: "http://{{ grafana_address }}:{{ grafana_port }}"
grafana_api_url: "{{ grafana_url }}"
grafana_domain: "{{ ansible_fqdn | default(ansible_host) | default('localhost') }}"
# Additional options for grafana "server" section
# This section WILL omit options for: http_addr, http_port, domain, and root_url, as those settings are set by variables listed before
grafana_server:
protocol: http
enforce_domain: false
socket: ""
cert_key: ""
cert_file: ""
enable_gzip: false
static_root_path: public
router_logging: false
serve_from_sub_path: false
# Variables correspond to ones in grafana.ini configuration file
# Security
grafana_security:
admin_user: admin
admin_password: ""
# secret_key: ""
# login_remember_days: 7
# cookie_username: grafana_user
# cookie_remember_name: grafana_remember
# disable_gravatar: true
# data_source_proxy_whitelist:
# Database setup
grafana_database:
type: sqlite3
# host: 127.0.0.1:3306
# name: grafana
# user: root
# password: ""
# url: ""
# ssl_mode: disable
# path: grafana.db
# max_idle_conn: 2
# max_open_conn: ""
# log_queries: ""
# Remote cache
grafana_remote_cache: {}
# User management and registration
grafana_welcome_email_on_sign_up: false
grafana_users:
allow_sign_up: false
# allow_org_create: true
# auto_assign_org: true
auto_assign_org_role: Viewer
# login_hint: "email or username"
default_theme: dark
# external_manage_link_url: ""
# external_manage_link_name: ""
# external_manage_info: ""
# grafana authentication mechanisms
grafana_auth: {}
# disable_login_form: false
# oauth_auto_login: false
# disable_signout_menu: false
# signout_redirect_url: ""
# anonymous:
# org_name: "Main Organization"
# org_role: Viewer
# ldap:
# config_file: "/etc/grafana/ldap.toml"
# allow_sign_up: false
# basic:
# enabled: true
grafana_ldap: {}
# verbose_logging: false
# servers:
# host: 127.0.0.1
# port: 389 # 636 for SSL
# use_ssl: false
# start_tls: false
# ssl_skip_verify: false
# root_ca_cert: /path/to/certificate.crt
# bind_dn: "cn=admin,dc=grafana,dc=org"
# bind_password: grafana
# search_filter: "(cn=%s)" # "(sAMAccountName=%s)" on AD
# search_base_dns:
# - "dc=grafana,dc=org"
# group_search_filter: "(&(objectClass=posixGroup)(memberUid=%s))"
# group_search_base_dns:
# - "ou=groups,dc=grafana,dc=org"
# attributes:
# name: givenName
# surname: sn
# username: sAMAccountName
# member_of: memberOf
# email: mail
# group_mappings:
# - name: Main Org.
# id: 1
# groups:
# - group_dn: "cn=admins,ou=groups,dc=grafana,dc=org"
# org_role: Admin
# - group_dn: "cn=editors,ou=groups,dc=grafana,dc=org"
# org_role: Editor
# - group_dn: "*"
# org_role: Viewer
# - name: Alternative Org
# id: 2
# groups:
# - group_dn: "cn=alternative_admins,ou=groups,dc=grafana,dc=org"
# org_role: Admin
grafana_session: {}
# provider: file
# provider_config: "sessions"
grafana_analytics: {}
# reporting_enabled: true
# google_analytics_ua_id: ""
# Set this for mail notifications
grafana_smtp: {}
# host:
# user:
# password:
# from_address:
# Enable grafana alerting mechanism
grafana_alerting:
execute_alerts: true
# error_or_timeout: 'alerting'
# nodata_or_nullvalues: 'no_data'
# concurrent_render_limit: 5
# Grafana logging configuration
grafana_log:
# mode: 'console file'
# level: info
# Internal grafana metrics system
grafana_metrics: {}
# interval_seconds: 10
# graphite:
# address: "localhost:2003"
# prefix: "prod.grafana.%(instance_name)s"
# Distributed tracing options
grafana_tracing: {}
# address: "localhost:6831"
# always_included_tag: "tag1:value1,tag2:value2"
# sampler_type: const
# sampler_param: 1
grafana_snapshots: {}
# external_enabled: true
# external_snapshot_url: "https://snapshots-origin.raintank.io"
# external_snapshot_name: "Publish to snapshot.raintank.io"
# snapshot_remove_expired: true
# snapshot_TTL_days: 90
# External image store
grafana_image_storage: {}
# provider: gcs
# key_file:
# bucket:
# path:
#######
# Plugins from https://grafana.com/plugins
grafana_plugins: []
# - raintank-worldping-app
# Dashboards from https://grafana.com/dashboards
grafana_dashboards: []
# - dashboard_id: '4271'
# revision_id: '3'
# datasource: 'Prometheus'
# - dashboard_id: '1860'
# revision_id: '4'
# datasource: 'Prometheus'
# - dashboard_id: '358'
# revision_id: '1'
# datasource: 'Prometheus'
grafana_dashboards_dir: "dashboards"
# Alert notification channels to configure
grafana_alert_notifications: []
# - name: "Email Alert"
# type: "email"
# uid: channel1
# is_default: true
# settings:
# addresses: "example@example.com"
# Datasources to configure
grafana_datasources: []
# - name: "Prometheus"
# type: "prometheus"
# access: "proxy"
# url: "http://prometheus.mydomain"
# basicAuth: true
# basicAuthUser: "admin"
# basicAuthPassword: "password"
# isDefault: true
# jsonData:
# tlsAuth: false
# tlsAuthWithCACert: false
# tlsSkipVerify: true
# API keys to configure
grafana_api_keys: []
# - name: "admin"
# role: "Admin"
# - name: "viewer"
# role: "Viewer"
# - name: "editor"
# role: "Editor"
# The location where the keys should be stored.
grafana_api_keys_dir: "{{ lookup('env', 'HOME') }}/grafana/keys"
grafana_environment: {}
# Panels configurations
grafana_panels: {}
# disable_sanitize_html: false
# enable_alpha: false

View File

@ -0,0 +1,28 @@
---
- name: "Restart grafana"
ansible.builtin.service:
name: grafana-server
state: restarted
become: true
listen: "restart_grafana"
tags:
- grafana_run
- name: "Set privileges on provisioned dashboards"
ansible.builtin.file:
path: "{{ grafana_data_dir }}/dashboards"
recurse: true
owner: "grafana"
group: "grafana"
mode: "0640"
become: true
listen: "provisioned dashboards changed"
- name: "Set privileges on provisioned dashboards directory"
ansible.builtin.file:
path: "{{ grafana_data_dir }}/dashboards"
state: "directory"
recurse: false
mode: "0755"
become: true
listen: "provisioned dashboards changed"

View File

@ -0,0 +1,31 @@
---
galaxy_info:
author: "Grafana"
description: "Grafana - platform for analytics and monitoring"
license: "MIT"
min_ansible_version: "2.9"
platforms:
- name: Ubuntu
versions:
- bionic
- xenial
- name: Debian
versions:
- stretch
- buster
- name: EL
versions:
- "7"
- "8"
- name: Fedora
versions:
- "30"
- "31"
galaxy_tags:
- grafana
- dashboard
- alerts
- alerting
- presentation
- monitoring
- metrics

View File

@ -0,0 +1,105 @@
---
- name: "Run role"
hosts: all
any_errors_fatal: true
roles:
- grafana.grafana.grafana
vars:
grafana_version: 6.2.5
grafana_security:
admin_user: admin
admin_password: "password"
grafana_address: "127.0.0.1"
grafana_auth:
login_maximum_inactive_lifetime_days: 42
disable_login_form: false
oauth_auto_login: false
disable_signout_menu: false
signout_redirect_url: ""
anonymous:
org_name: "Main Organization"
org_role: Viewer
ldap:
config_file: "/etc/grafana/ldap.toml"
allow_sign_up: false
basic:
enabled: true
grafana_ldap:
verbose_logging: false
servers:
host: 127.0.0.1
port: 389
use_ssl: false
start_tls: false
ssl_skip_verify: false
root_ca_cert: /path/to/certificate.crt
bind_dn: "cn=admin,dc=grafana,dc=org"
bind_password: grafana
search_filter: "(cn=%s)"
search_base_dns:
- "dc=grafana,dc=org"
group_search_filter: "(&(objectClass=posixGroup)(memberUid=%s))"
group_search_base_dns:
- "ou=groups,dc=grafana,dc=org"
attributes:
name: givenName
surname: sn
username: sAMAccountName
member_of: memberOf
email: mail
group_mappings:
- name: "Main Organization"
id: 1
groups:
- group_dn: "cn=admins,ou=groups,dc=grafana,dc=org"
org_role: Admin
- group_dn: "cn=editors,ou=groups,dc=grafana,dc=org"
org_role: Editor
- group_dn: "*"
org_role: Viewer
- name: "Alternative Org"
id: 2
groups:
- group_dn: "cn=alternative_admins,ou=groups,dc=grafana,dc=org"
org_role: Admin
grafana_api_keys:
- name: "admin"
role: "Admin"
- name: "viewer"
role: "Viewer"
- name: "editor"
role: "Editor"
grafana_api_keys_dir: "/tmp/grafana/keys"
grafana_plugins:
- raintank-worldping-app
grafana_alert_notifications:
notifiers:
- name: "Email Alert"
type: "email"
uid: notifier1
is_default: true
settings:
addresses: "example@example.com"
grafana_dashboards:
- dashboard_id: '1860'
revision_id: '4'
datasource: 'Prometheus'
- dashboard_id: '358'
revision_id: '1'
datasource: 'Prometheus'
grafana_datasources:
- name: "Prometheus"
type: "prometheus"
access: "proxy"
url: "http://prometheus.mydomain"
basicAuth: true
basicAuthUser: "admin"
basicAuthPassword: "password"
isDefault: true
jsonData:
tlsAuth: false
tlsAuthWithCACert: false
tlsSkipVerify: true
grafana_log:
mode: syslog
level: warn

View File

@ -0,0 +1 @@
---

View File

@ -0,0 +1,52 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
def test_directories(host):
dirs = [
"/etc/grafana",
"/var/log/grafana",
"/var/lib/grafana",
"/var/lib/grafana/dashboards",
"/var/lib/grafana/plugins",
"/var/lib/grafana/plugins/raintank-worldping-app"
]
files = [
"/etc/grafana/grafana.ini",
"/etc/grafana/ldap.toml"
]
for directory in dirs:
d = host.file(directory)
assert d.is_directory
assert d.exists
for file in files:
f = host.file(file)
assert f.exists
assert f.is_file
def test_service(host):
s = host.service("grafana-server")
# assert s.is_enabled
assert s.is_running
def test_packages(host):
p = host.package("grafana")
assert p.is_installed
assert p.version == "6.2.5"
def test_socket(host):
assert host.socket("tcp://127.0.0.1:3000").is_listening
def test_custom_auth_option(host):
f = host.file("/etc/grafana/grafana.ini")
assert f.contains("login_maximum_inactive_lifetime_days = 42")

View File

@ -0,0 +1,10 @@
---
- name: "Run role"
hosts: all
any_errors_fatal: true
roles:
- grafana.grafana.grafana
vars:
grafana_security:
admin_user: "admin"
admin_password: "password"

View File

@ -0,0 +1 @@
---

View File

@ -0,0 +1,50 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
def test_directories(host):
dirs = [
"/etc/grafana",
"/var/log/grafana",
"/var/lib/grafana",
"/var/lib/grafana/dashboards",
"/var/lib/grafana/plugins"
]
files = [
"/etc/grafana/grafana.ini"
]
for directory in dirs:
d = host.file(directory)
assert d.is_directory
assert d.exists
for file in files:
f = host.file(file)
assert f.exists
assert f.is_file
def test_service(host):
s = host.service("grafana-server")
# assert s.is_enabled
assert s.is_running
def test_packages(host):
p = host.package("grafana")
assert p.is_installed
def test_socket(host):
assert host.socket("tcp://0.0.0.0:3000").is_listening
def test_yum_repo(host):
if host.system_info.distribution in ['centos', 'redhat', 'fedora']:
f = host.file("/etc/yum.repos.d/grafana.repo")
assert f.exists

View File

@ -0,0 +1,43 @@
---
- name: "Ensure grafana key directory exists"
ansible.builtin.file:
path: "{{ grafana_api_keys_dir }}/{{ inventory_hostname }}"
state: directory
mode: "0755"
become: false
delegate_to: localhost
- name: "Check api key list"
ansible.builtin.uri:
url: "{{ grafana_api_url }}/api/auth/keys"
user: "{{ grafana_security.admin_user }}"
password: "{{ grafana_security.admin_password }}"
force_basic_auth: true
return_content: true
register: __existing_api_keys
no_log: "{{ 'false' if lookup('env', 'CI') else 'true' }}"
- name: "Create grafana api keys"
ansible.builtin.uri:
url: "{{ grafana_api_url }}/api/auth/keys"
user: "{{ grafana_security.admin_user }}"
password: "{{ grafana_security.admin_password }}"
force_basic_auth: true
method: POST
body_format: json
body: "{{ item | to_json }}"
loop: "{{ grafana_api_keys }}"
register: __new_api_keys
no_log: "{{ 'false' if lookup('env', 'CI') else 'true' }}"
when: "((__existing_api_keys['json'] | selectattr('name', 'equalto', item['name'])) | list) | length == 0"
- name: "Create api keys file to allow the keys to be seen and used by other automation"
ansible.builtin.copy:
dest: "{{ grafana_api_keys_dir }}/{{ inventory_hostname }}/{{ item['item']['name'] }}.key"
content: "{{ item['json']['key'] }}"
backup: false
mode: "0644"
loop: "{{ __new_api_keys['results'] }}"
become: false
delegate_to: localhost
when: "item['json'] is defined"

View File

@ -0,0 +1,84 @@
---
- name: "Ensure grafana directories exist"
ansible.builtin.file:
path: "{{ item.path }}"
state: "directory"
owner: "{{ item.owner | default('root') }}"
group: "{{ item.group | default('grafana') }}"
mode: "{{ item.mode | default('0755') }}"
loop:
- path: "/etc/grafana"
- path: "/etc/grafana/datasources"
- path: "/etc/grafana/provisioning"
- path: "/etc/grafana/provisioning/datasources"
- path: "/etc/grafana/provisioning/dashboards"
- path: "/etc/grafana/provisioning/notifiers"
- path: "/etc/grafana/provisioning/plugins"
- path: "{{ grafana_logs_dir }}"
owner: grafana
- path: "{{ grafana_data_dir }}"
owner: grafana
- path: "{{ grafana_data_dir }}/dashboards"
owner: grafana
- path: "{{ grafana_data_dir }}/plugins"
owner: grafana
- name: "Create grafana main configuration file"
ansible.builtin.template:
src: "grafana.ini.j2"
dest: "/etc/grafana/grafana.ini"
owner: "root"
group: "grafana"
mode: "0640"
no_log: "{{ 'false' if lookup('env', 'CI') else 'true' }}"
notify: restart_grafana
- name: "Create grafana LDAP configuration file"
ansible.builtin.template:
src: "ldap.toml.j2"
dest: "{{ grafana_auth.ldap.config_file | default('/etc/grafana/ldap.toml') }}"
owner: "root"
group: "grafana"
mode: "0640"
no_log: "{{ 'false' if lookup('env', 'CI') else 'true' }}"
notify: restart_grafana
when:
- "'ldap' in grafana_auth"
- "'enabled' not in grafana_auth.ldap or grafana_auth.ldap.enabled"
- name: "Enable grafana socket"
when:
- "grafana_server.protocol is defined and grafana_server.protocol == 'socket'"
- "grafana_server.socket | dirname != '/var/run'"
block:
- name: "Create grafana socket directory"
ansible.builtin.file:
path: "{{ grafana_server.socket | dirname }}"
state: "directory"
mode: "0775"
owner: "grafana"
group: "grafana"
- name: "Ensure grafana socket directory created on startup"
ansible.builtin.template:
src: "tmpfiles.j2"
dest: "/etc/tmpfiles.d/grafana.conf"
owner: "root"
group: "root"
mode: "0644"
- name: "Enable grafana to ports lower than port 1024"
community.general.capabilities:
path: /usr/sbin/grafana-server
capability: CAP_NET_BIND_SERVICE+ep
state: present
when:
- "grafana_port | int <= 1024"
- "grafana_cap_net_bind_service"
- name: "Enable and start Grafana systemd unit"
ansible.builtin.systemd:
name: "grafana-server"
enabled: true
state: started
daemon_reload: true

View File

@ -0,0 +1,133 @@
---
- name: "Download grafana.net dashboards"
become: false
delegate_to: localhost
run_once: true
when: "grafana_dashboards | length > 0"
block:
- name: "Create local grafana dashboard directory"
ansible.builtin.tempfile:
state: directory
register: __tmp_dashboards
changed_when: false
- name: "Download grafana dashboard from grafana.net to local directory"
ansible.builtin.get_url:
url: "https://grafana.com/api/dashboards/{{ item.dashboard_id }}/revisions/{{ item.revision_id }}/download"
dest: "{{ __tmp_dashboards.path }}/{{ item.dashboard_id }}.json"
mode: "0644"
register: __download_dashboards
until: "__download_dashboards is succeeded"
retries: 5
delay: 2
changed_when: false
loop: "{{ grafana_dashboards }}"
# As noted in [1] an exported dashboard replaces the exporter's datasource
# name with a representative name, something like 'DS_GRAPHITE'. The name
# is different for each datasource plugin, but always begins with 'DS_'.
# In the rest of the data, the same name is used, but captured in braces,
# for example: '${DS_GRAPHITE}'.
#
# [1] http://docs.grafana.org/reference/export_import/#import-sharing-with-grafana-2-x-or-3-0
#
# The data structure looks (massively abbreviated) something like:
#
# "name": "DS_GRAPHITE",
# "datasource": "${DS_GRAPHITE}",
#
# If we import the downloaded dashboard verbatim, it will not automatically
# be connected to the data source like we want it. The Grafana UI expects
# us to do the final connection by hand, which we do not want to do.
# So, in the below task we ensure that we replace instances of this string
# with the data source name we want.
# To make sure that we're not being too greedy with the regex replacement
# of the data source to use for each dashboard that's uploaded, we make the
# regex match very specific by using the following:
#
# 1. Literal boundaries for " on either side of the match.
# 2. Non-capturing optional group matches for the ${} bits which may, or
# or may not, be there..
# 3. A case-sensitive literal match for DS .
# 4. A one-or-more case-sensitive match for the part that follows the
# underscore, with only A-Z, 0-9 and - or _ allowed.
#
# This regex can be tested and understood better by looking at the
# matches and non-matches in https://regex101.com/r/f4Gkvg/6
- name: "Set the correct data source name in the dashboard"
ansible.builtin.replace:
dest: "{{ __tmp_dashboards.path }}/{{ item.dashboard_id }}.json"
regexp: '"(?:\${)?DS_[A-Z0-9_-]+(?:})?"'
replace: '"{{ item.datasource }}"'
changed_when: false
loop: "{{ grafana_dashboards }}"
- name: "Import grafana dashboards via api"
community.grafana.grafana_dashboard:
grafana_url: "{{ grafana_api_url }}"
grafana_user: "{{ grafana_security.admin_user }}"
grafana_password: "{{ grafana_security.admin_password }}"
path: "{{ item }}"
message: "Updated by ansible role {{ ansible_role_name }}"
state: present
overwrite: true
no_log: "{{ 'false' if lookup('env', 'CI') else 'true' }}"
with_fileglob:
- "{{ __tmp_dashboards.path }}/*"
- "{{ grafana_dashboards_dir }}/*.json"
when: "not grafana_use_provisioning"
- name: "Import grafana dashboards through provisioning"
when: grafana_use_provisioning
block:
- name: "Create/Update dashboards file (provisioning)"
ansible.builtin.copy:
dest: "/etc/grafana/provisioning/dashboards/ansible.yml"
content: |
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
type: file
options:
path: "{{ grafana_data_dir }}/dashboards"
backup: false
owner: root
group: grafana
mode: "0640"
become: true
notify: restart_grafana
- name: "Register previously copied dashboards"
ansible.builtin.find:
paths: "{{ grafana_data_dir }}/dashboards"
hidden: true
patterns:
- "*.json"
register: __dashboards_present
when: grafana_provisioning_synced
- name: "Import grafana dashboards"
ansible.builtin.copy:
src: "{{ item }}"
dest: "{{ grafana_data_dir }}/dashboards/{{ item | basename }}"
mode: "0640"
with_fileglob:
- "{{ __tmp_dashboards.path }}/*"
- "{{ grafana_dashboards_dir }}/*.json"
become: true
register: __dashboards_copied
notify: "provisioned dashboards changed"
- name: "Remove dashboards not present on deployer machine (synchronize)"
ansible.builtin.file:
path: "{{ item }}"
state: absent
loop: "{{ __dashboards_present_list | difference(__dashboards_copied_list) }}"
become: true
when: grafana_provisioning_synced
vars:
__dashboards_present_list: "{{ __dashboards_present | json_query('files[*].path') | default([]) }}"
__dashboards_copied_list: "{{ __dashboards_copied | json_query('results[*].dest') | default([]) }}"

View File

@ -0,0 +1,40 @@
---
- name: "Ensure datasources exist (via API)"
community.grafana.grafana_datasource:
grafana_url: "{{ grafana_api_url }}"
grafana_user: "{{ grafana_security.admin_user }}"
grafana_password: "{{ grafana_security.admin_password }}"
name: "{{ item.name }}"
url: "{{ item.url }}"
ds_type: "{{ item.type }}"
access: "{{ item.access | default(omit) }}"
is_default: "{{ item.isDefault | default(omit) }}"
basic_auth_user: "{{ item.basicAuthUser | default(omit) }}"
basic_auth_password: "{{ item.basicAuthPassword | default(omit) }}"
database: "{{ item.database | default(omit) }}"
user: "{{ item.user | default(omit) }}"
password: "{{ item.password | default(omit) }}"
aws_auth_type: "{{ item.aws_auth_type | default(omit) }}"
aws_default_region: "{{ item.aws_default_region | default(omit) }}"
aws_access_key: "{{ item.aws_access_key | default(omit) }}"
aws_secret_key: "{{ item.aws_secret_key | default(omit) }}"
aws_credentials_profile: "{{ item.aws_credentials_profile | default(omit) }}"
aws_custom_metrics_namespaces: "{{ item.aws_custom_metrics_namespaces | default(omit) }}"
loop: "{{ grafana_datasources }}"
when: "not grafana_use_provisioning"
- name: "Create/Update datasources file (provisioning)"
ansible.builtin.copy:
dest: "/etc/grafana/provisioning/datasources/ansible.yml"
content: |
apiVersion: 1
deleteDatasources: []
datasources:
"{{ grafana_datasources | to_nice_yaml }}"
backup: false
owner: root
group: grafana
mode: 0640
notify: restart_grafana
become: true
when: "grafana_use_provisioning"

View File

@ -0,0 +1,89 @@
---
- name: "Remove conflicting grafana packages"
ansible.builtin.package:
name: grafana-data
state: absent
- name: "Install dependencies"
ansible.builtin.package:
name: "{{ _grafana_dependencies }}"
state: present
update_cache: true
when: "(_grafana_dependencies | default())"
- name: "Prepare yum/dnf"
when:
- "ansible_pkg_mgr in ['yum', 'dnf']"
- "(grafana_manage_repo)"
environment: "{{ grafana_environment }}"
block:
- name: "Add Grafana yum/dnf repository"
ansible.builtin.yum_repository:
name: grafana
description: grafana
baseurl: "{{ grafana_yum_repo }}"
enabled: true
gpgkey: "{{ grafana_yum_key | default(omit) }}"
repo_gpgcheck: "{{ true if (grafana_yum_key) else omit }}"
gpgcheck: "{{ true if (grafana_yum_key) else omit }}"
when: "(not grafana_rhsm_repo)"
- name: "Attach RHSM subscription"
when: "(grafana_rhsm_subscription)"
block:
- name: "Check if Grafana RHSM subscription is enabled"
ansible.builtin.command:
cmd: "subscription-manager list --consumed --matches={{ grafana_rhsm_subscription | quote }} --pool-only"
register: __subscription_manager_consumed
changed_when: false
when: (grafana_rhsm_subscription)
- name: "Find RHSM repo subscription pool id"
ansible.builtin.command:
cmd: "subscription-manager list --available --matches={{ grafana_rhsm_subscription | quote }} --pool-only"
register: __subscription_manager_available
changed_when: false
when:
- "(grafana_rhsm_subscription)"
- "__subscription_manager_consumed.stdout | length <= 0"
- name: "Attach RHSM subscription"
ansible.builtin.command:
cmd: "subscription-manager attach --pool={{ __subscription_manager_available.stdout }}"
register: __subscription_manager_attach
changed_when: "__subscription_manager_attach.stdout is search('Successfully attached a subscription')"
failed_when: "__subscription_manager_attach.stdout is search('could not be found')"
when:
- "(grafana_rhsm_subscription)"
- "__subscription_manager_consumed.stdout | default() | length <= 0"
- "__subscription_manager_available.stdout | default() | length > 0"
- name: "Enable RHSM repository"
community.general.rhsm_repository:
name: "{{ grafana_rhsm_repo }}"
state: enabled
when: (grafana_rhsm_repo)
- name: "Prepare apt"
when:
- "ansible_pkg_mgr == 'apt'"
- "(grafana_manage_repo)"
environment: "{{ grafana_environment }}"
block:
- name: "Import Grafana apt gpg key"
ansible.builtin.apt_key:
url: "{{ grafana_apt_key }}"
state: present
validate_certs: false
- name: "Add Grafana apt repository"
ansible.builtin.apt_repository:
repo: "{{ grafana_apt_repo }}"
state: present
update_cache: true
- name: "Install Grafana"
ansible.builtin.package:
name: "{{ grafana_package }}"
state: "{{ (grafana_version == 'latest') | ternary('latest', 'present') }}"
notify: restart_grafana

View File

@ -0,0 +1,120 @@
---
- name: "Gather variables for each operating system"
ansible.builtin.include_vars: "{{ distrovars }}"
vars:
distrovars: "{{ lookup('first_found', params, errors='ignore') }}"
params:
skip: true
files:
- "{{ ansible_distribution | lower }}-{{ ansible_distribution_version | lower }}.yml"
- "{{ ansible_distribution | lower }}-{{ ansible_distribution_major_version | lower }}.yml"
- "{{ ansible_os_family | lower }}-{{ ansible_distribution_major_version | lower }}.yml"
- "{{ ansible_distribution | lower }}.yml"
- "{{ ansible_os_family | lower }}.yml"
paths:
- "vars/distro"
tags:
- grafana_install
- grafana_configure
- grafana_datasources
- grafana_notifications
- grafana_dashboards
- name: Preflight
ansible.builtin.include_tasks:
file: preflight.yml
apply:
tags:
- grafana_install
- grafana_configure
- grafana_datasources
- grafana_notifications
- grafana_dashboards
- name: Install
ansible.builtin.include_tasks:
file: install.yml
apply:
become: true
tags:
- grafana_install
- name: Configure
ansible.builtin.include_tasks:
file: configure.yml
apply:
become: true
tags:
- grafana_configure
- name: Plugins
ansible.builtin.include_tasks:
file: plugins.yml
apply:
tags:
- grafana_configure
when: "grafana_plugins != []"
- name: "Restart grafana before configuring datasources and dashboards"
ansible.builtin.meta: flush_handlers
tags:
- grafana_install
- grafana_configure
- grafana_datasources
- grafana_notifications
- grafana_dashboards
- grafana_run
- name: "Wait for grafana to start"
ansible.builtin.wait_for:
host: "{{ grafana_address if grafana_server.protocol is undefined or grafana_server.protocol in ['http', 'https'] else omit }}"
port: "{{ grafana_port if grafana_server.protocol is undefined or grafana_server.protocol in ['http', 'https'] else omit }}"
path: "{{ grafana_server.socket | default() if grafana_server.protocol is defined and grafana_server.protocol == 'socket' else omit }}"
tags:
- grafana_install
- grafana_configure
- grafana_datasources
- grafana_notifications
- grafana_dashboards
- grafana_run
- name: "Api keys"
ansible.builtin.include_tasks:
file: api_keys.yml
apply:
tags:
- grafana_configure
- grafana_run
when: "grafana_api_keys | length > 0"
- name: Datasources
ansible.builtin.include_tasks:
file: datasources.yml
apply:
tags:
- grafana_configure
- grafana_datasources
- grafana_run
when: "grafana_datasources != []"
- name: Notifications
ansible.builtin.include_tasks:
file: notifications.yml
apply:
tags:
- grafana_configure
- grafana_notifications
- grafana_run
when: "grafana_alert_notifications | length > 0"
- name: Dashboards
ansible.builtin.include_tasks:
file: dashboards.yml
apply:
tags:
- grafana_configure
- grafana_dashboards
- grafana_run
when: "grafana_dashboards | length > 0 or __found_dashboards | length > 0"
vars:
__found_dashboards: "{{ lookup('fileglob', grafana_dashboards_dir + '/*.json', wantlist=True) }}"

View File

@ -0,0 +1,13 @@
---
- name: "Create/Delete/Update alert notifications channels (provisioning)"
ansible.builtin.copy:
content: |
apiVersion: 1
"{{ grafana_alert_notifications | to_nice_yaml }}"
dest: /etc/grafana/provisioning/notifiers/ansible.yml
owner: root
group: grafana
mode: 0640
become: true
notify: restart_grafana
when: grafana_use_provisioning

View File

@ -0,0 +1,20 @@
---
- name: "Check which plugins are installed"
ansible.builtin.find:
file_type: directory
recurse: false
paths: "{{ grafana_data_dir }}/plugins"
register: __installed_plugins
- name: "Install plugins"
become: true
ansible.builtin.command:
cmd: "grafana-cli --pluginsDir {{ grafana_data_dir }}/plugins plugins install {{ item }}"
creates: "{{ grafana_data_dir }}/plugins/{{ item }}"
loop: "{{ grafana_plugins | difference(__installed_plugins.files) }}"
register: __plugin_install
until: "__plugin_install is succeeded"
retries: 5
delay: 2
notify:
- restart_grafana

View File

@ -0,0 +1,84 @@
---
- name: "Check variable types"
ansible.builtin.assert:
that:
- "grafana_server is mapping"
- "grafana_database is mapping"
- "grafana_security is mapping"
- name: "Fail when datasources aren't configured when dashboards are set to be installed"
ansible.builtin.fail:
msg: "You need to specify datasources for dashboards!!!"
when: "grafana_dashboards != [] and grafana_datasources == []"
- name: "Fail when grafana admin user isn't set"
ansible.builtin.fail:
msg: "Please specify grafana admin user (grafana_security.admin_user)"
when:
- "grafana_security.admin_user == '' or
grafana_security.admin_user is not defined"
- name: "Fail when grafana admin password isn't set"
ansible.builtin.fail:
msg: "Please specify grafana admin password (grafana_security.admin_password)"
when:
- "grafana_security.admin_password == '' or
grafana_security.admin_password is not defined"
- name: "Fail on incorrect variable types in datasource definitions"
ansible.builtin.fail:
msg: "Boolean variables in grafana_datasources shouldn't be passed as strings. Please remove unneeded apostrophes."
when: "( item.isDefault is defined and item.isDefault is string ) or
( item.basicAuth is defined and item.basicAuth is string )"
loop: "{{ grafana_datasources }}"
- name: "Fail on bad database configuration"
ansible.builtin.fail:
msg: "Wrong database configuration. Please look at http://docs.grafana.org/installation/configuration/#database"
when: "( grafana_database.type == 'sqlite3' and grafana_database.url is defined ) or
( grafana_database.type != 'sqlite3' and grafana_database.path is defined ) or
( grafana_database.type == 'sqlite3' and grafana_database.host is defined ) or
( grafana_database.type == 'sqlite3' and grafana_database.user is defined ) or
( grafana_database.type == 'sqlite3' and grafana_database.password is defined ) or
( grafana_database.type == 'sqlite3' and grafana_database.server_cert_name is defined )"
- name: "Fail when grafana domain isn't properly configured"
ansible.builtin.fail:
msg: "Check server configuration. Please look at http://docs.grafana.org/installation/configuration/#server"
when:
- "grafana_server.root_url is defined"
- "grafana_server.root_url is search(grafana_server.domain)"
- name: "Fail when grafana_api_keys uses invalid role names"
ansible.builtin.fail:
msg: "Check grafana_api_keys. The role can only be one of the following values: Viewer, Editor or Admin."
when: "item.role not in ['Viewer', 'Editor', 'Admin']"
loop: "{{ grafana_api_keys }}"
- name: "Fail when grafana_ldap isn't set when grafana_auth.ldap is"
ansible.builtin.fail:
msg: "You need to configure grafana_ldap.servers and grafana_ldap.group_mappings when grafana_auth.ldap is set"
when:
- "'ldap' in grafana_auth"
- "grafana_ldap is not defined or ('servers' not in grafana_ldap or 'group_mappings' not in grafana_ldap)"
- name: "Force grafana_use_provisioning to false if grafana_version is < 5.0 ( grafana_version is set to '{{ grafana_version }}' )"
ansible.builtin.set_fact:
grafana_use_provisioning: false
when:
- "grafana_version != 'latest'"
- "grafana_version is version_compare('5.0', '<')"
- name: "Fail if grafana_port is lower than 1024 and grafana_cap_net_bind_service is not true"
ansible.builtin.fail:
msg: "Trying to use a port lower than 1024 without setting grafana_cap_net_bind_service."
when:
- "grafana_port | int <= 1024"
- "not grafana_cap_net_bind_service"
- name: "Fail if grafana_server.socket not defined when in socket mode"
ansible.builtin.fail:
msg: "You need to configure grafana_server.socket when grafana_server.protocol is set to 'socket'"
when:
- "grafana_server.protocol is defined and grafana_server.protocol == 'socket'"
- "grafana_server.socket is undefined or grafana_server.socket == ''"

View File

@ -0,0 +1,197 @@
{{ ansible_managed | comment }}
# More informations:
# http://docs.grafana.org/installation/configuration
# https://github.com/grafana/grafana/blob/master/conf/sample.ini
app_mode = production
instance_name = {{ grafana_instance }}
# Directories
[paths]
data = {{ grafana_data_dir }}
logs = {{ grafana_logs_dir }}
plugins = {{ grafana_data_dir }}/plugins
; datasources = conf/datasources
# HTTP options
[server]
{% if grafana_server.protocol is undefined or grafana_server.protocol in ['http', 'https'] %}
http_addr = {{ grafana_address }}
http_port = {{ grafana_port }}
{% endif %}
domain = {{ grafana_domain }}
root_url = {{ grafana_url }}
{% for k,v in grafana_server.items() %}
{% if not k in ['http_addr', 'http_port', 'domain', 'root_url'] %}
{{ k }} = {{ v }}
{% endif %}
{% endfor %}
# Database
[database]
{% for k,v in grafana_database.items() %}
{% if k == 'password' %}
{{ k }} = """{{ v }}"""
{% else %}
{{ k }} = {{ v }}
{% endif %}
{% endfor %}
# Remote cache
[remote_cache]
{% for k,v in grafana_remote_cache.items() %}
{{ k }} = {{ v }}
{% endfor %}
# Security
[security]
{% for k,v in grafana_security.items() %}
{{ k }} = {{ v }}
{% endfor %}
# Users management and registration
{% if grafana_users != {} %}
[users]
{% for k,v in grafana_users.items() %}
{{ k }} = {{ v }}
{% endfor %}
{% endif %}
[emails]
welcome_email_on_sign_up = {{ grafana_welcome_email_on_sign_up }}
# Authentication
{% if grafana_auth != {} %}
[auth]
disable_login_form = {{ grafana_auth.disable_login_form | default('False') }}
oauth_auto_login = {{ grafana_auth.oauth_auto_login | default('False') }}
disable_signout_menu = {{ grafana_auth.disable_signout_menu | default('False') }}
signout_redirect_url = {{ grafana_auth.signout_redirect_url | default('') }}
{% for section, options in grafana_auth.items() %}
{% if options is mapping %}
[auth.{{ section }}]
{% if "enabled" not in options %}
enabled = True
{% endif %}
{% for k, v in options.items() %}
{{ k }} = {{ v }}
{% endfor %}
{% else %}
{{ section }} = {{ options }}
{% endif %}
{% endfor %}
{% endif %}
# Session
{% if grafana_session != {} %}
[session]
{% for k,v in grafana_session.items() %}
{{ k }} = {{ v }}
{% endfor %}
{% endif %}
# Analytics
[analytics]
reporting_enabled = "{{ grafana_analytics.reporting_enabled | default(True) }}"
{% if grafana_analytics.google_analytics_ua_id is defined and grafana_analytics.google_analytics_ua_id != '' %}
google_analytics_ua_id = "{{ grafana_analytics.google_analytics_ua_id }}"
{% endif %}
# Dashboards
[dashboards]
versions_to_keep = 20
[dashboards.json]
enabled = true
path = {{ grafana_data_dir }}/dashboards
# Alerting
[alerting]
{% if grafana_alerting != {} %}
enabled = true
{% for k,v in grafana_alerting.items() %}
{% if k != 'enabled' %}
{{ k }} = {{ v }}
{% endif %}
{% endfor %}
{% else %}
enabled = false
{% endif %}
# SMTP and email config
{% if grafana_smtp != {} %}
[smtp]
enabled = True
{% for k,v in grafana_smtp.items() %}
{% if k == 'enabled' %}{% endif %}
{% if k == 'password' %}
{{ k }} = """{{ v }}"""
{% else %}
{{ k }} = {{ v }}
{% endif %}
{% endfor %}
{% endif %}
# Logging
[log]
mode = {{ grafana_log.mode | default('console, file') }}
level = {{ grafana_log.level | default('info') }}
# Metrics
[metrics]
{% if grafana_metrics != {} %}
enabled = true
interval_seconds = {{ grafana_metrics.interval_seconds | default(10) }}
{% if grafana_metrics.basic_auth_username is defined %}
basic_auth_username = {{ grafana_metrics.basic_auth_username }}
{% endif %}
{% if grafana_metrics.basic_auth_password is defined %}
basic_auth_password = """{{ grafana_metrics.basic_auth_password }}"""
{% endif %}
{% if grafana_metrics.graphite is defined %}
[metrics.graphite]
address = {{ grafana_metrics.graphite.address }}
prefix = {{ grafana_metrics.graphite.prefix }}
{% endif %}
{% else %}
enabled = false
{% endif %}
# Tracing
{% if grafana_tracing != {} %}
[tracing.jaeger]
{% for k,v in grafana_tracing.items() %}
{{ k }} = {{ v }}
{% endfor %}
{% endif %}
# Grafana.com configuration
[grafana_com]
url = https://grafana.com
# Snapshots
{% if grafana_snapshots != {} %}
[snapshots]
{% for k,v in grafana_snapshots.items() %}
{{ k }} = {{ v }}
{% endfor %}
{% endif %}
# External image storage
{% if grafana_image_storage != {} %}
[external_image_storage]
provider = {{ grafana_image_storage.provider }}
[external_image_storage.{{ grafana_image_storage.provider }}]
{% for k,v in grafana_image_storage.items() %}
{% if k != 'provider' %}
{{ k }} = {{ v }}
{% endif %}
{% endfor %}
{% endif %}
# Panels
{% if grafana_panels != {} %}
[panels]
{% for k,v in grafana_panels.items() %}
{{ k }} = {{ v }}
{% endfor %}
{% endif %}

View File

@ -0,0 +1,39 @@
{{ ansible_managed | comment }}
# Documentation: http://docs.grafana.org/installation/ldap/
{% if 'verbose_logging' in grafana_ldap %}
verbose_logging = {{ 'true' if grafana_ldap.verbose_logging else 'false' }}
{% endif %}
[[servers]]
{% for k,v in grafana_ldap.servers.items() if k != 'attributes' %}
{% if k == 'port' %}
{{ k }} = {{ v | int }}
{% elif v in [True, False] %}
{{ k }} = {{ 'true' if v else 'false' }}
{% else %}
{{ k }} = {{ v | to_nice_json }}
{% endif %}
{% endfor %}
[servers.attributes]
{% for k,v in grafana_ldap.servers.attributes.items() %}
{{ k }} = {{ v | to_nice_json }}
{% endfor %}
{% for org in grafana_ldap.group_mappings %}
{% if 'name' in org %}
# {{ org.name }}
{% endif %}
{% for group in org.groups %}
[[servers.group_mappings]]
org_id = {{ org.id }}
{% for k,v in group.items() %}
{% if v in [True, False] %}
{{ k }} = {{ 'true' if v else 'false' }}
{% else %}
{{ k }} = "{{ v }}"
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}

View File

@ -0,0 +1,2 @@
{{ ansible_managed | comment }}
d {{ grafana_server.socket | dirname }} 0775 grafana grafana

View File

@ -0,0 +1,6 @@
molecule
docker
pytest-testinfra
jmespath
selinux
passlib

View File

@ -0,0 +1,8 @@
---
grafana_package: "grafana{% if ansible_architecture == 'armv6l' %}-rpi{% endif %}{{ (grafana_version != 'latest') | ternary('=' ~ grafana_version, '') }}"
_grafana_dependencies:
- apt-transport-https
- adduser
- ca-certificates
- libfontconfig
- gnupg2

View File

@ -0,0 +1,5 @@
---
grafana_package: "grafana{{ (grafana_version != 'latest') | ternary('-' ~ grafana_version, '') }}"
# https://unix.stackexchange.com/questions/534463/cant-enable-grafana-on-boot-in-fedora-because-systemd-sysv-install-missing
_grafana_dependencies:
- chkconfig

View File

@ -0,0 +1,2 @@
---
grafana_package: "grafana{{ (grafana_version != 'latest') | ternary('-' ~ grafana_version, '') }}"

View File

@ -26,7 +26,7 @@ All variables which can be overridden are stored in [./defaults/main.yaml](./def
| `grafana_agent_mode` | `static` | mode to run Grafana Agent in. Can be "flow" or "static", [Flow Docs](https://grafana.com/docs/agent/latest/flow/) | | `grafana_agent_mode` | `static` | mode to run Grafana Agent in. Can be "flow" or "static", [Flow Docs](https://grafana.com/docs/agent/latest/flow/) |
| `grafana_agent_user` | `grafana-agent` | os user to create for the agent to run as | | `grafana_agent_user` | `grafana-agent` | os user to create for the agent to run as |
| `grafana_agent_user_group` | `grafana-agent` | os user group to create for the agent | | `grafana_agent_user_group` | `grafana-agent` | os user group to create for the agent |
| `grafana_agent_user_groups` | `[]` | Configurable user groups that the grafana agent can be put in so that it can access logs | | `grafana_agent_user_groups` | `[]` | Configurable user groups that the Grafana agent can be put in so that it can access logs |
| `grafana_agent_user_shell` | `/usr/sbin/nologin` | the shell for the user | | `grafana_agent_user_shell` | `/usr/sbin/nologin` | the shell for the user |
| `grafana_agent_user_createhome` | `false` | whether or not to create a home directory for the user | | `grafana_agent_user_createhome` | `false` | whether or not to create a home directory for the user |
| `grafana_agent_local_binary_file` | `""` | full path to the local binary if already downloaded or built on the controller, this should only be set, if ansible is not downloading the binary and you have manually downloaded the binary | | `grafana_agent_local_binary_file` | `""` | full path to the local binary if already downloaded or built on the controller, this should only be set, if ansible is not downloading the binary and you have manually downloaded the binary |

View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
version="0.1.3"
src="https://github.com/gardar/ansible-test-molecule/releases/download/$version/ansible-test-molecule.sh"
# shellcheck disable=SC1090
if [[ -v GITHUB_TOKEN ]]
then
source <(curl -L -s -H "Authorization: token $GITHUB_TOKEN" $src)
else
source <(curl -L -s $src)
fi

View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
version="0.1.3"
src="https://github.com/gardar/ansible-test-molecule/releases/download/$version/ansible-test-molecule.sh"
# shellcheck disable=SC1090
if [[ -v GITHUB_TOKEN ]]
then
source <(curl -L -s -H "Authorization: token $GITHUB_TOKEN" $src)
else
source <(curl -L -s $src)
fi