Vendor Galaxy Roles and Collections
This commit is contained in:
parent
c1e1897cda
commit
2aed20393f
3553 changed files with 387444 additions and 2 deletions
71
ansible_collections/grafana/grafana/roles/alloy/README.md
Normal file
71
ansible_collections/grafana/grafana/roles/alloy/README.md
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# Ansible role - Alloy
|
||||
|
||||
[](LICENSE)
|
||||
|
||||
This Ansible role to install and configure [Alloy](https://grafana.com/docs/alloy/latest/), which can be used to collect traces, metrics, and logs.
|
||||
This role is tailored for operating systems such as **RedHat**, **Rocky Linux**, **AlmaLinux**, **Ubuntu**, **Debian**, **macOS**, and **openSUSE**.
|
||||
|
||||
## Table of Content
|
||||
|
||||
- [Requirements](#requirements)
|
||||
- [Role Variables](#role-variables)
|
||||
- [Playbook](#playbook)
|
||||
|
||||
## Requirements
|
||||
|
||||
- Ansible 2.13+
|
||||
- `ansible.utils` collection is required. Additionally, you must install the `netaddr` Python library on the host where you are running Ansible (not on the target remote host) if is not present.
|
||||
- `community.general` collection is required for macOS support
|
||||
- **macOS**: Homebrew must be installed
|
||||
|
||||
## Role Variables
|
||||
|
||||
| Variable Name | Description | Default Value |
|
||||
|-----------------------|----------------------------------------------------------------------|---------------------------------------------------------------------|
|
||||
| `alloy_version` | The version of Alloy to download and deploy. Supported standard version "1.4.2" format or "latest". | `latest` |
|
||||
| `alloy_uninstall` | If set to `true` will perfom uninstall instead of deployment. | `false` |
|
||||
| `alloy_expose_port` | By default, this is set to false. It supports only simple firewalld configurations. If set to true, a firewalld rule is added to expose the TCP alloy port. The Port is automatically extracted from the environment variable `alloy_env_file_vars` in CUSTOM_ARGS when --server.http.listen-addr=0.0.0.0:12345 is defined. If set to false, configuration is skipped. If the firewalld.service is not active, all firewalld tasks are skipped. | `false` |
|
||||
| `alloy_user_groups` | Appends the alloy user to specific groups. | `[]` |
|
||||
| `alloy_github_api_url` | The default Github API URL to check for the latest version available. | `"https://api.github.com/repos/grafana/alloy/releases/latest"` |
|
||||
| `alloy_download_url_rpm` | The default download URL for the Alloy rpm package from GitHub. | `"https://github.com/grafana/alloy/releases/download/v{{ aloy_version }}/alloy-{{ aloy_version }}-1.{{ __alloy_arch }}.rpm"` |
|
||||
| `alloy_download_url_deb` | The default download URL for the Alloy deb package from GitHub. | `"https://github.com/grafana/alloy/releases/download/v{{ aloy_version }}/alloy-{{ aloy_version }}-1.{{ __alloy_arch }}.deb"` |
|
||||
| `alloy_readiness_check_use_https` | This boolean variable determines whether the readiness check for the Alloy server should use HTTPS or HTTP when validating the `/-/ready` endpoint. This variable does not enable TLS on the Alloy server itself. | `false` |
|
||||
| `alloy_readiness_check_use_proxy` | This boolean variable determines whether the readiness check for the Alloy server should use a proxy when validating the `/-/ready` endpoint. If false, it will not use a proxy, even if one is defined in an environment variable on the target hosts. | `true` |
|
||||
| `alloy_env_file_vars` | You can use environment variables to control the run-time behavior of Grafana Alloy. | `{}` |
|
||||
| `alloy_systemd_override` | Systemd unit drop-in file used to override or extend the default configuration of a systemd unit. | `{}` |
|
||||
| `alloy_config` | This is the configuration that sets up Alloy. Refer to the [configuration blocks](https://grafana.com/docs/alloy/latest/reference/config-blocks/) and [components](https://grafana.com/docs/alloy/latest/reference/components/) documentation for more details. Since the purpose of using Alloy varies, no default configuration is provided. ⚠️ **You must provide either `alloy_config` for single config or set `alloy_env_file_vars.CONFIG_FILE` for multi-config setup**. Note that if you use `alloy_env_file_vars.CONFIG_FILE`, the content of `alloy_config` will not be templated. It is expected that you manage the multi-config content using pre_tasks or with your own role. | `{}` |
|
||||
|
||||
## Dependencies
|
||||
|
||||
No Dependencies
|
||||
|
||||
## Playbook
|
||||
|
||||
```yaml
|
||||
- name: Manage alloy service
|
||||
hosts: all
|
||||
become: true
|
||||
vars:
|
||||
# alloy_config: |
|
||||
# Your Config Content
|
||||
roles:
|
||||
- role: grafana.grafana.alloy
|
||||
```
|
||||
|
||||
- Playbook execution example
|
||||
```shell
|
||||
# Deploy Alloy
|
||||
ansible-playbook function_alloy_play.yml
|
||||
|
||||
# Uninstall Alloy
|
||||
ansible-playbook function_alloy_play.yml -e "alloy_uninstall=true"
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
See [LICENSE](https://github.com/grafana/grafana-ansible-collection/blob/main/LICENSE)
|
||||
|
||||
## Author Information
|
||||
|
||||
- [Ishan Jain](https://github.com/ishanjainn)
|
||||
- [VoidQuark](https://github.com/voidquark)
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
# defaults file for alloy
|
||||
alloy_version: "latest"
|
||||
alloy_uninstall: false
|
||||
alloy_expose_port: false
|
||||
alloy_github_api_url: "https://api.github.com/repos/grafana/alloy/releases/latest"
|
||||
alloy_download_url_rpm: "https://github.com/grafana/alloy/releases/download/v{{ alloy_version }}/alloy-{{ alloy_version }}-1.{{ __alloy_arch }}.rpm"
|
||||
alloy_download_url_deb: "https://github.com/grafana/alloy/releases/download/v{{ alloy_version }}/alloy-{{ alloy_version }}-1.{{ __alloy_arch }}.deb"
|
||||
alloy_readiness_check_use_https: false
|
||||
alloy_readiness_check_use_proxy: true
|
||||
|
||||
alloy_user_groups: []
|
||||
# alloy_user_groups:
|
||||
# - "systemd-journal"
|
||||
|
||||
alloy_env_file_vars: {}
|
||||
# alloy_env_file_vars:
|
||||
# CONFIG_FILE: "/custom/path"
|
||||
# CUSTOM_ARGS: "--server.http.listen-addr=0.0.0.0:12345 --stability.level=public-preview --feature.community-components.enabled=true"
|
||||
|
||||
alloy_systemd_override: {}
|
||||
# alloy_systemd_override: |
|
||||
# [Service]
|
||||
# User=root
|
||||
|
||||
alloy_config: {}
|
||||
# alloy_config: |
|
||||
# prometheus.scrape "default" {
|
||||
# targets = [{"__address__" = "127.0.0.1:12345"}]
|
||||
# forward_to = [prometheus.remote_write.prom.receiver]
|
||||
# }
|
||||
# prometheus.remote_write "prom" {
|
||||
# endpoint {
|
||||
# url = "http://mimir:9009/api/v1/push"
|
||||
# }
|
||||
# }
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
# handlers file for alloy
|
||||
- name: Restart alloy
|
||||
listen: "restart alloy"
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: true
|
||||
name: alloy.service
|
||||
state: restarted
|
||||
enabled: true
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Restart alloy macos
|
||||
listen: "restart alloy macos"
|
||||
ansible.builtin.command: "brew services restart {{ __alloy_brew_package }}"
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
- ansible_facts['os_family'] == 'Darwin'
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
galaxy_info:
|
||||
role_name: alloy
|
||||
author: Ishan Jain, voidquark
|
||||
description: Role to Install and Configure Grafana Alloy
|
||||
license: "GPL-3.0-or-later"
|
||||
min_ansible_version: "2.13"
|
||||
platforms:
|
||||
- name: EL
|
||||
versions:
|
||||
- "8"
|
||||
- "9"
|
||||
- name: Fedora
|
||||
versions:
|
||||
- all
|
||||
- name: Debian
|
||||
versions:
|
||||
- all
|
||||
- name: Ubuntu
|
||||
versions:
|
||||
- all
|
||||
- name: macOS
|
||||
versions:
|
||||
- all
|
||||
- name: opensuse
|
||||
versions:
|
||||
- all
|
||||
galaxy_tags:
|
||||
- alloy
|
||||
- grafana
|
||||
- observability
|
||||
- monitoring
|
||||
- opentelemetry
|
||||
- telemetry
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
- name: Converge
|
||||
hosts: all
|
||||
vars:
|
||||
alloy_version: "1.4.2"
|
||||
alloy_config: |
|
||||
prometheus.scrape "default" {
|
||||
targets = [{"__address__" = "127.0.0.1:12345"}]
|
||||
forward_to = [prometheus.remote_write.prom.receiver]
|
||||
}
|
||||
prometheus.remote_write "prom" {
|
||||
endpoint {
|
||||
url = "http://mimir:9009/api/v1/push"
|
||||
}
|
||||
}
|
||||
roles:
|
||||
- role: grafana.grafana.alloy
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
dependency:
|
||||
name: galaxy
|
||||
options:
|
||||
ignore-errors: true
|
||||
driver:
|
||||
name: docker
|
||||
platforms:
|
||||
- name: instance
|
||||
image: "geerlingguy/docker-${MOLECULE_DISTRO:-rockylinux8}-ansible:latest"
|
||||
command: ${MOLECULE_DOCKER_COMMAND:-""}
|
||||
volumes:
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||
cgroupns_mode: host
|
||||
privileged: true
|
||||
pre_build_image: true
|
||||
provisioner:
|
||||
name: ansible
|
||||
playbooks:
|
||||
converge: converge.yml
|
||||
176
ansible_collections/grafana/grafana/roles/alloy/tasks/deploy.yml
Normal file
176
ansible_collections/grafana/grafana/roles/alloy/tasks/deploy.yml
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
---
|
||||
- name: Obtain the latest version from the GitHub repo
|
||||
when: alloy_version == "latest"
|
||||
block:
|
||||
- name: Scrape Github API endpoint to obtain latest Alloy version
|
||||
ansible.builtin.uri:
|
||||
url: "{{ alloy_github_api_url }}"
|
||||
method: GET
|
||||
body_format: json
|
||||
become: false
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
check_mode: false
|
||||
register: __github_latest_version
|
||||
|
||||
- name: Latest available Alloy version
|
||||
ansible.builtin.set_fact:
|
||||
alloy_version: "{{ __github_latest_version.json.tag_name | regex_replace('^v?(\\d+\\.\\d+\\.\\d+)$', '\\1') }}"
|
||||
|
||||
- name: Verify current deployed version
|
||||
when: ansible_facts['os_family'] in ['RedHat', 'Debian', 'Suse']
|
||||
block:
|
||||
- name: Check if Alloy binary is present
|
||||
ansible.builtin.stat:
|
||||
path: "/usr/bin/alloy"
|
||||
register: __already_deployed
|
||||
|
||||
- name: Obtain current deployed Alloy version
|
||||
ansible.builtin.command:
|
||||
cmd: "/usr/bin/alloy --version"
|
||||
changed_when: false
|
||||
register: __current_deployed_version
|
||||
when: __already_deployed.stat.exists | bool
|
||||
|
||||
- name: Verify current deployed version on macOS
|
||||
when: ansible_facts['os_family'] == 'Darwin'
|
||||
block:
|
||||
- name: Check if Alloy is installed via Homebrew
|
||||
ansible.builtin.command: brew list --versions {{ __alloy_brew_package }}
|
||||
register: __brew_alloy_version
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
|
||||
- name: Extract current Alloy version on macOS
|
||||
ansible.builtin.set_fact:
|
||||
__current_deployed_version:
|
||||
stdout: "{{ __brew_alloy_version.stdout }}"
|
||||
when: __brew_alloy_version.rc == 0
|
||||
|
||||
- name: Include RedHat/Rocky setup
|
||||
ansible.builtin.include_tasks:
|
||||
file: setup-RedHat.yml
|
||||
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']
|
||||
|
||||
- name: Include Debian/Ubuntu setup
|
||||
ansible.builtin.include_tasks:
|
||||
file: setup-Debian.yml
|
||||
when: ansible_facts['os_family'] == 'Debian'
|
||||
|
||||
- name: Include macOS/Darwin setup
|
||||
ansible.builtin.include_tasks:
|
||||
file: setup-Darwin.yml
|
||||
when: ansible_facts['os_family'] == 'Darwin'
|
||||
|
||||
- name: Include SUSE setup
|
||||
ansible.builtin.include_tasks:
|
||||
file: setup-Suse.yml
|
||||
when: ansible_facts['os_family'] == 'Suse'
|
||||
|
||||
- name: Alloy systemd override
|
||||
when:
|
||||
- alloy_systemd_override | length > 0
|
||||
- ansible_facts['os_family'] in ['RedHat', 'Debian', 'Suse']
|
||||
block:
|
||||
- name: Ensure that Alloy systemd override path exist
|
||||
ansible.builtin.file:
|
||||
path: "/etc/systemd/system/alloy.service.d"
|
||||
state: directory
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0750"
|
||||
notify: restart alloy
|
||||
|
||||
- name: Template Alloy systemd override.conf - /etc/systemd/system/alloy.service.d/override.conf
|
||||
ansible.builtin.template:
|
||||
src: "override.conf.j2"
|
||||
dest: "/etc/systemd/system/alloy.service.d/override.conf"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0644"
|
||||
notify: restart alloy
|
||||
|
||||
- name: Template Alloy env file - {{ __alloy_env_file }}
|
||||
ansible.builtin.template:
|
||||
src: "alloy.j2"
|
||||
dest: "{{ __alloy_env_file }}"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0644"
|
||||
notify: restart alloy
|
||||
when: ansible_facts['os_family'] in ['RedHat', 'Debian', 'Suse']
|
||||
|
||||
- name: Template Alloy config - /etc/alloy/config.alloy
|
||||
ansible.builtin.template:
|
||||
src: "config.alloy.j2"
|
||||
dest: "/etc/alloy/config.alloy"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0644"
|
||||
when:
|
||||
- alloy_config | length > 0
|
||||
- alloy_env_file_vars.CONFIG_FILE is not defined
|
||||
- ansible_facts['os_family'] in ['RedHat', 'Debian', 'Suse']
|
||||
notify: restart alloy
|
||||
|
||||
- name: Ensure that /etc/alloy/alloy.config is absent when a custom configuration file/dir is specified in alloy_env_file_vars.CONFIG_FILE
|
||||
ansible.builtin.file:
|
||||
path: "/etc/alloy/config.alloy"
|
||||
state: absent
|
||||
when:
|
||||
- alloy_config | length < 1 or alloy_env_file_vars.CONFIG_FILE is defined
|
||||
- ansible_facts['os_family'] in ['RedHat', 'Debian', 'Suse']
|
||||
|
||||
- name: Add the Alloy system user to additional group
|
||||
ansible.builtin.user:
|
||||
name: "alloy"
|
||||
groups: "{{ item }}"
|
||||
system: true
|
||||
append: true
|
||||
create_home: false
|
||||
state: present
|
||||
loop: "{{ alloy_user_groups }}"
|
||||
when:
|
||||
- alloy_user_groups | length > 0
|
||||
- ansible_facts['os_family'] in ['RedHat', 'Debian', 'Suse']
|
||||
|
||||
- name: Get firewalld state
|
||||
ansible.builtin.systemd:
|
||||
name: "firewalld"
|
||||
register: __firewalld_service_state
|
||||
when: ansible_facts['os_family'] in ['RedHat', 'Debian', 'Suse']
|
||||
|
||||
- name: Enable firewalld rule to expose Alloy tcp port {{ __alloy_server_http_listen_port }}
|
||||
ansible.posix.firewalld:
|
||||
immediate: true
|
||||
permanent: true
|
||||
port: "{{ __alloy_server_http_listen_port }}/tcp"
|
||||
state: enabled
|
||||
when:
|
||||
- ansible_facts['os_family'] in ['RedHat', 'Debian', 'Suse']
|
||||
- __firewalld_service_state.status.ActiveState == "active"
|
||||
- alloy_expose_port | bool
|
||||
|
||||
- name: Flush handlers after deployment
|
||||
ansible.builtin.meta: flush_handlers
|
||||
|
||||
- name: Ensure that Alloy is started (Linux)
|
||||
ansible.builtin.systemd:
|
||||
name: alloy.service
|
||||
state: started
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
- ansible_facts['os_family'] in ['RedHat', 'Debian', 'Suse']
|
||||
|
||||
- name: Verify that Alloy URL is responding
|
||||
ansible.builtin.uri:
|
||||
url: "{{ alloy_readiness_check_use_https | ansible.builtin.ternary('https', 'http') }}://{{ __alloy_server_http_listen_address }}:{{ __alloy_server_http_listen_port }}/-/ready"
|
||||
method: GET
|
||||
use_proxy: "{{ alloy_readiness_check_use_proxy | bool }}"
|
||||
register: __alloy_verify_url_status_code
|
||||
retries: 5
|
||||
delay: 8
|
||||
until: __alloy_verify_url_status_code.status == 200
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
- ansible_facts['os_family'] in ['RedHat', 'Debian', 'Suse']
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
# tasks file for alloy
|
||||
- name: Include OS specific variables
|
||||
ansible.builtin.include_vars:
|
||||
file: "{{ ansible_facts['os_family'] }}.yml"
|
||||
|
||||
- name: Preflight
|
||||
ansible.builtin.include_tasks:
|
||||
file: "preflight.yml"
|
||||
|
||||
- name: Deploy Alloy service
|
||||
ansible.builtin.include_tasks:
|
||||
file: "deploy.yml"
|
||||
when: not alloy_uninstall
|
||||
|
||||
- name: Uninstall Alloy service
|
||||
ansible.builtin.include_tasks:
|
||||
file: "uninstall.yml"
|
||||
when: alloy_uninstall
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
- name: Fail when alloy_config or alloy_env_file_vars.CONFIG_FILE is not defined
|
||||
ansible.builtin.fail:
|
||||
msg: Variable alloy_config or alloy_env_file_vars.CONFIG_FILE is required!
|
||||
when:
|
||||
- alloy_config | length < 1
|
||||
- alloy_env_file_vars.CONFIG_FILE is not defined
|
||||
- not alloy_uninstall
|
||||
|
||||
- name: Extract IP address and PORT from alloy_env_file_vars
|
||||
when: alloy_env_file_vars.CUSTOM_ARGS is defined and alloy_env_file_vars.CUSTOM_ARGS | length > 0
|
||||
block:
|
||||
- name: Search for server.http.listen-addr string
|
||||
ansible.builtin.set_fact:
|
||||
__alloy_server_http_listen_addr_regex: "{{ alloy_env_file_vars.CUSTOM_ARGS | regex_search('--server.http.listen-addr=([\\d\\.]+):(\\d+)', '\\1', '\\2') or [] }}"
|
||||
|
||||
- name: Extract IP address and port
|
||||
ansible.builtin.set_fact:
|
||||
__alloy_server_http_listen_address: "{{ __alloy_server_http_listen_addr_regex[0] }}"
|
||||
__alloy_server_http_listen_port: "{{ __alloy_server_http_listen_addr_regex[1] }}"
|
||||
when: __alloy_server_http_listen_addr_regex | length > 0
|
||||
|
||||
- name: Assert that extracted IP address is valid
|
||||
ansible.builtin.assert:
|
||||
that: (__alloy_server_http_listen_address | ansible.utils.ipaddr) != ""
|
||||
when: __alloy_server_http_listen_addr_regex | length > 0
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
---
|
||||
- name: Check if Homebrew is installed
|
||||
ansible.builtin.command: which brew
|
||||
register: __brew_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Fail if Homebrew is not installed
|
||||
ansible.builtin.fail:
|
||||
msg: "Homebrew is required but not installed"
|
||||
when: __brew_check.rc != 0
|
||||
|
||||
- name: Get Homebrew prefix
|
||||
ansible.builtin.command: brew --prefix
|
||||
register: __brew_prefix
|
||||
changed_when: false
|
||||
|
||||
- name: Set Alloy config directory path
|
||||
ansible.builtin.set_fact:
|
||||
__alloy_config_path: "{{ __alloy_config_path_default }}"
|
||||
|
||||
- name: Add Grafana tap to Homebrew
|
||||
community.general.homebrew_tap:
|
||||
name: "{{ __alloy_brew_tap }}"
|
||||
state: present
|
||||
|
||||
- name: Install Alloy via Homebrew
|
||||
community.general.homebrew:
|
||||
name: "{{ __alloy_brew_package }}"
|
||||
state: present
|
||||
update_homebrew: true
|
||||
|
||||
- name: Ensure Alloy config directory exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ __alloy_config_path }}"
|
||||
state: directory
|
||||
owner: "{{ ansible_user_id }}"
|
||||
group: "{{ ansible_user_gid }}"
|
||||
mode: '0755'
|
||||
|
||||
- name: Template Alloy config
|
||||
ansible.builtin.template:
|
||||
src: "config.alloy.j2"
|
||||
dest: "{{ __alloy_config_path }}/config.alloy"
|
||||
owner: "{{ ansible_user_id }}"
|
||||
group: "{{ ansible_user_gid }}"
|
||||
mode: '0644'
|
||||
backup: true
|
||||
when: alloy_config | length > 0
|
||||
notify: restart alloy macos
|
||||
|
||||
- name: Check if Alloy service is loaded
|
||||
ansible.builtin.command: brew services list
|
||||
register: __brew_services
|
||||
changed_when: false
|
||||
|
||||
- name: Stop Alloy service if it exists (to clean up any issues)
|
||||
ansible.builtin.command: "brew services stop {{ __alloy_brew_package }}"
|
||||
register: __stop_result
|
||||
failed_when: false
|
||||
changed_when: "'Successfully stopped' in __stop_result.stdout"
|
||||
when: "'alloy' in __brew_services.stdout"
|
||||
|
||||
- name: Start Alloy service
|
||||
ansible.builtin.command: "brew services start {{ __alloy_brew_package }}"
|
||||
when:
|
||||
- "'alloy' not in __brew_services.stdout or 'started' not in __brew_services.stdout"
|
||||
register: __service_start
|
||||
failed_when: __service_start.rc != 0
|
||||
|
||||
- name: Restart Alloy service if already running
|
||||
ansible.builtin.command: "brew services restart {{ __alloy_brew_package }}"
|
||||
when:
|
||||
- "'alloy' in __brew_services.stdout and 'started' in __brew_services.stdout"
|
||||
register: __service_restart
|
||||
failed_when: __service_restart.rc != 0
|
||||
|
||||
- name: Check final service status
|
||||
ansible.builtin.command: brew services list
|
||||
register: __final_brew_services
|
||||
changed_when: false
|
||||
|
||||
- name: Verify Alloy installation
|
||||
ansible.builtin.command: alloy --version
|
||||
register: __alloy_version_output
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Display Alloy version
|
||||
ansible.builtin.debug:
|
||||
msg: "Alloy version: {{ __alloy_version_output.stdout }}"
|
||||
when: __alloy_version_output.rc == 0
|
||||
|
||||
- name: Display service status
|
||||
ansible.builtin.debug:
|
||||
msg: "Alloy service status: {{ __final_brew_services.stdout_lines | select('match', '.*alloy.*') | list }}"
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
- name: APT - Install Alloy
|
||||
ansible.builtin.apt:
|
||||
deb: "{{ alloy_download_url_deb }}"
|
||||
state: present
|
||||
notify: restart alloy
|
||||
when: __current_deployed_version.stdout is not defined or alloy_version not in __current_deployed_version.stdout
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
- name: DNF - Install Alloy from remote URL
|
||||
ansible.builtin.package:
|
||||
name: "{{ alloy_download_url_rpm }}"
|
||||
state: present
|
||||
disable_gpg_check: true
|
||||
notify: restart alloy
|
||||
when: __current_deployed_version.stdout is not defined or alloy_version not in __current_deployed_version.stdout
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
- name: Zypper - Install Alloy from remote URL
|
||||
community.general.zypper:
|
||||
name: "{{ alloy_download_url_rpm }}"
|
||||
state: present
|
||||
disable_gpg_check: true
|
||||
notify: restart alloy
|
||||
when: __current_deployed_version.stdout is not defined or alloy_version not in __current_deployed_version.stdout
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
- name: Stop Alloy service
|
||||
ansible.builtin.systemd: # noqa ignore-errors
|
||||
name: alloy
|
||||
state: stopped
|
||||
ignore_errors: true
|
||||
|
||||
- name: Stop Alloy service on macOS
|
||||
ansible.builtin.command: "brew services stop {{ __alloy_brew_package }}"
|
||||
when: ansible_facts['os_family'] == 'Darwin'
|
||||
failed_when: false
|
||||
|
||||
- name: Uninstall Alloy rpm package
|
||||
ansible.builtin.package:
|
||||
name: "alloy"
|
||||
state: absent
|
||||
autoremove: true
|
||||
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']
|
||||
|
||||
- name: Uninstall Alloy deb package
|
||||
ansible.builtin.apt:
|
||||
name: "alloy"
|
||||
state: absent
|
||||
purge: true
|
||||
when: ansible_facts['os_family'] == 'Debian'
|
||||
|
||||
- name: Uninstall Alloy via Homebrew
|
||||
community.general.homebrew:
|
||||
name: "{{ __alloy_brew_package }}"
|
||||
state: absent
|
||||
when: ansible_facts['os_family'] == 'Darwin'
|
||||
|
||||
- name: Uninstall Alloy rpm package (SUSE)
|
||||
community.general.zypper:
|
||||
name: "alloy"
|
||||
state: absent
|
||||
when: ansible_facts['os_family'] == 'Suse'
|
||||
|
||||
- name: Ensure that Alloy firewalld rule is not present - tcp port {{ __alloy_server_http_listen_port }}
|
||||
ansible.posix.firewalld: # noqa ignore-errors
|
||||
immediate: true
|
||||
permanent: true
|
||||
port: "{{ __alloy_server_http_listen_port }}/tcp"
|
||||
state: disabled
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove Alloy directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ remove_me }}"
|
||||
state: absent
|
||||
loop:
|
||||
- "/etc/alloy"
|
||||
- "/etc/systemd/system/alloy.service.d"
|
||||
- "/var/lib/alloy"
|
||||
- "/etc/sysconfig/alloy"
|
||||
- "/etc/default/alloy"
|
||||
loop_control:
|
||||
loop_var: remove_me
|
||||
|
||||
- name: Remove Alloy config directory on macOS
|
||||
ansible.builtin.file:
|
||||
path: "{{ __alloy_config_path_default }}"
|
||||
state: absent
|
||||
when: ansible_facts['os_family'] == 'Darwin'
|
||||
|
||||
- name: Remove the Alloy system user
|
||||
ansible.builtin.user:
|
||||
name: "alloy"
|
||||
force: true
|
||||
state: absent
|
||||
|
||||
- name: Remove Alloy system group
|
||||
ansible.builtin.group:
|
||||
name: "alloy"
|
||||
state: absent
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# Ansible Managed
|
||||
|
||||
{% if alloy_env_file_vars.CONFIG_FILE is not defined or alloy_env_file_vars.CONFIG_FILE | length < 1 %}
|
||||
CONFIG_FILE="/etc/alloy/config.alloy"
|
||||
{% endif %}
|
||||
RESTART_ON_UPGRADE=true
|
||||
|
||||
{% for key, value in alloy_env_file_vars.items() %}
|
||||
{{ key}}="{{value}}"
|
||||
{% endfor %}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
// Ansible Managed
|
||||
|
||||
{{ alloy_config }}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Ansible Managed
|
||||
|
||||
{{ alloy_systemd_override }}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
# macOS/Darwin specific variables
|
||||
__alloy_brew_tap: "grafana/grafana"
|
||||
__alloy_brew_package: "grafana/grafana/alloy"
|
||||
__alloy_config_path_default: "{{ __brew_prefix.stdout | default('/opt/homebrew') }}"
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
__alloy_env_file: "/etc/default/alloy"
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
__alloy_env_file: "/etc/sysconfig/alloy"
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
__alloy_env_file: "/etc/sysconfig/alloy"
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
__alloy_server_http_listen_address: 127.0.0.1
|
||||
__alloy_server_http_listen_port: 12345
|
||||
__alloy_arch_map:
|
||||
x86_64: 'amd64'
|
||||
armv6l: 'arm'
|
||||
armv7l: 'arm'
|
||||
aarch64: 'arm64'
|
||||
__alloy_arch: "{{ __alloy_arch_map[ansible_facts['architecture']] | default(ansible_facts['architecture']) }}"
|
||||
132
ansible_collections/grafana/grafana/roles/grafana/README.md
Normal file
132
ansible_collections/grafana/grafana/roles/grafana/README.md
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
<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
|
||||
|
||||
[](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://rpm.grafana.com | Yum repository URL |
|
||||
| `grafana_yum_key` | https://rpm.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_release_channel` | stable | Apt release chanel (stable or beta) |
|
||||
| `grafana_apt_arch` | {{ 'arm64' if ansible_facts['architecture'] == 'aarch64' else 'amd64' }} | Apt architecture |
|
||||
| `grafana_apt_repo` | deb [arch={{ grafana_apt_arch }} signed-by=/usr/share/keyrings/grafana.asc] https://apt.grafana.com/ {{ grafana_apt_release_channel }} main | Apt repository string |
|
||||
| `grafana_apt_key` | https://apt.grafana.com/gpg.key | Apt repository gpg key |
|
||||
| `grafana_ini.instance_name` | {{ ansible_facts['fqdn'] \| default(ansible_host) \| default(inventory_hostname) }} | Grafana instance name |
|
||||
| `grafana_ini.paths.logs` | /var/log/grafana | Path to logs directory |
|
||||
| `grafana_ini.paths.data` | /var/lib/grafana | Path to database directory |
|
||||
| `grafana_ini.server.http_addr` | 0.0.0.0 | Address on which Grafana listens |
|
||||
| `grafana_ini.server.http_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_ini.server.root_url` | "http://{{ grafana_ini.server.http_addr }}:{{ grafana_ini.server.http_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_ini.server.domain` | "{{ ansible_facts['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_ini.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_ini.security` | { admin_user: admin, admin_password: "" } | [security](http://docs.grafana.org/installation/configuration/#security) configuration section |
|
||||
| `grafana_ini.database` | { type: sqlite3 } | [database](http://docs.grafana.org/installation/configuration/#database) configuration section |
|
||||
| `grafana_ini.users` | { allow_sign_up: false, auto_assign_org_role: Viewer, default_theme: dark } | [users](http://docs.grafana.org/installation/configuration/#users) configuration section |
|
||||
| `grafana_ini.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_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_ini:
|
||||
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).
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
---
|
||||
grafana_version: latest
|
||||
grafana_manage_repo: true
|
||||
|
||||
grafana_yum_repo: "https://rpm.grafana.com"
|
||||
grafana_yum_key: "https://rpm.grafana.com/gpg.key"
|
||||
|
||||
grafana_rhsm_subscription: ""
|
||||
grafana_rhsm_repo: ""
|
||||
|
||||
grafana_apt_release_channel: stable
|
||||
grafana_apt_arch: "{{ 'arm64' if ansible_facts['architecture'] == 'aarch64' else 'amd64' }}"
|
||||
grafana_apt_repo_uri: "https://apt.grafana.com/"
|
||||
grafana_apt_repo: "deb [arch={{ grafana_apt_arch }} signed-by=/usr/share/keyrings/grafana.asc] {{ grafana_apt_repo_uri }} {{ grafana_apt_release_channel }} main"
|
||||
grafana_apt_key: "https://apt.grafana.com/gpg.key"
|
||||
grafana_apt_name: "grafana"
|
||||
|
||||
# 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
|
||||
|
||||
# Should we provision dashboards by following the files structure. This sets the foldersFromFilesStructure option
|
||||
grafana_provisioning_dashboards_from_file_structure: false
|
||||
|
||||
# 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
|
||||
|
||||
grafana_ini_default:
|
||||
instance_name: "{{ ansible_facts['fqdn'] | default(ansible_host) | default(inventory_hostname) }}"
|
||||
|
||||
paths:
|
||||
logs: "/var/log/grafana"
|
||||
data: "/var/lib/grafana"
|
||||
|
||||
server:
|
||||
http_addr: "0.0.0.0"
|
||||
http_port: 3000
|
||||
# External Grafana address. Variable maps to "root_url" in grafana server section
|
||||
#root_url: "http://{{ grafana_ini.server.http_addr }}:{{ grafana_ini.server.http_port }}"
|
||||
domain: "{{ ansible_facts['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
|
||||
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
|
||||
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
|
||||
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: ""
|
||||
|
||||
# User management and registration
|
||||
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
|
||||
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_api_url: "{{ grafana_ini.server.root_url }}"
|
||||
|
||||
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
|
||||
|
||||
#######
|
||||
# Plugins to install 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"
|
||||
|
||||
# Alert resources channels to configure
|
||||
grafana_alert_resources: {}
|
||||
|
||||
# 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: {}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
- 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_ini.paths.data }}/dashboards"
|
||||
recurse: true
|
||||
owner: "grafana"
|
||||
group: "grafana"
|
||||
mode: "u=rwX,g=rX,o=rX"
|
||||
become: true
|
||||
listen: "provisioned dashboards changed"
|
||||
|
||||
- name: "Set privileges on provisioned dashboards directory"
|
||||
ansible.builtin.file:
|
||||
path: "{{ grafana_ini.paths.data }}/dashboards"
|
||||
state: "directory"
|
||||
recurse: false
|
||||
mode: "0755"
|
||||
become: true
|
||||
listen: "provisioned dashboards changed"
|
||||
|
||||
- name: "Find dashboards subdirectories"
|
||||
ansible.builtin.find:
|
||||
paths: "{{ grafana_ini.paths.data }}/dashboards"
|
||||
recurse: yes
|
||||
file_type: directory
|
||||
register: __dashboards_subdirs
|
||||
become: true
|
||||
listen: "provisioned dashboards changed"
|
||||
|
||||
- name: "Set privileges on provisioned dashboards sub-directories"
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: "directory"
|
||||
recurse: false
|
||||
mode: "0755"
|
||||
with_items:
|
||||
- "{{ __dashboards_subdirs.files | map(attribute='path') | list }}"
|
||||
become: true
|
||||
listen: "provisioned dashboards changed"
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
galaxy_info:
|
||||
author: "Grafana"
|
||||
description: "Grafana - platform for analytics and monitoring"
|
||||
license: "GPL-3.0-or-later"
|
||||
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
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
---
|
||||
- name: "Run role"
|
||||
hosts: all
|
||||
any_errors_fatal: true
|
||||
roles:
|
||||
- grafana.grafana.grafana
|
||||
vars:
|
||||
grafana_version: 6.2.5
|
||||
grafana_ini:
|
||||
security:
|
||||
admin_user: admin
|
||||
admin_password: "password"
|
||||
server:
|
||||
http_addr: "127.0.0.1"
|
||||
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
|
||||
log:
|
||||
mode: syslog
|
||||
level: warn
|
||||
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
|
||||
|
|
@ -0,0 +1 @@
|
|||
---
|
||||
|
|
@ -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")
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
- name: "Run role"
|
||||
hosts: all
|
||||
any_errors_fatal: true
|
||||
roles:
|
||||
- grafana.grafana.grafana
|
||||
vars:
|
||||
grafana_ini:
|
||||
security:
|
||||
admin_user: admin
|
||||
admin_password: password
|
||||
|
|
@ -0,0 +1 @@
|
|||
---
|
||||
|
|
@ -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
|
||||
|
|
@ -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_ini.security.admin_user }}"
|
||||
password: "{{ grafana_ini.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_ini.security.admin_user }}"
|
||||
password: "{{ grafana_ini.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"
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
---
|
||||
- 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/notification"
|
||||
- path: "/etc/grafana/provisioning/plugins"
|
||||
- path: "/etc/grafana/provisioning/alerting"
|
||||
- path: "{{ grafana_ini.paths.logs }}"
|
||||
owner: grafana
|
||||
- path: "{{ grafana_ini.paths.data }}"
|
||||
owner: grafana
|
||||
- path: "{{ grafana_ini.paths.data }}/dashboards"
|
||||
owner: grafana
|
||||
- path: "{{ grafana_ini.paths.data }}/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_ini.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_ini.auth"
|
||||
- "'enabled' not in grafana_ini.auth.ldap or grafana_ini.auth.ldap.enabled"
|
||||
|
||||
- name: "Enable grafana socket"
|
||||
when:
|
||||
- "grafana_ini.server.protocol is defined and grafana_ini.server.protocol == 'socket'"
|
||||
- "grafana_ini.server.socket | dirname != '/var/run'"
|
||||
block:
|
||||
- name: "Create grafana socket directory"
|
||||
ansible.builtin.file:
|
||||
path: "{{ grafana_ini.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_ini.server.http_port | int <= 1024"
|
||||
- "grafana_cap_net_bind_service"
|
||||
|
||||
- name: Create a directory for overrides.conf unit file if it does not exist
|
||||
ansible.builtin.file:
|
||||
path: /etc/systemd/system/grafana-server.service.d
|
||||
state: directory
|
||||
mode: '0755'
|
||||
when:
|
||||
- "grafana_ini.server.http_port | int <= 1024"
|
||||
- "grafana_cap_net_bind_service"
|
||||
|
||||
- name: "Enable grafana to ports lower than port 1024 in systemd unitfile"
|
||||
ansible.builtin.blockinfile:
|
||||
path: /etc/systemd/system/grafana-server.service.d/overrides.conf
|
||||
create: true
|
||||
block: |
|
||||
[Service]
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
when:
|
||||
- "grafana_ini.server.http_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
|
||||
|
|
@ -0,0 +1,245 @@
|
|||
---
|
||||
- name: "Create local grafana dashboard directory"
|
||||
become: false
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
ansible.builtin.tempfile:
|
||||
state: directory
|
||||
register: __tmp_dashboards
|
||||
changed_when: false
|
||||
check_mode: false
|
||||
|
||||
- name: "Download grafana.net dashboards"
|
||||
become: false
|
||||
delegate_to: localhost
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
- "grafana_dashboards | length > 0"
|
||||
block:
|
||||
- name: "Get latest revision id"
|
||||
ansible.builtin.uri:
|
||||
url: "https://grafana.com/api/dashboards/{{ item.dashboard_id }}"
|
||||
method: GET
|
||||
return_content: yes
|
||||
register: __dashboard_info
|
||||
loop: "{{ grafana_dashboards }}"
|
||||
when: item.dashboard_url is not defined
|
||||
|
||||
- name: "Extract revision_id if not defined in grafana_dashboards"
|
||||
ansible.builtin.set_fact:
|
||||
__dashboards_with_revision: >-
|
||||
{{
|
||||
__dashboard_info.results | map(attribute='json.revision')
|
||||
| map('default', 1) | map('community.general.dict_kv', 'revision_id')
|
||||
| zip(grafana_dashboards) | map('combine')
|
||||
}}
|
||||
|
||||
- name: "Download grafana dashboard from grafana.net to local directory"
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ item.dashboard_url if item.dashboard_url is defined else
|
||||
('https://grafana.com/api/dashboards/' ~ item.dashboard_id ~
|
||||
'/revisions/' ~ item.revision_id | default(1) ~ '/download') }}"
|
||||
dest: "{{ __tmp_dashboards.path }}/{{ item.dashboard_id ~ '.json'
|
||||
if item.dashboard_id is defined else item.dashboard_url | basename}}"
|
||||
mode: "0644"
|
||||
register: __download_dashboards
|
||||
until: "__download_dashboards is succeeded"
|
||||
retries: 5
|
||||
delay: 2
|
||||
changed_when: false
|
||||
loop: "{{ __dashboards_with_revision }}"
|
||||
|
||||
# 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: "{{ item.dest }}"
|
||||
regexp: '"(?:\${)?DS_[A-Z0-9_-]+(?:})?"'
|
||||
replace: '"{{ item.item.datasource }}"'
|
||||
changed_when: false
|
||||
loop: "{{ __download_dashboards.results }}"
|
||||
loop_control:
|
||||
label: "{{ item.item }}"
|
||||
|
||||
- name: "Import grafana dashboards via api"
|
||||
community.grafana.grafana_dashboard:
|
||||
grafana_url: "{{ grafana_api_url }}"
|
||||
grafana_user: "{{ grafana_ini.security.admin_user }}"
|
||||
grafana_password: "{{ grafana_ini.security.admin_password }}"
|
||||
path: "{{ item }}"
|
||||
commit_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_ini.paths.data }}/dashboards"
|
||||
foldersFromFilesStructure: {{ grafana_provisioning_dashboards_from_file_structure | bool | to_nice_yaml }}
|
||||
backup: false
|
||||
owner: root
|
||||
group: grafana
|
||||
mode: "0640"
|
||||
become: true
|
||||
notify: restart_grafana
|
||||
|
||||
- name: "Register previously copied dashboards"
|
||||
ansible.builtin.find:
|
||||
paths: "{{ grafana_ini.paths.data }}/dashboards"
|
||||
hidden: true
|
||||
recurse: true
|
||||
patterns:
|
||||
- "*.json"
|
||||
register: __dashboards_present
|
||||
when: grafana_provisioning_synced | bool
|
||||
|
||||
- name: "Register previously created folders"
|
||||
ansible.builtin.find:
|
||||
paths: "{{ grafana_ini.paths.data }}/dashboards/"
|
||||
recurse: yes
|
||||
file_type: directory
|
||||
register: __dashboards_dir_present
|
||||
become: true
|
||||
when: grafana_provisioning_synced
|
||||
|
||||
- name: "Import grafana.net dashboards"
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item }}"
|
||||
dest: "{{ grafana_ini.paths.data }}/dashboards/{{ item | basename }}"
|
||||
owner: root
|
||||
group: grafana
|
||||
mode: "0644"
|
||||
with_fileglob:
|
||||
- "{{ __tmp_dashboards.path }}/*"
|
||||
become: true
|
||||
register: __dashboards_copied
|
||||
notify: "provisioned dashboards changed"
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: "Verify if custom grafana dashboards dir exist"
|
||||
ansible.builtin.stat:
|
||||
path: "{{ grafana_dashboards_dir }}"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
register: __grafana_custom_dashboards_dir
|
||||
|
||||
- name: "Import custom grafana dashboards"
|
||||
when: __grafana_custom_dashboards_dir.stat.exists
|
||||
block:
|
||||
- name: "Find which directories to create"
|
||||
ansible.builtin.find:
|
||||
paths: "{{ grafana_dashboards_dir }}/"
|
||||
recurse: yes
|
||||
file_type: directory
|
||||
register: __dashboards_subdirs
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
|
||||
- name: "Create dashboard folders"
|
||||
ansible.builtin.file:
|
||||
path: "{{ grafana_ini.paths.data }}/dashboards/{{ item }}"
|
||||
state: "directory"
|
||||
recurse: false
|
||||
owner: "grafana"
|
||||
group: "grafana"
|
||||
mode: "0755"
|
||||
loop: "{{ __dashboards_subdirs.files | map(attribute='path') | sort | regex_replace(grafana_dashboards_dir + '/*', '') }}"
|
||||
become: true
|
||||
register: __dashboards_dir_created
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: "Copy dashboard files"
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item.path }}"
|
||||
dest: '{{ grafana_ini.paths.data }}/dashboards/{{ item.path | regex_replace(grafana_dashboards_dir + "/*", "") }}'
|
||||
owner: root
|
||||
group: grafana
|
||||
mode: "0644"
|
||||
loop: "{{ __found_dashboards.files | default([]) }}"
|
||||
become: true
|
||||
register: __dashboards_copied_custom
|
||||
notify: "provisioned dashboards changed"
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: "Register present and copied folders list"
|
||||
ansible.builtin.set_fact:
|
||||
__folders_present_list: "{{ __dashboards_dir_present.files | default([]) | map(attribute='path') | list }}"
|
||||
__folders_copied_list: "{{ __dashboards_dir_created.results | default([]) | map(attribute='path') | list }}"
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: "Register present and copied dashboards list"
|
||||
ansible.builtin.set_fact:
|
||||
__dashboards_present_list: "{{ __dashboards_present.files | default([]) | map(attribute='path') | list }}"
|
||||
__dashboards_copied_list: "{{
|
||||
(
|
||||
(__dashboards_copied.results | default([]) | map(attribute='dest') | list) +
|
||||
(__dashboards_copied_custom.results | default([]) | map(attribute='dest') | list)
|
||||
) | list
|
||||
}}"
|
||||
when: not ansible_check_mode
|
||||
|
||||
- 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:
|
||||
- __dashboards_present_list is defined and __dashboards_present_list
|
||||
- __dashboards_copied_list is defined and __dashboards_copied_list
|
||||
- grafana_provisioning_synced | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: "Remove folders not present on deployer machine (synchronize)"
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
loop: "{{ __folders_present_list | difference(__folders_copied_list) }}"
|
||||
become: true
|
||||
when: grafana_provisioning_synced and not ansible_check_mode
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
- name: "Ensure datasources exist (via API)"
|
||||
community.grafana.grafana_datasource:
|
||||
grafana_url: "{{ grafana_api_url }}"
|
||||
grafana_user: "{{ grafana_ini.security.admin_user }}"
|
||||
grafana_password: "{{ grafana_ini.security.admin_password }}"
|
||||
name: "{{ item.name }}"
|
||||
ds_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"
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
---
|
||||
- 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 is defined
|
||||
- _grafana_dependencies | length > 0
|
||||
|
||||
- name: "Prepare zypper"
|
||||
when:
|
||||
- "ansible_facts['pkg_mgr'] == 'zypper'"
|
||||
- "(grafana_manage_repo)"
|
||||
environment: "{{ grafana_environment }}"
|
||||
block:
|
||||
- name: import Grafana RPM Key
|
||||
ansible.builtin.rpm_key:
|
||||
state: present
|
||||
key: "{{ grafana_yum_key }}"
|
||||
|
||||
- name: "Add Grafana zypper repository"
|
||||
community.general.zypper_repository:
|
||||
name: grafana
|
||||
description: grafana
|
||||
repo: "{{ grafana_yum_repo }}"
|
||||
enabled: true
|
||||
disable_gpg_check : "{{ false if (grafana_yum_key) else omit }}"
|
||||
runrefresh: true
|
||||
when: "(not grafana_rhsm_repo)"
|
||||
|
||||
- name: "Prepare yum/dnf"
|
||||
when:
|
||||
- "ansible_facts['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_facts['pkg_mgr'] == 'apt'"
|
||||
- "(grafana_manage_repo)"
|
||||
environment: "{{ grafana_environment }}"
|
||||
block:
|
||||
- name: "Use deb822 format?"
|
||||
ansible.builtin.set_fact:
|
||||
__use_deb822: "{{ (ansible_facts['distribution'] == 'Debian' and (ansible_facts['distribution_major_version'] | int) >= 12) or
|
||||
(ansible_facts['distribution'] == 'Ubuntu' and (ansible_facts['distribution_major_version'] | int) >= 24) }}"
|
||||
- name: "Import Grafana apt gpg key"
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ grafana_apt_key }}"
|
||||
dest: /usr/share/keyrings/grafana.asc
|
||||
mode: "0644"
|
||||
when: not __use_deb822
|
||||
- name: "Add Grafana apt repository"
|
||||
when: not __use_deb822
|
||||
ansible.builtin.apt_repository:
|
||||
repo: "{{ grafana_apt_repo }}"
|
||||
update_cache: true
|
||||
- name: "Add Grafana apt repository"
|
||||
when: __use_deb822
|
||||
ansible.builtin.deb822_repository:
|
||||
name: "{{ grafana_apt_name }}"
|
||||
types: deb
|
||||
uris: "{{ grafana_apt_repo_uri }}"
|
||||
suites: "{{ grafana_apt_release_channel }}"
|
||||
components:
|
||||
- main
|
||||
architectures:
|
||||
- "{{ grafana_apt_arch }}"
|
||||
signed_by: "{{ grafana_apt_key }}"
|
||||
register: __update_cache
|
||||
- name: "Update apt cache"
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
when: __update_cache is defined and __update_cache.changed
|
||||
|
||||
- name: "Install Grafana"
|
||||
ansible.builtin.package:
|
||||
name: "{{ grafana_package }}"
|
||||
state: "{{ (grafana_version == 'latest') | ternary('latest', 'present') }}"
|
||||
notify: restart_grafana
|
||||
133
ansible_collections/grafana/grafana/roles/grafana/tasks/main.yml
Normal file
133
ansible_collections/grafana/grafana/roles/grafana/tasks/main.yml
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
---
|
||||
- name: Inherit default vars
|
||||
ansible.builtin.set_fact:
|
||||
grafana_ini: "{{ grafana_ini_default | ansible.builtin.combine(grafana_ini | default({}), recursive=true) }}"
|
||||
no_log: "{{ 'false' if lookup('env', 'CI') else 'true' }}"
|
||||
tags:
|
||||
- always
|
||||
- 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_facts['distribution'] | lower }}-{{ ansible_facts['distribution_version'] | lower }}.yml"
|
||||
- "{{ ansible_facts['distribution'] | lower }}-{{ ansible_facts['distribution_major_version'] | lower }}.yml"
|
||||
- "{{ ansible_facts['os_family'] | lower }}-{{ ansible_facts['distribution_major_version'] | lower }}.yml"
|
||||
- "{{ ansible_facts['distribution'] | lower }}.yml"
|
||||
- "{{ ansible_facts['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_ini.server.http_addr if grafana_ini.server.protocol is undefined or grafana_ini.server.protocol in ['http', 'https'] else omit }}"
|
||||
port: "{{ grafana_ini.server.http_port if grafana_ini.server.protocol is undefined or grafana_ini.server.protocol in ['http', 'https'] else omit }}"
|
||||
path: "{{ grafana_ini.server.socket | default() if grafana_ini.server.protocol is defined and grafana_ini.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 or grafana_alert_resources | length > 0"
|
||||
|
||||
- name: Find dashboards to be provisioned
|
||||
ansible.builtin.find:
|
||||
paths: "{{ grafana_dashboards_dir }}"
|
||||
recurse: true
|
||||
patterns: "*.json"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
register: __found_dashboards
|
||||
|
||||
- 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['files'] | length > 0"
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
# legacy config
|
||||
- name: "Create/Delete/Update alert notifications channels (provisioning)"
|
||||
ansible.builtin.copy:
|
||||
content: |
|
||||
apiVersion: 1
|
||||
{{ grafana_alert_notifications | to_nice_yaml }}
|
||||
dest: /etc/grafana/provisioning/notification/ansible.yml
|
||||
owner: root
|
||||
group: grafana
|
||||
mode: "0640"
|
||||
become: true
|
||||
notify: restart_grafana
|
||||
when: grafana_use_provisioning and grafana_alert_notifications | length > 0
|
||||
|
||||
# new alert resources
|
||||
- name: "Create/Delete/Update alert resources (provisioning)"
|
||||
ansible.builtin.copy:
|
||||
content: |
|
||||
apiVersion: 1
|
||||
{{ grafana_alert_resources | to_nice_yaml }}
|
||||
dest: /etc/grafana/provisioning/alerting/ansible.yml
|
||||
owner: root
|
||||
group: grafana
|
||||
mode: "0640"
|
||||
become: true
|
||||
notify: restart_grafana
|
||||
when: grafana_use_provisioning and grafana_alert_resources | length > 0
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
- name: "Check which plugins are installed"
|
||||
ansible.builtin.find:
|
||||
file_type: directory
|
||||
recurse: false
|
||||
paths: "{{ grafana_ini.paths.data }}/plugins"
|
||||
register: __installed_plugins
|
||||
|
||||
- name: "Install plugins"
|
||||
become: true
|
||||
ansible.builtin.command:
|
||||
cmd: "grafana-cli --pluginsDir {{ grafana_ini.paths.data }}/plugins plugins install {{ item }}"
|
||||
creates: "{{ grafana_ini.paths.data }}/plugins/{{ item }}"
|
||||
loop: "{{ grafana_plugins | difference(__installed_plugins.files) }}"
|
||||
register: __plugin_install
|
||||
until: "__plugin_install is succeeded"
|
||||
retries: 5
|
||||
delay: 2
|
||||
notify:
|
||||
- restart_grafana
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
---
|
||||
- name: "Check variable types"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- grafana_logs_dir is undefined
|
||||
- grafana_data_dir is undefined
|
||||
- grafana_server is undefined
|
||||
- grafana_database is undefined
|
||||
- grafana_security is undefined
|
||||
- grafana_remote_cache is undefined
|
||||
- grafana_welcome_email_on_sign_up is undefined
|
||||
- grafana_users is undefined
|
||||
- grafana_auth is undefined
|
||||
- grafana_auth_generic_oauth is undefined
|
||||
- grafana_session is undefined
|
||||
- grafana_analytics is undefined
|
||||
- grafana_smtp is undefined
|
||||
- grafana_alerting is undefined
|
||||
- grafana_unified_alerting is undefined
|
||||
- grafana_log is undefined
|
||||
- grafana_metrics is undefined
|
||||
- grafana_tracing is undefined
|
||||
- grafana_snapshots is undefined
|
||||
- grafana_image_storage is undefined
|
||||
- grafana_date_formats is undefined
|
||||
- grafana_feature_toggles is undefined
|
||||
- grafana_plugins_ops is undefined
|
||||
- grafana_instance is undefined
|
||||
- grafana_address is undefined
|
||||
- grafana_port is undefined
|
||||
- grafana_domain is undefined
|
||||
- grafana_url is undefined
|
||||
- grafana_panels is undefined
|
||||
fail_msg: Check upgrade notes
|
||||
|
||||
- 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_ini.security.admin_user)"
|
||||
when:
|
||||
- "grafana_ini.security.admin_user == '' or
|
||||
grafana_ini.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_ini.security.admin_password)"
|
||||
when:
|
||||
- "grafana_ini.security.admin_password == '' or
|
||||
grafana_ini.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: "Invalid database configuration. Please look at http://docs.grafana.org/installation/configuration/#database"
|
||||
when: "( grafana_ini.database.type == 'sqlite3' and grafana_ini.database.url is defined ) or
|
||||
( grafana_ini.database.type != 'sqlite3' and grafana_ini.database.path is defined ) or
|
||||
( grafana_ini.database.type == 'sqlite3' and grafana_ini.database.host is defined ) or
|
||||
( grafana_ini.database.type == 'sqlite3' and grafana_ini.database.user is defined ) or
|
||||
( grafana_ini.database.type == 'sqlite3' and grafana_ini.database.password is defined ) or
|
||||
( grafana_ini.database.type == 'sqlite3' and grafana_ini.database.server_cert_name is defined )"
|
||||
|
||||
- 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_ini.auth.ldap is"
|
||||
ansible.builtin.fail:
|
||||
msg: "You need to configure grafana_ldap.servers and grafana_ldap.group_mappings when grafana_ini.auth.ldap is set"
|
||||
when:
|
||||
- "'ldap' in grafana_ini.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_ini.server.http_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_ini.server.http_port | int <= 1024"
|
||||
- "not grafana_cap_net_bind_service"
|
||||
|
||||
- name: "Fail if grafana_ini.server.socket not defined when in socket mode"
|
||||
ansible.builtin.fail:
|
||||
msg: "You need to configure grafana_ini.server.socket when grafana_ini.server.protocol is set to 'socket'"
|
||||
when:
|
||||
- "grafana_ini.server.protocol is defined and grafana_ini.server.protocol == 'socket'"
|
||||
- "grafana_ini.server.socket is undefined or grafana_ini.server.socket == ''"
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
{{ ansible_managed | comment }}
|
||||
# More informations:
|
||||
# http://docs.grafana.org/installation/configuration
|
||||
# https://github.com/grafana/grafana/blob/master/conf/sample.ini
|
||||
|
||||
{% for k, v in grafana_ini.items() %}
|
||||
{% if v is not mapping %}
|
||||
{{ k }} = {{ v }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% for section, items in grafana_ini.items() %}
|
||||
{% if items is mapping %}
|
||||
[{{ section }}]
|
||||
{% for sub_key, sub_value in items.items() %}
|
||||
{% if sub_value is mapping %}
|
||||
|
||||
[{{ section }}.{{ sub_key }}]
|
||||
{% for k, v in sub_value.items() %}
|
||||
{{ k }} = {{ v }}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{{ sub_key }} = {{ sub_value }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
|
@ -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 %}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
{{ ansible_managed | comment }}
|
||||
d {{ grafana_ini.server.socket | dirname }} 0775 grafana grafana
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
molecule
|
||||
docker
|
||||
pytest-testinfra
|
||||
jmespath
|
||||
selinux
|
||||
passlib
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
grafana_package: "grafana{% if ansible_facts['architecture'] == 'armv6l' %}-rpi{% endif %}{{ (grafana_version != 'latest') | ternary('=' ~ grafana_version, '') }}"
|
||||
_grafana_dependencies:
|
||||
- apt-transport-https
|
||||
- adduser
|
||||
- ca-certificates
|
||||
- libfontconfig
|
||||
- gnupg2
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
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
|
||||
# applies to SuSe too
|
||||
_grafana_dependencies:
|
||||
- insserv-compat
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
| | This Ansible role is now in maintenance mode only. We recommend using the Grafana Alloy Role for future deployments and updates.
|
||||
|---|---|
|
||||
|
||||
# Ansible Role for Grafana Agent
|
||||
|
||||
Ansible Role to deploy Grafana Agent on Linux hosts. Using this Role, Grafana Agent can be deployed on RedHat, Ubuntu, Debian, CentOS
|
||||
and Fedora linux distributions.
|
||||
|
||||
## Requirements
|
||||
|
||||
Please ensure that `curl` is intalled on Ansible controller.
|
||||
|
||||
To use this role, You need a YAML file having the Grafana Agent configuration.
|
||||
|
||||
## Role Variables
|
||||
|
||||
All variables which can be overridden are stored in [./defaults/main.yaml](./defaults/main.yaml) file as well as in table below.
|
||||
|
||||
| Variable | Default | Description |
|
||||
| :------ | :------ | :--------- |
|
||||
| `grafana_agent_version` | `latest` | version of the agent to install |
|
||||
| `grafana_agent_base_download_url` | `https://github.com/{{ _grafana_agent_github_org }}/{{ _grafana_agent_github_repo }}/releases/download` | base download url. Github or mirror to download from |
|
||||
| `grafana_agent_install_dir` | `/opt/grafana-agent/bin` | directory to install the binary to |
|
||||
| `grafana_agent_binary` | `grafana-agent` | name to use for the binary |
|
||||
| `grafana_agent_config_dir` | `/etc/grafana-agent` | directory to store the configuration files in |
|
||||
| `grafana_agent_config_filename` | `config.yaml` | name of the configuration file for the agent |
|
||||
| `grafana_agent_env_file` | `service.env` | name of the environment file loaded by the system unit file |
|
||||
| `grafana_agent_service_extra` | "" | dictionary of additional custom settings for the systemd service file |
|
||||
| `grafana_agent_local_tmp_dir` | `/tmp/grafana-agent` | temporary directory to create on the controller/localhost where the archive will be downloaded to |
|
||||
| `grafana_agent_data_dir` | `/var/lib/grafana-agent` | the data directory to create for the wal and positions |
|
||||
| `grafana_agent_wal_dir` | `"{{ grafana_agent_data_dir }}/data"` | wal directory to use, should be a sub-folder of grafana_agent_data_dir, will automatically be created when the agent starts |
|
||||
| `grafana_agent_positions_dir` | `"{{ grafana_agent_data_dir }}/data"` | positions directory to use, should be a sub-folder of grafana_agent_data_dir, will automatically be created when the agent starts |
|
||||
| `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_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_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_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_flags_extra` | see [./defaults/main.yaml](./defaults/main.yaml) | dictionary of additional command-line flags, run grafana-agent --help for a complete list. [Docs](https://grafana.com/docs/agent/latest/configuration/flags/) |
|
||||
| `grafana_agent_env_vars` | `{}` | sets Environment variables in the systemd service configuration. |
|
||||
| `grafana_agent_env_file_vars` | `{}` | dictionary of key/pair values to write to the environment file that is loaded by the service, with the flag `--config.expand-env=true` any generated config files will support the expansion of environment variables at runtime by referencing ${ENVVAR}. be aware of boolean values, when output they will result in the proper-cased string "True" and "False" |
|
||||
| `grafana_agent_provisioned_config_file` | `""` | path to a config file on the controller that will be used instead of the provided configs below if specified. |
|
||||
| `grafana_agent_server_config` | see [./defaults/main.yaml](./defaults/main.yaml) | Configures the server of the Agent used to enable self-scraping, [Docs](https://grafana.com/docs/agent/latest/configuration/server-config/) |
|
||||
| `grafana_agent_metrics_config` | see [./defaults/main.yaml](./defaults/main.yaml) | Configures metric collection, [Docs](https://grafana.com/docs/agent/latest/configuration/metrics-config/) |
|
||||
| `grafana_agent_logs_config` | see [./defaults/main.yaml](./defaults/main.yaml) | Configures logs collection, [Docs](https://grafana.com/docs/agent/latest/configuration/logs-config/) |
|
||||
| `grafana_agent_traces_config` | see [./defaults/main.yaml](./defaults/main.yaml) | Configures traces collection, [Docs](https://grafana.com/docs/agent/latest/configuration/traces-config/) |
|
||||
| `grafana_agent_integrations_config` | see [./defaults/main.yaml](./defaults/main.yaml) | Configures integrations for the agent, [Docs](https://grafana.com/docs/agent/latest/configuration/integrations/) |
|
||||
|
||||
## OS Support
|
||||
The Grafana Agent role has been tested on below Operating Systems
|
||||
- Ubuntu 22.10, Ubunutu 22.04 LTS, Ubunutu 20.04 LTS, Ubunutu 18.04 LTS
|
||||
- Fedora 37, Fedora 36
|
||||
- Debian 11, Debian 10, Debian 9
|
||||
- CentOS 9 Stream, CentOS 8 Stream, CentOS 7
|
||||
- AlmaLinux 9, AlmaLinux 8
|
||||
- RockyLinux 9, RockyLinux 8
|
||||
|
||||
## Example Playbooks
|
||||
|
||||
See [examples](../../examples)
|
||||
|
||||
## License
|
||||
|
||||
See [LICENSE](https://github.com/grafana/grafana-ansible-collection/blob/main/LICENSE)
|
||||
|
||||
## Author Information
|
||||
|
||||
- [Grafana Labs](https://github.com/grafana)
|
||||
- [Ishan Jain](https://github.com/ishanjainn)
|
||||
- [Aaron Benton](https://github.com/bentonam)
|
||||
- [Vitaly Zhuravlev](https://github.com/v-zhuravlev)
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
---
|
||||
# version of the agent to install
|
||||
grafana_agent_version: latest
|
||||
|
||||
# base download url. Github or mirror to download from
|
||||
grafana_agent_base_download_url: "https://github.com/{{ _grafana_agent_github_org }}/{{ _grafana_agent_github_repo }}/releases/download"
|
||||
|
||||
# directory to install the binary to
|
||||
grafana_agent_install_dir: /opt/grafana-agent/bin
|
||||
|
||||
# name to use for the binary
|
||||
grafana_agent_binary: grafana-agent
|
||||
|
||||
# directory to store the configuration files in
|
||||
grafana_agent_config_dir: /etc/grafana-agent
|
||||
|
||||
# name of the configuration file for the agent
|
||||
grafana_agent_config_filename: config.yaml
|
||||
|
||||
# name of the environment file loaded by the system unit file
|
||||
grafana_agent_env_file: service.env
|
||||
|
||||
# dictionary of additional custom settings for the systemd service file
|
||||
grafana_agent_service_extra: {}
|
||||
|
||||
# temporary directory to create on the controller/localhost where the archive will be downloaded to
|
||||
grafana_agent_local_tmp_dir: /tmp/grafana-agent
|
||||
|
||||
# data directory to create for the wal and positions
|
||||
grafana_agent_data_dir: /var/lib/grafana-agent
|
||||
|
||||
# wal directory to use, should be a sub-folder of grafana_agent_data_dir, will automatically be created when the agent starts
|
||||
grafana_agent_wal_dir: "{{ grafana_agent_data_dir }}/wal"
|
||||
|
||||
# positions directory to use, should be a sub-folder of grafana_agent_data_dir, will automatically be created when the agent starts
|
||||
grafana_agent_positions_dir: "{{ grafana_agent_data_dir }}/positions"
|
||||
|
||||
# mode to run Grafana Agent in. Can be "flow" or "static".
|
||||
# Docs: https://grafana.com/docs/agent/latest/flow/
|
||||
grafana_agent_mode: static
|
||||
|
||||
# os user to create for the agent to run as
|
||||
grafana_agent_user: grafana-agent
|
||||
|
||||
# os user group to create for the agent
|
||||
grafana_agent_user_group: grafana-agent
|
||||
|
||||
# Configurable user groups that the grafana agent can be put in so that it can access logs
|
||||
# (See https://github.com/grafana/grafana-ansible-collection/issues/40)
|
||||
grafana_agent_user_groups: []
|
||||
|
||||
# the shell for the user
|
||||
grafana_agent_user_shell: /usr/sbin/nologin
|
||||
|
||||
# whether or not to create a home directory for the user
|
||||
grafana_agent_user_createhome: false
|
||||
|
||||
# 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: ""
|
||||
|
||||
# dictionary of additional command-line flags, run grafana-agent --help for a complete list
|
||||
# Docs: https://grafana.com/docs/agent/latest/static/configuration/flags/
|
||||
grafana_agent_flags_extra:
|
||||
config.expand-env: 'true'
|
||||
config.enable-read-api: 'false'
|
||||
server.register-instrumentation: 'true'
|
||||
server.http.address: 127.0.0.1:12345
|
||||
server.grpc.address: 127.0.0.1:12346
|
||||
|
||||
# sets Environment variables in the systemd service configuration.
|
||||
grafana_agent_env_vars: {}
|
||||
|
||||
# dictionary of key/pair values to write to the environment file that is loaded by the service, with the flag --config.expand-env=true
|
||||
# any generated config files will support the expansion of environment variables at runtime by referencing ${ENVVAR}.
|
||||
# be aware of boolean values, when output they will result in the proper-cased string "True" and "False"
|
||||
grafana_agent_env_file_vars: {}
|
||||
|
||||
# path to a config file on the controller that will be used instead of the provided configs below if specified.
|
||||
grafana_agent_provisioned_config_file: ""
|
||||
|
||||
#################################################################################################
|
||||
# Configures the server of the Agent used to enable self-scraping #
|
||||
#################################################################################################
|
||||
# Docs: https://grafana.com/docs/agent/latest/static/configuration/server-config/
|
||||
# the entire dictionary value for this object is copied to the server: block in the config file
|
||||
grafana_agent_server_config:
|
||||
# Log only messages with the given severity or above. Supported values [debug,
|
||||
# info, warn, error]. This level affects logging for all Agent-level logs, not
|
||||
# just the HTTP and gRPC server.
|
||||
#
|
||||
# Note that some integrations use their own loggers which ignore this
|
||||
# setting.
|
||||
log_level: info
|
||||
|
||||
#################################################################################################
|
||||
# Configures metric collection #
|
||||
#################################################################################################
|
||||
# Docs: https://grafana.com/docs/agent/latest/static/configuration/metrics-config/
|
||||
# the entire dictionary value for this object is copied to the metrics: block in the config file
|
||||
grafana_agent_metrics_config:
|
||||
# Configure values for all Prometheus instances
|
||||
# Docs: https://grafana.com/docs/agent/latest/static/configuration/metrics-config/#global_config
|
||||
global:
|
||||
# How frequently should Prometheus instances scrape.
|
||||
scrape_interval: 1m
|
||||
|
||||
# How long to wait before timing out a scrape from a target.
|
||||
scrape_timeout: 10s
|
||||
|
||||
# A dictionary of key/pair static labels to add for all metrics.
|
||||
external_labels: {}
|
||||
|
||||
# Default set of remote_write endpoints. If an instance doesn't define any
|
||||
# remote_writes, it will use this list.
|
||||
# Docs: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write
|
||||
remote_write: []
|
||||
|
||||
# The list of Prometheus instances to launch with the agent.
|
||||
# Docs: https://grafana.com/docs/agent/latest/static/configuration/metrics-config/#metrics_instance_config
|
||||
configs: []
|
||||
# - name: name-of-scrape-job
|
||||
# # Docs: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config
|
||||
# scrape_configs: []
|
||||
# # Optional list of remote_write targets, if not specified metrics.global.remote_write is used
|
||||
# # Docs: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write
|
||||
# remote_write: []
|
||||
|
||||
# Configure the directory used by instances to store their WAL.
|
||||
#
|
||||
# The Grafana Agent assumes that all folders within wal_directory are managed by
|
||||
# the agent itself.
|
||||
wal_directory: "{{ grafana_agent_wal_dir }}"
|
||||
# Configures how long ago an abandoned (not associated with an instance) WAL
|
||||
# may be written to before being eligible to be deleted
|
||||
wal_cleanup_age: 12h
|
||||
# Configures how often checks for abandoned WALs to be deleted are performed.
|
||||
# A value of 0 disables periodic cleanup of abandoned WALs
|
||||
wal_cleanup_period: 30m
|
||||
|
||||
#################################################################################################
|
||||
# Configures logs collection #
|
||||
#################################################################################################
|
||||
# Docs: https://grafana.com/docs/agent/latest/static/configuration/logs-config/
|
||||
# the entire dictionary value for this object is copied to the logs: block in the config file
|
||||
grafana_agent_logs_config:
|
||||
# Directory to store Loki Promtail positions files in. Positions files are
|
||||
# required to read logs, and are used to store the last read offset of log
|
||||
# sources. The positions files will be stored in
|
||||
# <positions_directory>/<logs_instance_config.name>.yml.
|
||||
#
|
||||
# Optional only if every config has a positions.filename manually provided.
|
||||
#
|
||||
# This directory will be automatically created if it doesn't exist.
|
||||
positions_directory: "{{ grafana_agent_positions_dir }}"
|
||||
# Configure values for all Loki Promtail instances.
|
||||
global:
|
||||
# Docs: https://grafana.com/docs/agent/latest/static/configuration/logs-config/#logs_instance_config
|
||||
clients: []
|
||||
|
||||
#################################################################################################
|
||||
# Configures traces collection #
|
||||
#################################################################################################
|
||||
# Docs: https://grafana.com/docs/agent/latest/static/configuration/traces-config/
|
||||
# the entire dictionary value for this object is copied to the traces: block in the config file
|
||||
grafana_agent_traces_config:
|
||||
# Docs: https://grafana.com/docs/agent/latest/static/configuration/traces-config/#traces_instance_config
|
||||
configs: []
|
||||
|
||||
#################################################################################################
|
||||
# Configures integrations for the agent #
|
||||
#################################################################################################
|
||||
# Docs: https://grafana.com/docs/agent/latest/static/configuration/integrations/
|
||||
# the entire dictionary value for this object is copied to the integrations: block in the config file
|
||||
grafana_agent_integrations_config:
|
||||
# Automatically collect metrics from enabled integrations. If disabled,
|
||||
# integrations will be run but not scraped and thus not remote_written. Metrics
|
||||
# for integrations will be exposed at /integrations/<integration_key>/metrics
|
||||
# and can be scraped by an external process.
|
||||
scrape_integrations: true
|
||||
# Controls the Agent integration
|
||||
agent:
|
||||
# Enables the Agent integration, allowing the Agent to automatically
|
||||
# collect and send metrics about itself.
|
||||
enabled: true
|
||||
# Allows for relabeling labels on the target.
|
||||
relabel_configs: []
|
||||
# Relabel metrics coming from the integration, allowing to drop series
|
||||
# from the integration that you don't care about.
|
||||
metric_relabel_configs: []
|
||||
|
||||
# Controls the node_exporter integration
|
||||
# Docs: https://grafana.com/docs/agent/latest/static/configuration/integrations/node-exporter-config/
|
||||
node_exporter:
|
||||
enabled: true
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
- name: Restart Grafana Agent
|
||||
become: true
|
||||
ansible.builtin.systemd:
|
||||
name: grafana-agent
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
listen: "restart grafana-agent"
|
||||
|
||||
- name: Check Grafana Agent is started properly
|
||||
ansible.builtin.include_tasks: ga-started.yaml
|
||||
listen: "restart grafana-agent"
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
dependencies: []
|
||||
|
||||
galaxy_info:
|
||||
role_name: grafana_agent
|
||||
author: Ishan Jain
|
||||
description: Ansible Role to deploy Grafana Agent on Linux hosts.
|
||||
license: "GPL-3.0-or-later"
|
||||
min_ansible_version: "2.11"
|
||||
platforms:
|
||||
- name: Fedora
|
||||
versions:
|
||||
- "all"
|
||||
- name: Debian
|
||||
versions:
|
||||
- "all"
|
||||
- name: Ubuntu
|
||||
versions:
|
||||
- "all"
|
||||
- name: EL
|
||||
versions:
|
||||
- "all"
|
||||
galaxy_tags:
|
||||
- grafana
|
||||
- observability
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
# these tasks are ran in both install and configure, as directories could have changed
|
||||
- name: Configure directories
|
||||
ansible.builtin.import_tasks: install/directories.yaml
|
||||
|
||||
- name: Create a symbolic link
|
||||
ansible.builtin.file:
|
||||
src: "{{ grafana_agent_install_dir }}/{{ grafana_agent_binary }}"
|
||||
dest: "/usr/local/bin/{{ grafana_agent_binary }}"
|
||||
owner: root
|
||||
group: root
|
||||
state: link
|
||||
|
||||
- name: Overwrite/Create Grafana Agent service
|
||||
ansible.builtin.template:
|
||||
src: grafana-agent.service.j2
|
||||
dest: "{{ _grafana_agent_systemd_dir }}/{{ _grafana_agent_systemd_unit }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
notify: "restart grafana-agent"
|
||||
|
||||
- name: Create the Service Environment file
|
||||
ansible.builtin.template:
|
||||
src: EnvironmentFile.j2
|
||||
dest: "{{ grafana_agent_config_dir }}/{{ grafana_agent_env_file }}"
|
||||
owner: root
|
||||
group: "{{ grafana_agent_user_group }}"
|
||||
mode: 0640
|
||||
notify: "restart grafana-agent"
|
||||
|
||||
- name: Create Grafana Agent config
|
||||
ansible.builtin.template:
|
||||
src: config.yaml.j2
|
||||
dest: "{{ grafana_agent_config_dir }}/{{ grafana_agent_config_filename }}"
|
||||
force: true
|
||||
owner: root
|
||||
group: "{{ grafana_agent_user_group }}"
|
||||
mode: 0640
|
||||
notify: "restart grafana-agent"
|
||||
when: grafana_agent_provisioned_config_file | length == 0
|
||||
|
||||
- name: Create Grafana Agent River Config if flow mode for Grafana Agent
|
||||
ansible.builtin.shell: "AGENT_MODE=flow {{ grafana_agent_install_dir }}/grafana-agent convert -f static {{ grafana_agent_config_dir }}/{{ grafana_agent_config_filename }} -o {{ grafana_agent_config_dir }}/{{ grafana_agent_config_filename }}"
|
||||
notify: "restart grafana-agent"
|
||||
when: grafana_agent_provisioned_config_file | length == 0
|
||||
|
||||
- name: Copy Grafana Agent config
|
||||
ansible.builtin.copy:
|
||||
src: "{{ grafana_agent_provisioned_config_file }}"
|
||||
dest: "{{ grafana_agent_config_dir }}/{{ grafana_agent_config_filename }}"
|
||||
owner: root
|
||||
group: "{{ grafana_agent_user_group }}"
|
||||
mode: 0640
|
||||
notify: "restart grafana-agent"
|
||||
when: grafana_agent_provisioned_config_file | length > 0
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
- name: Health check Grafana Agent
|
||||
ansible.builtin.uri:
|
||||
url: "{{ _grafana_agent_healthcheck_endpoint }}"
|
||||
follow_redirects: none
|
||||
method: GET
|
||||
register: _result
|
||||
failed_when: false
|
||||
until: _result.status == 200
|
||||
retries: 3
|
||||
delay: 5
|
||||
changed_when: false
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Check system logs if Grafana Agent is not started
|
||||
when: not ansible_check_mode and _result.status != 200
|
||||
block:
|
||||
- name: Run journalctl
|
||||
ansible.builtin.shell:
|
||||
cmd: "journalctl -u grafana-agent -b -n20 --no-pager"
|
||||
register: journal_ret
|
||||
changed_when: false
|
||||
- name: Output Grafana agent logs
|
||||
ansible.builtin.debug:
|
||||
var: journal_ret.stdout_lines
|
||||
- name: Rise alerts
|
||||
ansible.builtin.assert:
|
||||
that: false
|
||||
fail_msg: "Service grafana-agent hasn't started."
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
# user and group creation
|
||||
- name: Configure user groups
|
||||
ansible.builtin.import_tasks: install/user-group.yaml
|
||||
|
||||
# directory creation
|
||||
- name: Configure directories
|
||||
ansible.builtin.import_tasks: install/directories.yaml
|
||||
|
||||
# download and install agent
|
||||
- name: Download and install Grafana Agent
|
||||
ansible.builtin.import_tasks: install/download-install.yaml
|
||||
when: (grafana_agent_local_binary_file is not defined) or (grafana_agent_local_binary_file | length == 0)
|
||||
|
||||
# local install of agent
|
||||
- name: Local install of Grafana Agent
|
||||
ansible.builtin.import_tasks:
|
||||
file: install/local-install.yaml
|
||||
when: __grafana_agent_local_install
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
- name: Create install directories
|
||||
block:
|
||||
- name: Create Grafana Agent install directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ grafana_agent_install_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: "{{ grafana_agent_user_group }}"
|
||||
mode: 0770
|
||||
|
||||
- name: Create Grafana Agent conf directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ grafana_agent_config_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: "{{ grafana_agent_user_group }}"
|
||||
mode: 0770
|
||||
|
||||
- name: Create Grafana Agent data directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ grafana_agent_data_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: "{{ grafana_agent_user_group }}"
|
||||
mode: 0775
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
- name: Download Grafana Agent binary to controller (localhost)
|
||||
block:
|
||||
- name: Create Grafana Agent temp directory
|
||||
become: false
|
||||
ansible.builtin.file:
|
||||
path: "{{ grafana_agent_local_tmp_dir }}"
|
||||
state: directory
|
||||
mode: 0751
|
||||
delegate_to: localhost
|
||||
check_mode: false
|
||||
run_once: true
|
||||
|
||||
- name: Download Grafana Agent archive to local folder
|
||||
become: false
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ _grafana_agent_download_url }}"
|
||||
dest: "{{ grafana_agent_local_tmp_dir }}/grafana-agent_{{ _grafana_agent_cpu_arch }}_{{ grafana_agent_version }}.zip"
|
||||
mode: 0664
|
||||
register: _download_archive
|
||||
until: _download_archive is succeeded
|
||||
retries: 5
|
||||
delay: 2
|
||||
delegate_to: localhost
|
||||
check_mode: false
|
||||
run_once: true
|
||||
|
||||
- name: Extract grafana-agent.zip
|
||||
become: false
|
||||
ansible.builtin.unarchive:
|
||||
src: "{{ grafana_agent_local_tmp_dir }}/grafana-agent_{{ _grafana_agent_cpu_arch }}_{{ grafana_agent_version }}.zip"
|
||||
dest: "{{ grafana_agent_local_tmp_dir }}"
|
||||
remote_src: false
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
|
||||
- name: Set local path
|
||||
ansible.builtin.set_fact:
|
||||
__grafana_agent_local_binary_file: "{{ grafana_agent_local_tmp_dir }}/{{ grafana_agent_binary }}"
|
||||
|
||||
- name: Propagate downloaded binary
|
||||
ansible.builtin.copy:
|
||||
src: "{{ grafana_agent_local_tmp_dir }}/{{ _grafana_agent_download_binary_file }}"
|
||||
dest: "{{ grafana_agent_install_dir }}/{{ grafana_agent_binary }}"
|
||||
mode: 0755
|
||||
owner: root
|
||||
group: root
|
||||
when: not ansible_check_mode
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
- name: Install from local
|
||||
block:
|
||||
- name: "Propagate local binary {{ grafana_agent_local_binary_file }}"
|
||||
ansible.builtin.copy:
|
||||
src: "{{ grafana_agent_local_binary_file }}"
|
||||
dest: "{{ grafana_agent_install_dir }}/{{ grafana_agent_binary }}"
|
||||
mode: 0755
|
||||
owner: root
|
||||
group: root
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
- name: Grafana Agent group creation
|
||||
block:
|
||||
- name: "Check if the group exists ({{ grafana_agent_user_group }})"
|
||||
ansible.builtin.getent:
|
||||
database: group
|
||||
key: "{{ grafana_agent_user_group }}"
|
||||
fail_key: false
|
||||
|
||||
- name: Set whether not the user group exists
|
||||
ansible.builtin.set_fact:
|
||||
__grafana_agent_user_group_exists: "{{ ansible_facts.getent_group[grafana_agent_user_group] is not none }}"
|
||||
|
||||
- name: Add user group "{{ grafana_agent_user_group }}"
|
||||
ansible.builtin.group:
|
||||
name: "{{ grafana_agent_user_group }}"
|
||||
system: true
|
||||
state: present
|
||||
when: not __grafana_agent_user_group_exists and grafana_agent_user_group != 'root'
|
||||
|
||||
- name: Grafana Agent user group exists
|
||||
ansible.builtin.debug:
|
||||
msg: |-
|
||||
The user group \"{{ grafana_agent_user_group }}\" already exists and will not be modified,
|
||||
if modifying permissions please perform a separate task
|
||||
when: __grafana_agent_user_group_exists
|
||||
|
||||
- name: Grafana Agent user creation
|
||||
block:
|
||||
- name: Add user "{{ grafana_agent_user }}"
|
||||
ansible.builtin.user:
|
||||
name: "{{ grafana_agent_user }}"
|
||||
comment: "Grafana Agent account"
|
||||
groups: "{{ [ grafana_agent_user_group ] + grafana_agent_user_groups }}"
|
||||
system: true
|
||||
shell: "{{ grafana_agent_user_shell }}"
|
||||
createhome: "{{ grafana_agent_user_createhome }}"
|
||||
when: grafana_agent_user != 'root'
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
- name: Preflight tasks
|
||||
ansible.builtin.include_tasks:
|
||||
file: preflight.yaml
|
||||
apply:
|
||||
become: true
|
||||
tags:
|
||||
- grafana_agent_install
|
||||
- grafana_agent_configure
|
||||
- grafana_agent_run
|
||||
tags:
|
||||
- grafana_agent_install
|
||||
- grafana_agent_configure
|
||||
- grafana_agent_run
|
||||
|
||||
- name: Install tasks
|
||||
ansible.builtin.include_tasks:
|
||||
file: install.yaml
|
||||
apply:
|
||||
become: true
|
||||
tags:
|
||||
- grafana_agent_install
|
||||
tags:
|
||||
- grafana_agent_install
|
||||
|
||||
- name: Configuration tasks
|
||||
ansible.builtin.include_tasks:
|
||||
file: configure.yaml
|
||||
apply:
|
||||
become: true
|
||||
tags:
|
||||
- grafana_agent_configure
|
||||
tags:
|
||||
- grafana_agent_configure
|
||||
|
||||
- name: Flush handlers
|
||||
ansible.builtin.meta: flush_handlers
|
||||
|
||||
- name: Ensure Grafana Agent is started and enabled on boot
|
||||
become: true
|
||||
ansible.builtin.systemd:
|
||||
name: grafana-agent
|
||||
enabled: true
|
||||
state: started
|
||||
tags:
|
||||
- grafana_agent_install
|
||||
- grafana_agent_configure
|
||||
- grafana_agent_run
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
- name: Preflight variable checks
|
||||
ansible.builtin.import_tasks: preflight/vars.yaml
|
||||
|
||||
- name: Systemd variable checks
|
||||
ansible.builtin.import_tasks: preflight/systemd.yaml
|
||||
|
||||
- name: Install variable checks
|
||||
ansible.builtin.import_tasks: preflight/install.yaml
|
||||
|
||||
- name: Download variable checks
|
||||
ansible.builtin.import_tasks: preflight/download.yaml
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
- name: Get Grafana Agent version from Github
|
||||
when: grafana_agent_version == 'latest' and not __grafana_agent_local_install
|
||||
block:
|
||||
- name: Get the latest published Grafana Agent # noqa command-instead-of-module
|
||||
ansible.builtin.shell: |
|
||||
curl -s https://api.github.com/repos/{{ _grafana_agent_github_org }}/{{ _grafana_agent_github_repo }}/releases/latest \
|
||||
| grep -m 1 tag_name \
|
||||
| cut -d '"' -f 4 | cut -c 2-
|
||||
changed_when: false
|
||||
run_once: true
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
register: _grafana_agent_version_request
|
||||
|
||||
- name: Fail if cannot get Grafana Agent Version
|
||||
ansible.builtin.fail:
|
||||
msg: Issue getting the Grafana Agent Version
|
||||
when: _grafana_agent_version_request == ""
|
||||
|
||||
- name: Set the Grafana Agent version
|
||||
ansible.builtin.set_fact:
|
||||
grafana_agent_version: "{{ _grafana_agent_version_request.stdout }}"
|
||||
|
||||
- name: Grafana Agent version to download
|
||||
ansible.builtin.debug:
|
||||
var: grafana_agent_version
|
||||
|
||||
- name: Set the Grafana Agent download URL
|
||||
ansible.builtin.set_fact:
|
||||
_grafana_agent_download_url: |-
|
||||
{{ grafana_agent_base_download_url }}/v{{ grafana_agent_version }}/{{ _grafana_agent_download_archive_file }}
|
||||
|
||||
- name: Grafana Agent download URL
|
||||
ansible.builtin.debug:
|
||||
var: _grafana_agent_download_url
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
---
|
||||
- name: Default to non-local install
|
||||
ansible.builtin.set_fact:
|
||||
__grafana_agent_local_install: false
|
||||
|
||||
- name: Fail when grafana_agent_local_binary_file is defined but the file doesn't exist
|
||||
when: grafana_agent_local_binary_file is defined and grafana_agent_local_binary_file | length > 0
|
||||
block:
|
||||
- name: Check if grafana_agent_local_binary_file exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ grafana_agent_local_binary_file }}"
|
||||
register: __grafana_agent_local_binary_check
|
||||
become: false
|
||||
delegate_to: localhost
|
||||
check_mode: false
|
||||
|
||||
- name: Fail when the grafana_agent_local_binary_file does not exist
|
||||
ansible.builtin.fail:
|
||||
msg: "The grafana_agent_local_binary_file ({{ grafana_agent_local_binary_file }}) was specified but does not exist"
|
||||
when: not __grafana_agent_local_binary_check.stat.exists
|
||||
|
||||
- name: Change to local install
|
||||
ansible.builtin.set_fact:
|
||||
__grafana_agent_local_install: true
|
||||
|
||||
- name: Fail when grafana_agent_provisioned_config_file is defined but the file doesn't exist
|
||||
when: grafana_agent_provisioned_config_file is defined and grafana_agent_provisioned_config_file | length > 0
|
||||
block:
|
||||
- name: Check if grafana_agent_provisioned_config_file exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ grafana_agent_provisioned_config_file }}"
|
||||
register: __grafana_agent_provisioned_config_file_check
|
||||
become: false
|
||||
delegate_to: localhost
|
||||
check_mode: false
|
||||
|
||||
- name: Fail when the grafana_agent_provisioned_config_file does not exist
|
||||
ansible.builtin.fail:
|
||||
msg: "The grafana_agent_provisioned_config_file ({{ grafana_agent_provisioned_config_file }}) was specified but does not exist"
|
||||
when: not __grafana_agent_provisioned_config_file_check.stat.exists
|
||||
|
||||
- name: Check if grafana_agent is already installed on the host
|
||||
ansible.builtin.stat:
|
||||
path: "{{ grafana_agent_install_dir }}/{{ grafana_agent_binary }}"
|
||||
register: __grafana_agent_is_installed
|
||||
check_mode: false
|
||||
|
||||
- name: Is Grafana Agent already installed on the host
|
||||
ansible.builtin.debug:
|
||||
var: __grafana_agent_is_installed.stat.exists
|
||||
|
||||
- name: Install checks
|
||||
when: __grafana_agent_is_installed.stat.exists and not __grafana_agent_local_install
|
||||
block:
|
||||
- name: Gather currently installed grafana-agent version from the host
|
||||
ansible.builtin.shell:
|
||||
cmd: |
|
||||
{{ grafana_agent_install_dir }}/{{ grafana_agent_binary }} --version | \
|
||||
head -n 1 | \
|
||||
awk '{ print $3; }' | \
|
||||
cut -d 'v' -f 2
|
||||
changed_when: false
|
||||
register: __grafana_agent_current_version_output
|
||||
check_mode: false
|
||||
|
||||
- name: Set Grafana Agent installed version for the host
|
||||
ansible.builtin.set_fact:
|
||||
__grafana_agent_installed_version: "{{ __grafana_agent_current_version_output.stdout }}"
|
||||
|
||||
- name: Grafana Agent installed version on host
|
||||
ansible.builtin.debug:
|
||||
var: __grafana_agent_installed_version
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
- name: Assert usage of systemd as an init system
|
||||
ansible.builtin.assert:
|
||||
that: ansible_facts['service_mgr'] == 'systemd'
|
||||
msg: This role only works with systemd
|
||||
|
||||
- name: Get systemd version # noqa command-instead-of-module
|
||||
ansible.builtin.command: systemctl --version
|
||||
changed_when: false
|
||||
check_mode: false
|
||||
register: __systemd_version
|
||||
|
||||
- name: Set systemd version fact
|
||||
ansible.builtin.set_fact:
|
||||
grafana_agent_systemd_version: "{{ __systemd_version.stdout_lines[0] | regex_replace('^systemd\\s(\\d+).*$', '\\1') }}"
|
||||
|
||||
- name: Fail when _grafana_agent_systemd_dir the directory doesn't exist
|
||||
block:
|
||||
- name: Check if _grafana_agent_systemd_dir exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ _grafana_agent_systemd_dir }}"
|
||||
register: ___grafana_agent_systemd_dir_check
|
||||
check_mode: false
|
||||
|
||||
- name: Fail when the _grafana_agent_systemd_dir directory does not exist
|
||||
ansible.builtin.fail:
|
||||
msg: "The _grafana_agent_systemd_dir ({{ _grafana_agent_systemd_dir }}) does not exist"
|
||||
when: not ___grafana_agent_systemd_dir_check.stat.exists
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
---
|
||||
# Performs initial variable validation
|
||||
- name: Fail when variables are not defined
|
||||
ansible.builtin.fail:
|
||||
msg: "The {{ item }} property must be set"
|
||||
when: ( vars[item] is not defined )
|
||||
with_items:
|
||||
- grafana_agent_version
|
||||
- grafana_agent_install_dir
|
||||
- grafana_agent_binary
|
||||
- grafana_agent_config_dir
|
||||
- grafana_agent_config_filename
|
||||
- grafana_agent_env_file
|
||||
- grafana_agent_local_tmp_dir
|
||||
- grafana_agent_wal_dir
|
||||
- grafana_agent_positions_dir
|
||||
- grafana_agent_mode
|
||||
- _grafana_agent_systemd_dir
|
||||
- _grafana_agent_systemd_unit
|
||||
- grafana_agent_user
|
||||
- grafana_agent_user_group
|
||||
- grafana_agent_user_shell
|
||||
- grafana_agent_user_createhome
|
||||
- grafana_agent_local_binary_file
|
||||
- grafana_agent_flags_extra
|
||||
- grafana_agent_env_vars
|
||||
- grafana_agent_env_file_vars
|
||||
- grafana_agent_provisioned_config_file
|
||||
- grafana_agent_metrics_config
|
||||
- grafana_agent_logs_config
|
||||
- grafana_agent_traces_config
|
||||
- grafana_agent_integrations_config
|
||||
|
||||
- name: Fail when variables do not have a length
|
||||
ansible.builtin.fail:
|
||||
msg: "The {{ item }} property must be valued"
|
||||
when: ( vars[item] | string | length == 0 )
|
||||
with_items:
|
||||
- grafana_agent_version
|
||||
- grafana_agent_install_dir
|
||||
- grafana_agent_binary
|
||||
- grafana_agent_config_dir
|
||||
- grafana_agent_config_filename
|
||||
- grafana_agent_env_file
|
||||
- grafana_agent_local_tmp_dir
|
||||
- grafana_agent_wal_dir
|
||||
- grafana_agent_positions_dir
|
||||
- grafana_agent_mode
|
||||
- _grafana_agent_systemd_dir
|
||||
- _grafana_agent_systemd_unit
|
||||
- grafana_agent_user
|
||||
- grafana_agent_user_group
|
||||
- grafana_agent_user_shell
|
||||
- grafana_agent_user_createhome
|
||||
|
||||
- name: Fail when variables are not a number
|
||||
ansible.builtin.fail:
|
||||
msg: "The {{ item }} property must be number"
|
||||
when: ( vars[item] is defined and vars[item] is not number)
|
||||
with_items: []
|
||||
|
||||
- name: Fail when flags are not a boolean
|
||||
ansible.builtin.fail:
|
||||
msg: "The {{ item }} property must be a boolean true or false"
|
||||
when: ( vars[item] | bool | string | lower ) not in ['true', 'false']
|
||||
with_items:
|
||||
- grafana_agent_user_createhome
|
||||
|
||||
- name: Fail when the agent mode is not "flow" or "static"
|
||||
ansible.builtin.fail:
|
||||
msg: "The grafana_agent_mode property must be a boolean 'flow' or 'static'"
|
||||
when: grafana_agent_mode not in ['flow', 'static']
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{{ ansible_managed | comment }}
|
||||
# Grafana Agent Environment File
|
||||
AGENT_MODE={{ grafana_agent_mode }}
|
||||
|
||||
GOMAXPROCS={{ ansible_facts['processor_vcpus']|default(ansible_facts['processor_count']) }}
|
||||
|
||||
{% for key, value in grafana_agent_env_file_vars.items() %}
|
||||
{{key}}={{value}}
|
||||
{% endfor %}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
{{ ansible_managed | comment }}
|
||||
|
||||
#################################################################################################
|
||||
# Configures the server of the Agent used to enable self-scraping #
|
||||
#################################################################################################
|
||||
# Docs: https://grafana.com/docs/agent/latest/configuration/server-config/
|
||||
server:
|
||||
{{ grafana_agent_server_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2) }}
|
||||
|
||||
#################################################################################################
|
||||
# Configures metric collection #
|
||||
#################################################################################################
|
||||
# Docs: https://grafana.com/docs/agent/latest/configuration/metrics-config/
|
||||
metrics:
|
||||
{{ grafana_agent_metrics_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2) }}
|
||||
|
||||
#################################################################################################
|
||||
# Configures logs collection #
|
||||
#################################################################################################
|
||||
# Docs: https://grafana.com/docs/agent/latest/configuration/logs-config/
|
||||
logs:
|
||||
{{ grafana_agent_logs_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2) }}
|
||||
|
||||
{% if grafana_agent_mode == 'static' %}
|
||||
#################################################################################################
|
||||
# Configures traces collection #
|
||||
#################################################################################################
|
||||
# Docs: https://grafana.com/docs/agent/latest/configuration/traces-config/
|
||||
traces:
|
||||
{{ grafana_agent_traces_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2) }}
|
||||
{% endif %}
|
||||
|
||||
#################################################################################################
|
||||
# Configures integrations for the agent #
|
||||
#################################################################################################
|
||||
# Docs: https://grafana.com/docs/agent/latest/configuration/integrations/
|
||||
integrations:
|
||||
{{ grafana_agent_integrations_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2) }}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
[Unit]
|
||||
Description=Grafana Agent
|
||||
Documentation=https://grafana.com/docs/agent/latest/
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ grafana_agent_user }}
|
||||
Group={{ grafana_agent_user_group }}
|
||||
WorkingDirectory={{ grafana_agent_data_dir }}
|
||||
{% for key, value in grafana_agent_env_vars.items() %}
|
||||
Environment={{key}}={{value}}
|
||||
{% endfor %}
|
||||
EnvironmentFile={{ grafana_agent_config_dir }}/{{ grafana_agent_env_file}}
|
||||
{% for key, value in grafana_agent_service_extra.items() %}
|
||||
{{ key }}={{ value }}
|
||||
{% endfor %}
|
||||
|
||||
{% if grafana_agent_mode == 'flow' %}
|
||||
ExecStart={{ grafana_agent_install_dir }}/{{ grafana_agent_binary }} run \
|
||||
{% for flag, flag_value in grafana_agent_flags_extra.items() %}
|
||||
{% if not flag_value %}
|
||||
--{{ flag }} \
|
||||
{% elif flag_value is string %}
|
||||
--{{ flag }}={{ flag_value }} \
|
||||
{% elif flag_value is sequence %}
|
||||
{% for flag_value_item in flag_value %}
|
||||
--{{ flag }}={{ flag_value_item }} \
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ grafana_agent_config_dir }}/{{ grafana_agent_config_filename }}
|
||||
{% else %}
|
||||
ExecStart={{ grafana_agent_install_dir }}/{{ grafana_agent_binary }} \
|
||||
{% for flag, flag_value in grafana_agent_flags_extra.items() %}
|
||||
{% if not flag_value %}
|
||||
--{{ flag }} \
|
||||
{% elif flag_value is string %}
|
||||
--{{ flag }}={{ flag_value }} \
|
||||
{% elif flag_value is sequence %}
|
||||
{% for flag_value_item in flag_value %}
|
||||
--{{ flag }}={{ flag_value_item }} \
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
--config.file={{ grafana_agent_config_dir }}/{{ grafana_agent_config_filename }}
|
||||
{% endif %}
|
||||
|
||||
SyslogIdentifier=grafana-agent
|
||||
Restart=always
|
||||
|
||||
{% if grafana_agent_systemd_version | int >= 232 %}
|
||||
ProtectSystem=strict
|
||||
ProtectControlGroups=true
|
||||
ProtectKernelModules=true
|
||||
ProtectKernelTunables=yes
|
||||
{% else %}
|
||||
ProtectSystem=full
|
||||
{% endif %}
|
||||
ReadWritePaths=/tmp {{ grafana_agent_data_dir }} {{ grafana_agent_positions_dir }} {{ grafana_agent_wal_dir }}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
_grafana_agent_github_org: grafana
|
||||
_grafana_agent_github_repo: agent
|
||||
|
||||
# set the go cpu arch
|
||||
_download_cpu_arch_map:
|
||||
i386: '386'
|
||||
x86_64: amd64
|
||||
aarch64: arm64
|
||||
armv7l: armv7
|
||||
armv6l: armv6
|
||||
|
||||
_grafana_agent_cpu_arch: "{{ _download_cpu_arch_map[ansible_facts['architecture']] | default(ansible_facts['architecture']) }}"
|
||||
|
||||
# set the go os family
|
||||
_grafana_agent_os_family: "{{ ansible_facts['system'] | lower }}"
|
||||
|
||||
# set the name of the archive file to download
|
||||
_grafana_agent_download_archive_file: "grafana-agent-{{ _grafana_agent_os_family }}-{{ _grafana_agent_cpu_arch }}.zip"
|
||||
|
||||
# set the name of the binary file
|
||||
_grafana_agent_download_binary_file: "grafana-agent-{{ _grafana_agent_os_family }}-{{ _grafana_agent_cpu_arch }}"
|
||||
|
||||
# systemd info
|
||||
_grafana_agent_systemd_dir: /lib/systemd/system/
|
||||
_grafana_agent_systemd_unit: grafana-agent.service
|
||||
|
||||
# Server http address, used in self health check after start
|
||||
_grafana_agent_healthcheck_endpoint: "http://{{ grafana_agent_flags_extra['server.http.address'] if grafana_agent_flags_extra['server.http.address'] is defined else '127.0.0.1:12345' }}/-/ready"
|
||||
247
ansible_collections/grafana/grafana/roles/loki/README.md
Normal file
247
ansible_collections/grafana/grafana/roles/loki/README.md
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
# Ansible role - Loki
|
||||
|
||||
[](LICENSE)
|
||||
|
||||
The Ansible Loki Role allows you to effortlessly deploy and manage [Loki](https://grafana.com/oss/loki/), the log aggregation system. This role is tailored for operating systems such as **RedHat**, **Rocky Linux**, **AlmaLinux**, **Ubuntu**, and **Debian**.
|
||||
|
||||
**🔑 Key Features**
|
||||
- **📦 Out-of-the-box Deployment**: Get Loki up and running quickly with default configurations.
|
||||
- **🧹 Effortless Uninstall**: Easily remove Loki from your system setting the "loki_uninstall" variable.
|
||||
- **🔔 Example Alerting Rules**: Benefit from the included sample Ruler configuration. Utilize the provided example alerting rules as a reference guide for structuring your own rules effectively.
|
||||
|
||||
## Table of Content
|
||||
|
||||
- [Requirements](#requirements)
|
||||
- [Role Variables](#role-variables)
|
||||
- - [Default Variables - `defaults/main.yml`](#default-variables---defaultsmainyml)
|
||||
- - [Alerting Rules Variables](#alerting-rules-variables)
|
||||
- - [Additional Config Variables for `/etc/loki/config.yml`](#additional-config-variables-for-etclokiconfigyml)
|
||||
- [Playbook](#playbook)
|
||||
|
||||
## Requirements
|
||||
|
||||
- Ansible 2.10+
|
||||
|
||||
## Role Variables
|
||||
|
||||
- 📚 Official Loki configuration [documentation](https://grafana.com/docs/loki/latest/configuration/)
|
||||
- 🏗️ Upgrading Loki [documentation](https://grafana.com/docs/loki/latest/upgrading/)
|
||||
|
||||
### **Default Variables - `defaults/main.yml`**
|
||||
|
||||
```yaml
|
||||
loki_version: "latest"
|
||||
```
|
||||
|
||||
The version of Loki to download and deploy. Supported standard version "3.0.0" format or "latest".
|
||||
|
||||
```yaml
|
||||
loki_uninstall: "false"
|
||||
```
|
||||
|
||||
If set to `true` will perfom uninstall instead of deployment.
|
||||
|
||||
```yaml
|
||||
loki_http_listen_port: 3100
|
||||
```
|
||||
The TCP port on which Loki listens. By default, it listens on port `3100`.
|
||||
|
||||
```yaml
|
||||
loki_http_listen_address: "0.0.0.0"
|
||||
```
|
||||
The address on which Loki listens for HTTP requests. By default, it listens on all interfaces.
|
||||
|
||||
```yaml
|
||||
loki_expose_port: false
|
||||
```
|
||||
By default, this is set to `false`. It supports only simple `firewalld` configurations. If set to `true`, a firewalld rule is added to expose the TCP `loki_http_listen_port`. If set to `false`, the system ensures that the rule is not present. If the `firewalld.service` is not active, all firewalld tasks are skipped.
|
||||
|
||||
```yaml
|
||||
loki_download_url_rpm: "https://github.com/grafana/loki/releases/download/v{{ loki_version }}/loki-{{ loki_version }}.{{ __loki_arch }}.rpm"
|
||||
```
|
||||
The default download URL for the Loki rpm package from GitHub.
|
||||
|
||||
```yaml
|
||||
loki_download_url_deb: "https://github.com/grafana/loki/releases/download/v{{ loki_version }}/loki_{{ loki_version }}_{{ __loki_arch }}.deb"
|
||||
```
|
||||
The default download URL for the Loki deb package from GitHub.
|
||||
|
||||
```yaml
|
||||
loki_working_path: "/var/lib/loki"
|
||||
```
|
||||
⚠️ Avoid using `/tmp/loki` as the working path. This role removes the /tmp/loki directory and replaces it with the specified working path to ensure a permanent configuration.
|
||||
|
||||
```yaml
|
||||
loki_ruler_alert_path: "{{ loki_working_path }}/rules/fake"
|
||||
```
|
||||
The variable defines the location where the `ruler` configuration `alerts` are stored.
|
||||
⚠️ Please note that the role currently does not support multi-tenancy for alerting, so there is no need to modify this variable for different tenants.
|
||||
|
||||
```yaml
|
||||
loki_auth_enabled: false
|
||||
```
|
||||
Enables authentication through the X-Scope-OrgID header, which must be present if `true`. If `false`, the OrgID will always be set to `fake`.
|
||||
|
||||
```yaml
|
||||
loki_target: "all"
|
||||
```
|
||||
A comma-separated list of components to run. The default value 'all' runs Loki in single binary mode.
|
||||
Supported values: `all`, `compactor`, `distributor`, `ingester`, `querier`, `query-scheduler`, `ingester-querier`, `query-frontend`, `index-gateway`, `ruler`, `table-manager`, `read`, `write`.
|
||||
|
||||
```yaml
|
||||
loki_ballast_bytes: 0
|
||||
```
|
||||
The amount of virtual memory in bytes to reserve as ballast in order to optimize garbage collection.
|
||||
|
||||
```yaml
|
||||
loki_server:
|
||||
http_listen_address: "{{ loki_http_listen_address }}"
|
||||
http_listen_port: "{{ loki_http_listen_port }}"
|
||||
grpc_listen_port: 9096
|
||||
```
|
||||
Configures the `server` of the launched module(s). [All possible values for `server`](https://grafana.com/docs/loki/latest/configuration/#server)
|
||||
|
||||
```yaml
|
||||
loki_common:
|
||||
instance_addr: 127.0.0.1
|
||||
path_prefix: "{{ loki_working_path }}"
|
||||
storage:
|
||||
filesystem:
|
||||
chunks_directory: "{{ loki_working_path }}/chunks"
|
||||
rules_directory: "{{ loki_working_path }}/rules"
|
||||
replication_factor: 1
|
||||
ring:
|
||||
kvstore:
|
||||
store: inmemory
|
||||
```
|
||||
Common configuration to be shared between multiple modules. If a more specific configuration is given in other sections, the related configuration within this section will be ignored. [All possible values for `common`](https://grafana.com/docs/loki/latest/configuration/#common)
|
||||
|
||||
```yaml
|
||||
loki_query_range:
|
||||
results_cache:
|
||||
cache:
|
||||
embedded_cache:
|
||||
enabled: true
|
||||
max_size_mb: 100
|
||||
```
|
||||
The `query_range` block configures the query splitting and caching in the Loki query-frontend. [All possible values for `query_range`](https://grafana.com/docs/loki/latest/configuration/#query_range)
|
||||
|
||||
```yaml
|
||||
loki_schema_config:
|
||||
configs:
|
||||
- from: 2020-10-24
|
||||
store: tsdb
|
||||
object_store: filesystem
|
||||
schema: v13
|
||||
index:
|
||||
prefix: index_
|
||||
period: 24h
|
||||
```
|
||||
Configures the chunk index schema and where it is stored. [All possible values for `schema_config`](https://grafana.com/docs/loki/latest/configuration/#schema_config)
|
||||
|
||||
```yaml
|
||||
loki_ruler:
|
||||
storage:
|
||||
type: local
|
||||
local:
|
||||
directory: "{{ loki_working_path }}/rules"
|
||||
rule_path: "{{ loki_working_path }}/rules_tmp"
|
||||
ring:
|
||||
kvstore:
|
||||
store: inmemory
|
||||
enable_api: true
|
||||
enable_alertmanager_v2: true
|
||||
alertmanager_url: http://localhost:9093
|
||||
```
|
||||
The `ruler` block configures the Loki ruler. [All possible values for `ruler`](https://grafana.com/docs/loki/latest/configuration/#ruler)
|
||||
|
||||
```yaml
|
||||
loki_analytics:
|
||||
reporting_enabled: false
|
||||
```
|
||||
Enable anonymous usage reporting. Disabled by default.
|
||||
|
||||
|
||||
### **Alerting Rules Variables**
|
||||
(not set by default)
|
||||
|
||||
```yaml
|
||||
---
|
||||
loki_ruler_alerts:
|
||||
- name: Logs.Nextcloud
|
||||
rules:
|
||||
- alert: NextcloudLoginFailed
|
||||
expr: |
|
||||
count by (filename,env,job) (count_over_time({job=~"nextcloud"} | json | message=~"Login failed.*" [10m])) > 4
|
||||
for: 0m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "{% raw %}On {{ $labels.job }} in log {{ $labels.filename }} failed login detected.{% endraw %}"
|
||||
- name: Logs.sshd
|
||||
rules:
|
||||
- alert: SshLoginFailed
|
||||
expr: |
|
||||
count_over_time({job=~"secure"} |="sshd[" |~": Failed|: Invalid|: Connection closed by authenticating user" | __error__="" [15m]) > 15
|
||||
for: 0m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "{% raw %}SSH authentication failure (instance {{ $labels.instance }}).{% endraw %}"
|
||||
```
|
||||
Example alerting rule configuration. You can add multiple alerting rules to suit your requirements. Please note that the alerting rules are not templated by default
|
||||
|
||||
### **Additional Config Variables for `/etc/loki/config.yml`**
|
||||
(not set by default)
|
||||
|
||||
Below variables allow you to extend Loki configuration to fit your needs. Always refer to official [Loki configuration](https://grafana.com/docs/loki/latest/configuration/) to obtain possible configuration parameters.
|
||||
|
||||
| Variable Name | Description
|
||||
| ----------- | ----------- |
|
||||
| `loki_distributor` | Configures the `distributor`. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#distributor)
|
||||
| `loki_querier` | Configures the `querier`. Only appropriate when running all modules or just the querier. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#querier)
|
||||
| `loki_query_scheduler` | The `query_scheduler` block configures the Loki query scheduler. When configured it separates the tenant query queues from the query-frontend. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#query_scheduler)
|
||||
| `loki_frontend` | The `frontend` block configures the Loki query-frontend. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#frontend)
|
||||
| `loki_ingester_client` | The `ingester_client` block configures how the distributor will connect to ingesters. Only appropriate when running all components, the distributor, or the querier. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#ingester_client)
|
||||
| `loki_ingester` | The `ingester` block configures the ingester and how the ingester will register itself to a key value store. 📚 configuration [documentation](https://grafana.com/docs/loki/latest/configuration/#ingester)
|
||||
| `loki_index_gateway` | The `index_gateway` block configures the Loki index gateway server, responsible for serving index queries without the need to constantly interact with the object store. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#index_gateway)
|
||||
| `loki_storage_config` | The `storage_config` block configures one of many possible stores for both the index and chunks. Which configuration to be picked should be defined in schema_config block. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#storage_config)
|
||||
| `loki_chunk_store_config` | The `chunk_store_config` block configures how chunks will be cached and how long to wait before saving them to the backing store. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#chunk_store_config)
|
||||
| `loki_compactor` | The `compactor` block configures the compactor component, which compacts index shards for performance. 📚 [documentation](https://grafana.com/docs/loki/latest/configure/#compactor)
|
||||
| `loki_limits_config` | The `limits_config` block configures global and per-tenant limits in Loki. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#limits_config)
|
||||
| `loki_frontend_worker` | The `frontend_worker` configures the worker - running within the Loki querier - picking up and executing queries enqueued by the query-frontend. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#frontend_worker)
|
||||
| `loki_table_manager` | The `table_manager` block configures the table manager for retention. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#table_manager)
|
||||
| `loki_memberlist` | Configuration for memberlist client. Only applies if the selected kvstore is memberlist. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#memberlist)
|
||||
| `loki_runtime_config` | Configuration for `runtime config` module, responsible for reloading runtime configuration file. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#runtime_config)
|
||||
| `loki_operational_config` | These are values which allow you to control aspects of Loki's operation, most commonly used for controlling types of higher verbosity logging, the values here can be overridden in the configs section of the `runtime_config` file. 📚 [documentation](https://grafana.com/docs/loki/latest/configure/#operational_config)
|
||||
| `loki_tracing` | Configuration for tracing. 📚 [documentation](https://grafana.com/docs/loki/latest/configuration/#tracing)
|
||||
| `loki_bloom_build` | The `bloom_build` block configures the Loki bloom planner and builder servers, responsible for building bloom filters. 📚 [documentation](https://grafana.com/docs/loki/latest/configure/#bloom_build)
|
||||
| `loki_bloom_gateway` | The `bloom_gateway` block configures the Loki bloom gateway server, responsible for serving queries for filtering chunks based on filter expressions. 📚 [documentation](https://grafana.com/docs/loki/latest/configure/#bloom_gateway)
|
||||
|
||||
## Playbook
|
||||
|
||||
- playbook
|
||||
```yaml
|
||||
- name: Manage loki service
|
||||
hosts: all
|
||||
become: true
|
||||
roles:
|
||||
- role: grafana.grafana.loki
|
||||
```
|
||||
|
||||
- Playbook execution example
|
||||
```shell
|
||||
# Deployment
|
||||
ansible-playbook -i inventory/hosts playbook/function_loki_play.yml
|
||||
|
||||
# Uninstall
|
||||
ansible-playbook -i inventory/hosts playbook/function_loki_play.yml -e "loki_uninstall=true"
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
See [LICENSE](https://github.com/grafana/grafana-ansible-collection/blob/main/LICENSE)
|
||||
|
||||
## Author Information
|
||||
|
||||
- [VoidQuark](https://github.com/voidquark)
|
||||
110
ansible_collections/grafana/grafana/roles/loki/defaults/main.yml
Normal file
110
ansible_collections/grafana/grafana/roles/loki/defaults/main.yml
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
---
|
||||
# defaults file for loki
|
||||
loki_version: "latest"
|
||||
loki_uninstall: false
|
||||
loki_http_listen_port: 3100
|
||||
loki_http_listen_address: "0.0.0.0"
|
||||
loki_expose_port: false
|
||||
loki_download_url_rpm: "https://github.com/grafana/loki/releases/download/v{{ loki_version }}/loki-{{ loki_version }}.{{ __loki_arch }}.rpm"
|
||||
loki_download_url_deb: "https://github.com/grafana/loki/releases/download/v{{ loki_version }}/loki_{{ loki_version }}_{{ __loki_arch }}.deb"
|
||||
loki_working_path: "/var/lib/loki"
|
||||
loki_ruler_alert_path: "{{ loki_working_path }}/rules/fake"
|
||||
|
||||
# Default Variables for /etc/loki/config.yml
|
||||
loki_auth_enabled: false
|
||||
loki_target: "all"
|
||||
loki_ballast_bytes: 0
|
||||
|
||||
loki_server:
|
||||
http_listen_address: "{{ loki_http_listen_address }}"
|
||||
http_listen_port: "{{ loki_http_listen_port }}"
|
||||
grpc_listen_port: 9096
|
||||
|
||||
loki_common:
|
||||
instance_addr: 127.0.0.1
|
||||
path_prefix: "{{ loki_working_path }}"
|
||||
storage:
|
||||
filesystem:
|
||||
chunks_directory: "{{ loki_working_path }}/chunks"
|
||||
rules_directory: "{{ loki_working_path }}/rules"
|
||||
replication_factor: 1
|
||||
ring:
|
||||
kvstore:
|
||||
store: inmemory
|
||||
|
||||
loki_query_range:
|
||||
results_cache:
|
||||
cache:
|
||||
embedded_cache:
|
||||
enabled: true
|
||||
max_size_mb: 100
|
||||
|
||||
loki_schema_config:
|
||||
configs:
|
||||
- from: 2020-10-24
|
||||
store: tsdb
|
||||
object_store: filesystem
|
||||
schema: v13
|
||||
index:
|
||||
prefix: index_
|
||||
period: 24h
|
||||
|
||||
loki_ruler:
|
||||
storage:
|
||||
type: local
|
||||
local:
|
||||
directory: "{{ loki_working_path }}/rules"
|
||||
rule_path: "{{ loki_working_path }}/rules_tmp"
|
||||
ring:
|
||||
kvstore:
|
||||
store: inmemory
|
||||
enable_api: true
|
||||
enable_alertmanager_v2: true
|
||||
alertmanager_url: http://localhost:9093
|
||||
|
||||
loki_analytics:
|
||||
reporting_enabled: false
|
||||
|
||||
# Alerting Rules Variables
|
||||
# loki_ruler_alerts:
|
||||
# - name: Logs.Nextcloud
|
||||
# rules:
|
||||
# - alert: NextcloudLoginFailed
|
||||
# expr: |
|
||||
# count by (filename,env,job) (count_over_time({job=~"nextcloud"} | json | message=~"Login failed.*" [10m])) > 4
|
||||
# for: 0m
|
||||
# labels:
|
||||
# severity: critical
|
||||
# annotations:
|
||||
# summary: "{% raw %}On {{ $labels.job }} in log {{ $labels.filename }} failed login detected.{% endraw %}"
|
||||
# - name: Logs.sshd
|
||||
# rules:
|
||||
# - alert: SshLoginFailed
|
||||
# expr: |
|
||||
# count_over_time({job=~"secure"} |="sshd[" |~": Failed|: Invalid|: Connection closed by authenticating user" | __error__="" [15m]) > 15
|
||||
# for: 0m
|
||||
# labels:
|
||||
# severity: critical
|
||||
# annotations:
|
||||
# summary: "{% raw %}SSH authentication failure (instance {{ $labels.instance }}).{% endraw %}"
|
||||
|
||||
# Additional Config Variables for /etc/loki/config.yml
|
||||
# loki_distributor:
|
||||
# loki_querier:
|
||||
# loki_query_scheduler:
|
||||
# loki_frontend:
|
||||
# loki_ingester_client:
|
||||
# loki_ingester:
|
||||
# loki_index_gateway:
|
||||
# loki_storage_config:
|
||||
# loki_chunk_store_config:
|
||||
# loki_compactor:
|
||||
# loki_limits_config:
|
||||
# loki_frontend_worker:
|
||||
# loki_table_manager:
|
||||
# loki_memberlist:
|
||||
# loki_runtime_config:
|
||||
# loki_operational_config:
|
||||
# loki_tracing:
|
||||
# loki_bloom_build:
|
||||
# loki_bloom_gateway:
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
# handlers file for loki
|
||||
- name: Restart loki
|
||||
listen: "restart loki"
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: true
|
||||
name: loki.service
|
||||
state: restarted
|
||||
enabled: true
|
||||
when: not ansible_check_mode
|
||||
28
ansible_collections/grafana/grafana/roles/loki/meta/main.yml
Normal file
28
ansible_collections/grafana/grafana/roles/loki/meta/main.yml
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
galaxy_info:
|
||||
role_name: loki
|
||||
author: voidquark
|
||||
description: Manage Grafana Loki Application
|
||||
license: "GPL-3.0-or-later"
|
||||
min_ansible_version: "2.10"
|
||||
platforms:
|
||||
- name: EL
|
||||
versions:
|
||||
- "8"
|
||||
- "9"
|
||||
- name: Fedora
|
||||
versions:
|
||||
- all
|
||||
- name: Debian
|
||||
versions:
|
||||
- all
|
||||
- name: Ubuntu
|
||||
versions:
|
||||
- all
|
||||
galaxy_tags:
|
||||
- loki
|
||||
- grafana
|
||||
- logging
|
||||
- monitoring
|
||||
|
||||
dependencies: []
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
- name: Converge
|
||||
hosts: all
|
||||
roles:
|
||||
- role: grafana.grafana.loki
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
dependency:
|
||||
name: galaxy
|
||||
options:
|
||||
ignore-errors: true
|
||||
driver:
|
||||
name: docker
|
||||
platforms:
|
||||
- name: instance
|
||||
image: "geerlingguy/docker-${MOLECULE_DISTRO:-rockylinux8}-ansible:latest"
|
||||
command: ${MOLECULE_DOCKER_COMMAND:-""}
|
||||
volumes:
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||
cgroupns_mode: host
|
||||
privileged: true
|
||||
pre_build_image: true
|
||||
provisioner:
|
||||
name: ansible
|
||||
playbooks:
|
||||
converge: converge.yml
|
||||
150
ansible_collections/grafana/grafana/roles/loki/tasks/deploy.yml
Normal file
150
ansible_collections/grafana/grafana/roles/loki/tasks/deploy.yml
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
---
|
||||
# tasks file for loki deployment
|
||||
|
||||
- name: Obtain the latest version from the Loki GitHub repo
|
||||
when: loki_version == "latest"
|
||||
block:
|
||||
- name: Scrape Github API endpoint to obtain latest Loki version
|
||||
ansible.builtin.uri:
|
||||
url: "https://api.github.com/repos/grafana/loki/releases/latest"
|
||||
method: GET
|
||||
body_format: json
|
||||
become: false
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
check_mode: false
|
||||
register: __github_latest_version
|
||||
|
||||
- name: Latest available Loki version
|
||||
ansible.builtin.set_fact:
|
||||
loki_version: "{{ __github_latest_version.json.tag_name | regex_replace('^v?(\\d+\\.\\d+\\.\\d+)$', '\\1') }}"
|
||||
|
||||
- name: Verify current deployed version
|
||||
block:
|
||||
- name: Check if Loki binary is present
|
||||
ansible.builtin.stat:
|
||||
path: "/usr/bin/loki"
|
||||
register: __already_deployed
|
||||
|
||||
- name: Obtain current deployed Loki version
|
||||
ansible.builtin.command:
|
||||
cmd: "/usr/bin/loki --version"
|
||||
changed_when: false
|
||||
register: __current_deployed_version
|
||||
when: __already_deployed.stat.exists | bool
|
||||
|
||||
- name: Include RedHat/Rocky setup
|
||||
ansible.builtin.include_tasks:
|
||||
file: setup-RedHat.yml
|
||||
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']
|
||||
|
||||
- name: Include Debian/Ubuntu setup
|
||||
ansible.builtin.include_tasks:
|
||||
file: setup-Debian.yml
|
||||
when: ansible_facts['os_family'] == 'Debian'
|
||||
|
||||
- name: Check if Loki default dir is present
|
||||
ansible.builtin.stat:
|
||||
path: "/tmp/loki/boltdb-shipper-active"
|
||||
register: __default_structure
|
||||
|
||||
- name: Default structure cleanup
|
||||
when: __default_structure.stat.exists | bool
|
||||
block:
|
||||
- name: Ensure that Loki is stopped before default cleanup
|
||||
ansible.builtin.systemd:
|
||||
name: loki.service
|
||||
state: stopped
|
||||
|
||||
- name: Remove default configuration from "/tmp/loki" directory
|
||||
ansible.builtin.file:
|
||||
path: "/tmp/loki"
|
||||
state: absent
|
||||
|
||||
- name: Ensure that Loki working path exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ loki_working_path }}"
|
||||
state: directory
|
||||
owner: "loki"
|
||||
group: "root"
|
||||
mode: "0755"
|
||||
|
||||
- name: Template Loki config - /etc/loki/config.yml
|
||||
ansible.builtin.template:
|
||||
src: "config.yml.j2"
|
||||
dest: "/etc/loki/config.yml"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0644"
|
||||
validate: "/usr/bin/loki --verify-config -config.file %s"
|
||||
notify: restart loki
|
||||
|
||||
- name: Ensure that Loki rule path exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ loki_ruler_alert_path }}"
|
||||
state: directory
|
||||
owner: "loki"
|
||||
group: "root"
|
||||
mode: "0750"
|
||||
when:
|
||||
- loki_ruler_alert_path is defined
|
||||
- loki_ruler is defined
|
||||
|
||||
- name: Template Loki Rule File
|
||||
ansible.builtin.template:
|
||||
src: "rules.yml.j2"
|
||||
dest: "{{ loki_ruler_alert_path }}/rules.yml"
|
||||
owner: "loki"
|
||||
group: "root"
|
||||
mode: "0644"
|
||||
notify: restart loki
|
||||
when:
|
||||
- loki_ruler_alerts is defined
|
||||
- loki_ruler_alert_path is defined
|
||||
- loki_ruler is defined
|
||||
|
||||
- name: Get firewalld state
|
||||
ansible.builtin.systemd:
|
||||
name: "firewalld"
|
||||
register: __firewalld_service_state
|
||||
|
||||
- name: Enable firewalld rule to expose Loki tcp port {{ loki_http_listen_port }}
|
||||
ansible.posix.firewalld:
|
||||
immediate: true
|
||||
permanent: true
|
||||
port: "{{ loki_http_listen_port }}/tcp"
|
||||
state: enabled
|
||||
when:
|
||||
- __firewalld_service_state.status.ActiveState == "active"
|
||||
- loki_expose_port | bool
|
||||
|
||||
- name: Ensure that Loki firewalld rule is not present - tcp port {{ loki_http_listen_port }}
|
||||
ansible.posix.firewalld:
|
||||
immediate: true
|
||||
permanent: true
|
||||
port: "{{ loki_http_listen_port }}/tcp"
|
||||
state: disabled
|
||||
when:
|
||||
- __firewalld_service_state.status.ActiveState == "active"
|
||||
- not loki_expose_port | bool
|
||||
|
||||
- name: Flush handlers after deployment
|
||||
ansible.builtin.meta: flush_handlers
|
||||
|
||||
- name: Ensure that Loki is started
|
||||
ansible.builtin.systemd:
|
||||
name: loki.service
|
||||
state: started
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Verify that Loki URL is responding
|
||||
ansible.builtin.uri:
|
||||
url: "http://{{ loki_http_listen_address }}:{{ loki_http_listen_port }}/ready"
|
||||
method: GET
|
||||
register: loki_verify_url_status_code
|
||||
retries: 5
|
||||
delay: 8
|
||||
until: loki_verify_url_status_code.status == 200
|
||||
when:
|
||||
- loki_expose_port | bool
|
||||
- not ansible_check_mode
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
# tasks file for loki
|
||||
- name: Include OS specific variables
|
||||
ansible.builtin.include_vars:
|
||||
file: "{{ ansible_facts['os_family'] }}.yml"
|
||||
|
||||
- name: Deploy Loki service
|
||||
ansible.builtin.include_tasks:
|
||||
file: "deploy.yml"
|
||||
when: not loki_uninstall
|
||||
|
||||
- name: Uninstall Loki service
|
||||
ansible.builtin.include_tasks:
|
||||
file: "uninstall.yml"
|
||||
when: loki_uninstall
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
- name: APT - Install Loki
|
||||
ansible.builtin.apt:
|
||||
deb: "{{ loki_download_url_deb }}"
|
||||
state: present
|
||||
notify: restart loki
|
||||
when: __current_deployed_version.stdout is not defined or loki_version not in __current_deployed_version.stdout
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
- name: DNF - Install Loki from remote URL
|
||||
ansible.builtin.dnf:
|
||||
name: "{{ loki_download_url_rpm }}"
|
||||
state: present
|
||||
disable_gpg_check: true
|
||||
notify: restart loki
|
||||
when: __current_deployed_version.stdout is not defined or loki_version not in __current_deployed_version.stdout
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
# tasks file for loki uninstall
|
||||
|
||||
- name: Stop Loki service
|
||||
ansible.builtin.systemd: # noqa ignore-errors
|
||||
name: loki
|
||||
state: stopped
|
||||
ignore_errors: true
|
||||
|
||||
- name: Uninstall Loki rpm package
|
||||
ansible.builtin.dnf:
|
||||
name: "loki"
|
||||
state: absent
|
||||
autoremove: true
|
||||
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']
|
||||
|
||||
- name: Uninstall Loki deb package
|
||||
ansible.builtin.apt:
|
||||
name: "loki"
|
||||
state: absent
|
||||
purge: true
|
||||
when: ansible_facts['os_family'] == 'Debian'
|
||||
|
||||
- name: Ensure that Loki firewalld rule is not present - tcp port {{ loki_http_listen_port }}
|
||||
ansible.posix.firewalld: # noqa ignore-errors
|
||||
immediate: true
|
||||
permanent: true
|
||||
port: "{{ loki_http_listen_port }}/tcp"
|
||||
state: disabled
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove Loki directories"
|
||||
ansible.builtin.file:
|
||||
path: "{{ remove_me }}"
|
||||
state: absent
|
||||
loop:
|
||||
- "/etc/loki"
|
||||
- "{{ loki_working_path }}"
|
||||
loop_control:
|
||||
loop_var: remove_me
|
||||
|
||||
- name: Remove the Loki system user
|
||||
ansible.builtin.user:
|
||||
name: "loki"
|
||||
force: true
|
||||
state: absent
|
||||
|
||||
- name: Remove Loki system group
|
||||
ansible.builtin.group:
|
||||
name: "loki"
|
||||
state: absent
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
{% if loki_target is defined %}
|
||||
target: {{ loki_target }}
|
||||
{% endif %}
|
||||
{% if loki_auth_enabled is defined %}
|
||||
auth_enabled: {{ loki_auth_enabled }}
|
||||
{% endif %}
|
||||
{% if loki_ballast_bytes is defined %}
|
||||
ballast_bytes: {{ loki_ballast_bytes }}
|
||||
{% endif %}
|
||||
server:
|
||||
{{ loki_server | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% if loki_distributor is defined %}
|
||||
distributor:
|
||||
{{ loki_distributor | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_querier is defined %}
|
||||
querier:
|
||||
{{ loki_querier | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_query_scheduler is defined %}
|
||||
query_scheduler:
|
||||
{{ loki_query_scheduler | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_frontend is defined %}
|
||||
frontend:
|
||||
{{ loki_frontend | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_query_range is defined %}
|
||||
query_range:
|
||||
{{ loki_query_range | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_ruler is defined %}
|
||||
ruler:
|
||||
{{ loki_ruler | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_ingester_client is defined %}
|
||||
ingester_client:
|
||||
{{ loki_ingester_client | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_ingester is defined %}
|
||||
ingester:
|
||||
{{ loki_ingester | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_index_gateway is defined %}
|
||||
index_gateway:
|
||||
{{ loki_index_gateway | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_storage_config is defined %}
|
||||
storage_config:
|
||||
{{ loki_storage_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_chunk_store_config is defined %}
|
||||
chunk_store_config:
|
||||
{{ loki_chunk_store_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_schema_config is defined %}
|
||||
schema_config:
|
||||
{{ loki_schema_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_compactor is defined %}
|
||||
compactor:
|
||||
{{ loki_compactor | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_limits_config is defined %}
|
||||
limits_config:
|
||||
{{ loki_limits_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_frontend_worker is defined %}
|
||||
frontend_worker:
|
||||
{{ loki_frontend_worker | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_table_manager is defined %}
|
||||
table_manager:
|
||||
{{ loki_table_manager | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_memberlist is defined %}
|
||||
memberlist:
|
||||
{{ loki_memberlist | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_runtime_config is defined %}
|
||||
runtime_config:
|
||||
{{ loki_runtime_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_operational_config is defined %}
|
||||
operational_config:
|
||||
{{ loki_operational_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_tracing is defined %}
|
||||
tracing:
|
||||
{{ loki_tracing | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_analytics is defined %}
|
||||
analytics:
|
||||
{{ loki_analytics | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_common is defined %}
|
||||
common:
|
||||
{{ loki_common | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_bloom_build is defined %}
|
||||
bloom_build:
|
||||
{{ loki_bloom_build | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
{% if loki_bloom_gateway is defined %}
|
||||
bloom_gateway:
|
||||
{{ loki_bloom_gateway | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }}
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
groups:
|
||||
{{ loki_ruler_alerts | to_nice_yaml(indent=2,sort_keys=False) | indent(2,False) }}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
__loki_arch_map:
|
||||
x86_64: 'amd64'
|
||||
armv6l: 'arm'
|
||||
armv7l: 'arm'
|
||||
aarch64: 'arm64'
|
||||
|
||||
__loki_arch: "{{ __loki_arch_map[ansible_facts['architecture']] | default(ansible_facts['architecture']) }}"
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
__loki_arch: "{{ ansible_facts['architecture'] }}"
|
||||
109
ansible_collections/grafana/grafana/roles/mimir/README.md
Normal file
109
ansible_collections/grafana/grafana/roles/mimir/README.md
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
# Ansible role - Mimir
|
||||
|
||||
[](LICENSE)
|
||||
|
||||
This role installs and configures a [Mimir](https://grafana.com/docs/mimir/latest/)
|
||||
standalone application.
|
||||
|
||||
## Testing with Molecule
|
||||
|
||||
To be able to test this collection locally, we use Molecule. Molecule is an Ansible test tool that enable us to run our roles inside containers. In our case, we are using Podman as a container runtime. To be able to run the Molecule test, you need to have the following installed on your machine:
|
||||
|
||||
- Podman
|
||||
- Ansible
|
||||
- Python3
|
||||
|
||||
### First Time Setup
|
||||
|
||||
To install all the dependencies, use the following commands:
|
||||
|
||||
```sh
|
||||
# Create a virtual environment
|
||||
python -m venv .venv
|
||||
|
||||
# On MacOS, WSL, Linux
|
||||
source .venv/bin/activate
|
||||
|
||||
# On Windows
|
||||
.\.venv\Scripts\activate
|
||||
|
||||
# Install dependencies
|
||||
pip3 install ansible-core==2.16 'molecule-plugins[docker]' pytest-testinfra jmespath selinux passlib
|
||||
|
||||
# Create molecule network
|
||||
docker network create molecule
|
||||
```
|
||||
|
||||
### Run Minio for local S3
|
||||
|
||||
To be able to run Mimir using an object store backend, run the following command
|
||||
|
||||
```sh
|
||||
docker run -d \
|
||||
-p 9000:9000 \
|
||||
-p 9001:9001 \
|
||||
--name minio-mimir \
|
||||
--network molecule \
|
||||
-e "MINIO_ROOT_USER=testtest" \
|
||||
-e "MINIO_ROOT_PASSWORD=testtest" \
|
||||
-e "MINIO_DEFAULT_BUCKETS=mimir" \
|
||||
bitnami/minio:latest
|
||||
```
|
||||
|
||||
### Testing the changes
|
||||
|
||||
To test the changes in a role run:
|
||||
|
||||
```sh
|
||||
molecule converge
|
||||
## example: molecule converge
|
||||
```
|
||||
|
||||
When Ansible has succesfully ran, you can run assertions against your infrastructure using.
|
||||
|
||||
```sh
|
||||
molecule verify
|
||||
## example: `molecule verify`
|
||||
```
|
||||
|
||||
You can also run commands like `molecule destroy`, `molecule prepare`, and `molecule test`. See Molecule documentation for more information
|
||||
|
||||
## Role Variables
|
||||
|
||||
---
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --------------------------------------- | ---- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| mimir_working_path | str | /usr/share/mimir | Used to specify the directory path where Mimir, a component of the Grafana Agent, stores its working files and temporary data. |
|
||||
| mimir_uninstall | bool | false | If set to `true` will perfom uninstall instead of deployment. |
|
||||
| mimir_ruler_alert_path | str | /data/ruler | Used to specify the directory path where the Mimir ruler component of the Grafana Agent stores its alert files. |
|
||||
| mimir_http_listen_port | str | 8080 | Used to specify the port number on which the Mimir component of the Grafana Agent listens for incoming HTTP requests. |
|
||||
| mimir_http_listen_address | str | 0.0.0.0 | Used to specify the network address on which the Mimir component of the Grafana Agent listens for incoming HTTP requests. |
|
||||
| mimir_ruler.rule_path | str | /data/ruler | Used to specify the directory path where the Mimir ruler component of the Grafana Agent looks for rule files. |
|
||||
| mimir_ruler.alertmanager_url | str | http://127.0.0.1:8080/alertmanager | Used to specify the URL or address of the Alertmanager API that the Mimir ruler component of the Grafana Agent should communicate with. |
|
||||
| mimir_ruler.ring.heartbeat_period | str | 2s | Used to specify the interval at which the Mimir ruler component of the Grafana Agent sends heartbeat signals to the ring. |
|
||||
| mimir_ruler.heartbeat_timeout | str | 10s | Used to specify the maximum duration of time that the Mimir ruler component of the Grafana Agent will wait for a heartbeat signal from other components in the ring. |
|
||||
| mimir_alertmanager.data_dir | str | /data/alertmanager | sed to specify the directory path where the Mimir Alertmanager component of the Grafana Agent stores its data files. |
|
||||
| mimir_alertmanager.fallback_config_file | str | /etc/alertmanager-fallback-config.yaml | Used to specify the path to a fallback configuration file for the Mimir Alertmanager component of the Grafana Agent. |
|
||||
| mimir_alertmanager.external_url | str | http://localhost:9009/alertmanager | Used to specify the external URL or address at which the Mimir Alertmanager component of the Grafana Agent can be accessed. |
|
||||
| mimir_memberlist.join_members | [] | List of members for the Mimir cluster |
|
||||
|
||||
## **Additional Config Variables for `/etc/mimir/config.yml`**
|
||||
|
||||
Below variables allow you to extend Mimir configuration to fit your needs.
|
||||
Always refer to official [Mimir configuration](https://grafana.com/docs/mimir/latest/configure/about-configurations/)
|
||||
to obtain possible configuration parameters.
|
||||
|
||||
> [!NOTE]
|
||||
> These variables are not set by default.
|
||||
|
||||
| Name | Description |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `mimir_blocks_storage` | Configures the `blocks_storage` component. 📚 [documentation](https://grafana.com/docs/mimir/latest/configure/configuration-parameters/#blocks_storage) |
|
||||
| `mimir_ruler_storage` | Configures the `ruler_storage` component. 📚 [documentation](https://grafana.com/docs/mimir/latest/configure/configuration-parameters/#ruler_storage) |
|
||||
| `mimir_alertmanager_storage` | Configures the `alertmanager_storage` component. 📚 [documentation](https://grafana.com/docs/mimir/latest/configure/configuration-parameters/#alertmanager_storage) |
|
||||
| `mimir_distributor` | Configures the `distributor` component. 📚 [documentation](https://grafana.com/docs/mimir/latest/configure/configuration-parameters/#distributor) |
|
||||
| `mimir_ingester` | Configures the `ingester` component. 📚 [documentation](https://grafana.com/docs/mimir/latest/configure/configuration-parameters/#ingester) |
|
||||
| `mimir_querier` | Configures the `querier` component. 📚 [documentation](https://grafana.com/docs/mimir/latest/configure/configuration-parameters/#querier) |
|
||||
|
||||
For extra configuration samples refer to [`examples` directory](../../examples).
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
# defaults file for mimir
|
||||
mimir_version: "latest"
|
||||
mimir_uninstall: false
|
||||
__mimir_arch: "{{ arch_mapping[ansible_facts['architecture']] | default('amd64') }}"
|
||||
mimir_download_url_rpm: "https://github.com/grafana/mimir/releases/download/mimir-{{ mimir_version }}/mimir-{{ mimir_version }}_{{ __mimir_arch }}.rpm"
|
||||
mimir_download_url_deb: "https://github.com/grafana/mimir/releases/download/mimir-{{ mimir_version }}/mimir-{{ mimir_version }}_{{ __mimir_arch }}.deb"
|
||||
mimir_working_path: "/var/lib/mimir"
|
||||
mimir_ruler_alert_path: "{{ mimir_working_path }}/ruler"
|
||||
mimir_http_listen_port: 8080
|
||||
mimir_http_listen_address: "0.0.0.0"
|
||||
|
||||
arch_mapping:
|
||||
x86_64: amd64
|
||||
aarch64: arm64
|
||||
armv7l: armhf
|
||||
i386: i386
|
||||
ppc64le: ppc64le
|
||||
|
||||
mimir_server:
|
||||
http_listen_port: "{{ mimir_http_listen_port }}"
|
||||
http_listen_address: "{{ mimir_http_listen_address }}"
|
||||
|
||||
mimir_ruler:
|
||||
rule_path: "{{ mimir_working_path }}/ruler"
|
||||
alertmanager_url: "http://localhost:{{ mimir_http_listen_port }}/alertmanager"
|
||||
|
||||
mimir_alertmanager:
|
||||
data_dir: "{{ mimir_working_path }}/alertmanager"
|
||||
external_url: "http://localhost:{{ mimir_http_listen_port }}/alertmanager"
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
|
||||
- name: Restart mimir
|
||||
ansible.builtin.systemd:
|
||||
name: mimir.service
|
||||
state: restarted
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
# meta/main.yml
|
||||
galaxy_info:
|
||||
author: "Grafana"
|
||||
role_name: mimir
|
||||
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
|
||||
|
||||
dependencies: []
|
||||
|
||||
allow_duplicates: true
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
- name: Converge mimir
|
||||
hosts: all
|
||||
collections:
|
||||
- grafana.grafana
|
||||
vars:
|
||||
mimir_storage:
|
||||
storage:
|
||||
backend: s3
|
||||
s3:
|
||||
endpoint: minio-mimir.:9000
|
||||
access_key_id: testtest
|
||||
secret_access_key: testtest
|
||||
insecure: true
|
||||
bucket_name: mimir
|
||||
|
||||
# Blocks storage requires a prefix when using a common object storage bucket.
|
||||
mimir_blocks_storage:
|
||||
storage_prefix: blocks
|
||||
tsdb:
|
||||
dir: "{{ mimir_working_path}}/ingester"
|
||||
|
||||
# Use memberlist, a gossip-based protocol, to enable the 3 Mimir replicas to communicate
|
||||
mimir_memberlist:
|
||||
join_members:
|
||||
- molecule-grafana-mimir01.:7946
|
||||
- molecule-grafana-mimir02.:7946
|
||||
- molecule-grafana-mimir03.:7946
|
||||
|
||||
tasks:
|
||||
- name: "Run Grafana mimir collection"
|
||||
include_role:
|
||||
name: mimir
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
dependency:
|
||||
name: galaxy
|
||||
driver:
|
||||
name: docker
|
||||
platforms:
|
||||
- name: molecule-grafana-mimir01
|
||||
image: "geerlingguy/docker-${MOLECULE_DISTRO:-rockylinux8}-ansible:latest"
|
||||
command: ${MOLECULE_DOCKER_COMMAND:-"/sbin/init"}
|
||||
volumes:
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||
cgroupns_mode: host
|
||||
privileged: true
|
||||
pre_build_image: true
|
||||
network: molecule
|
||||
network_mode: "molecule"
|
||||
published_ports:
|
||||
- 7946
|
||||
- 9019:9009
|
||||
- 9096
|
||||
- name: molecule-grafana-mimir02
|
||||
image: "geerlingguy/docker-${MOLECULE_DISTRO:-rockylinux8}-ansible:latest"
|
||||
command: ${MOLECULE_DOCKER_COMMAND:-"/sbin/init"}
|
||||
volumes:
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||
cgroupns_mode: host
|
||||
privileged: true
|
||||
pre_build_image: true
|
||||
network: molecule
|
||||
network_mode: "molecule"
|
||||
published_ports:
|
||||
- 7946
|
||||
- 9029:9009
|
||||
- 9096
|
||||
- name: molecule-grafana-mimir03
|
||||
image: "geerlingguy/docker-${MOLECULE_DISTRO:-rockylinux8}-ansible:latest"
|
||||
command: ${MOLECULE_DOCKER_COMMAND:-"/sbin/init"}
|
||||
volumes:
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||
cgroupns_mode: host
|
||||
privileged: true
|
||||
pre_build_image: true
|
||||
network: molecule
|
||||
network_mode: "molecule"
|
||||
published_ports:
|
||||
- 7946
|
||||
- 9039:9009
|
||||
- 9096
|
||||
|
||||
provisioner:
|
||||
name: ansible
|
||||
env:
|
||||
ANSIBLE_ROLES_PATH: ${MOLECULE_PROJECT_DIRECTORY}/roles
|
||||
|
||||
verifier:
|
||||
name: testinfra
|
||||
lint: |
|
||||
set -e
|
||||
yamllint .
|
||||
ansible-lint .
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
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/mimir",
|
||||
"/var/lib/mimir",
|
||||
]
|
||||
files = [
|
||||
"/etc/mimir/config.yml"
|
||||
]
|
||||
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("mimir")
|
||||
assert s.is_running
|
||||
|
||||
|
||||
def test_packages(host):
|
||||
p = host.package("mimir")
|
||||
assert p.is_installed
|
||||
111
ansible_collections/grafana/grafana/roles/mimir/tasks/deploy.yml
Normal file
111
ansible_collections/grafana/grafana/roles/mimir/tasks/deploy.yml
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
---
|
||||
# tasks file for Mimir deployment
|
||||
- name: Obtain the latest version from the Mimir GitHub repo
|
||||
when: mimir_version == "latest"
|
||||
block:
|
||||
- name: Scrape Github API endpoint to obtain latest Mimir version
|
||||
ansible.builtin.uri:
|
||||
url: "https://api.github.com/repos/grafana/mimir/releases/latest"
|
||||
method: GET
|
||||
body_format: json
|
||||
become: false
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
register: __github_latest_version
|
||||
|
||||
- name: Latest available Mimir version
|
||||
ansible.builtin.set_fact:
|
||||
mimir_version: "{{ __github_latest_version.json.tag_name | regex_replace('^v?(\\d+\\.\\d+\\.\\d+)$', '\\1') }}"
|
||||
|
||||
- name: Verify current deployed version
|
||||
block:
|
||||
- name: Check if Mimir binary is present
|
||||
ansible.builtin.stat:
|
||||
path: "/usr/bin/mimir"
|
||||
register: __already_deployed
|
||||
|
||||
- name: Obtain current deployed Mimir version
|
||||
ansible.builtin.command:
|
||||
cmd: "/usr/bin/mimir --version"
|
||||
changed_when: false
|
||||
register: __current_deployed_version
|
||||
when: __already_deployed.stat.exists | bool
|
||||
|
||||
- name: Include RedHat/Rocky setup
|
||||
ansible.builtin.include_tasks:
|
||||
file: setup-Redhat.yml
|
||||
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']
|
||||
|
||||
- name: Include Debian/Ubuntu setup
|
||||
ansible.builtin.include_tasks:
|
||||
file: setup-Debian.yml
|
||||
when: ansible_facts['os_family'] == 'Debian'
|
||||
|
||||
- name: Check if Mimir default dir is present
|
||||
ansible.builtin.stat:
|
||||
path: "/tmp/mimir/boltdb-shipper-active"
|
||||
register: __default_structure
|
||||
|
||||
- name: Default structure cleanup
|
||||
when: __default_structure.stat.exists | bool
|
||||
block:
|
||||
- name: Ensure that Mimir is stopped before default cleanup
|
||||
ansible.builtin.systemd:
|
||||
name: mimir.service
|
||||
state: stopped
|
||||
|
||||
- name: Remove default configuration from "/tmp/mimir" directory
|
||||
ansible.builtin.file:
|
||||
path: "/tmp/mimir"
|
||||
state: absent
|
||||
|
||||
- name: Ensure that Mimir working path exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ mimir_working_path }}"
|
||||
state: directory
|
||||
owner: "mimir"
|
||||
group: "mimir"
|
||||
mode: "0755"
|
||||
|
||||
- name: Ensure that Mimir rule path exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ mimir_ruler_alert_path }}"
|
||||
state: directory
|
||||
owner: "mimir"
|
||||
group: "mimir"
|
||||
mode: "0755"
|
||||
when:
|
||||
- mimir_ruler_alert_path is defined
|
||||
- mimir_ruler is defined
|
||||
|
||||
- name: Template Mimir config - /etc/mimir/config.yml
|
||||
ansible.builtin.template:
|
||||
src: "config.yml.j2"
|
||||
dest: "/etc/mimir/config.yml"
|
||||
owner: "mimir"
|
||||
group: "mimir"
|
||||
mode: "0644"
|
||||
validate: "mimir -modules --config.file=%s"
|
||||
environment:
|
||||
PATH: "/usr/local/bin:{{ ansible_env.PATH }}"
|
||||
notify:
|
||||
- Restart mimir
|
||||
|
||||
- name: Ensure restart has completed
|
||||
ansible.builtin.meta: flush_handlers
|
||||
|
||||
- name: Ensure that Mimir is started
|
||||
ansible.builtin.systemd:
|
||||
name: mimir.service
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
|
||||
- name: Verify that Mimir URL is responding
|
||||
ansible.builtin.uri:
|
||||
url: "http://{{ mimir_http_listen_address }}:{{ mimir_http_listen_port }}/ready"
|
||||
method: GET
|
||||
register: mimir_verify_url_status_code
|
||||
retries: 5
|
||||
delay: 8
|
||||
until: mimir_verify_url_status_code.status == 200
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
- name: Deploy Mimir service
|
||||
ansible.builtin.include_tasks:
|
||||
file: "deploy.yml"
|
||||
when: not mimir_uninstall
|
||||
|
||||
- name: Uninstall Mimir service
|
||||
ansible.builtin.include_tasks:
|
||||
file: "uninstall.yml"
|
||||
when: mimir_uninstall
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
- name: APT - Install Mimir
|
||||
ansible.builtin.apt:
|
||||
deb: "{{ mimir_download_url_deb }}"
|
||||
state: present
|
||||
notify: Restart mimir
|
||||
when: __current_deployed_version.stdout is not defined or mimir_version not in __current_deployed_version.stdout
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
- name: DNF - Install Mimir from remote URL
|
||||
ansible.builtin.dnf:
|
||||
name: "{{ mimir_download_url_rpm }}"
|
||||
state: present
|
||||
disable_gpg_check: true
|
||||
notify: Restart mimir
|
||||
when: __current_deployed_version.stdout is not defined or mimir_version not in __current_deployed_version.stdout
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
# tasks file for Mimir uninstall
|
||||
|
||||
- name: Stop Mimir service
|
||||
ansible.builtin.systemd: # noqa ignore-errors
|
||||
name: mimir
|
||||
state: stopped
|
||||
ignore_errors: true
|
||||
|
||||
- name: Uninstall Mimir rpm package
|
||||
ansible.builtin.dnf:
|
||||
name: "mimir"
|
||||
state: absent
|
||||
autoremove: true
|
||||
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']
|
||||
|
||||
- name: Uninstall Mimir deb package
|
||||
ansible.builtin.apt:
|
||||
name: "mimir"
|
||||
state: absent
|
||||
purge: true
|
||||
when: ansible_facts['os_family'] == 'Debian'
|
||||
|
||||
- name: Ensure that Mimir firewalld rule is not present - tcp port {{ mimir_http_listen_port }}
|
||||
ansible.posix.firewalld: # noqa ignore-errors
|
||||
immediate: true
|
||||
permanent: true
|
||||
port: "{{ mimir_http_listen_port }}/tcp"
|
||||
state: disabled
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove Mimir directories"
|
||||
ansible.builtin.file:
|
||||
path: "{{ remove_me }}"
|
||||
state: absent
|
||||
loop:
|
||||
- "/etc/mimir"
|
||||
- "{{ mimir_working_path }}"
|
||||
loop_control:
|
||||
loop_var: remove_me
|
||||
|
||||
- name: Remove the Mimir system user
|
||||
ansible.builtin.user:
|
||||
name: "mimir"
|
||||
force: true
|
||||
state: absent
|
||||
|
||||
- name: Remove Mimir system group
|
||||
ansible.builtin.group:
|
||||
name: "mimir"
|
||||
state: absent
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
# Run Mimir in single process mode, with all components running in 1 process.
|
||||
target: all,alertmanager,overrides-exporter
|
||||
|
||||
# Configure Mimir to use Minio as object storage backend.
|
||||
common:
|
||||
{% if mimir_storage is defined %}
|
||||
{{ mimir_storage | to_nice_yaml(indent=2, sort_keys=False) | indent(2, False)}}
|
||||
{% endif %}
|
||||
|
||||
# Blocks storage requires a prefix when using a common object storage bucket.
|
||||
{% if mimir_blocks_storage is defined %}
|
||||
blocks_storage:
|
||||
{{ mimir_blocks_storage | to_nice_yaml(indent=2, sort_keys=False) | indent(2, False)}}
|
||||
{% endif %}
|
||||
|
||||
# Blocks storage requires a prefix when using a common object storage bucket.
|
||||
{% if mimir_ruler_storage is defined %}
|
||||
ruler_storage:
|
||||
{{ mimir_ruler_storage | to_nice_yaml(indent=2, sort_keys=False) | indent(2, False)}}
|
||||
{% endif %}
|
||||
|
||||
# Alertmanager storage requires a prefix when using a common object storage bucket.
|
||||
{% if mimir_alertmanager_storage is defined %}
|
||||
alertmanager_storage:
|
||||
{{ mimir_alertmanager_storage | to_nice_yaml(indent=2, sort_keys=False) | indent(2, False)}}
|
||||
{% endif %}
|
||||
|
||||
# Use memberlist, a gossip-based protocol, to enable the 3 Mimir replicas to communicate.
|
||||
{% if mimir_memberlist is defined %}
|
||||
memberlist:
|
||||
{{ mimir_memberlist | to_nice_yaml(indent=2, sort_keys=False) | indent(2, False)}}
|
||||
{% endif %}
|
||||
|
||||
{% if mimir_ruler is defined %}
|
||||
ruler:
|
||||
{{ mimir_ruler | to_nice_yaml(indent=2, sort_keys=False) | indent(2, False)}}
|
||||
{% endif %}
|
||||
|
||||
{% if mimir_alertmanager is defined %}
|
||||
alertmanager:
|
||||
{{ mimir_alertmanager | to_nice_yaml(indent=2, sort_keys=False) | indent(2, False)}}
|
||||
{% endif %}
|
||||
|
||||
{% if mimir_server is defined %}
|
||||
server:
|
||||
{{ mimir_server | to_nice_yaml(indent=2, sort_keys=False) | indent(2, False)}}
|
||||
{% endif %}
|
||||
|
||||
{% if mimir_limits is defined %}
|
||||
limits:
|
||||
{{ mimir_limits | to_nice_yaml(indent=2, sort_keys=False) | indent(2, False)}}
|
||||
{% endif %}
|
||||
|
||||
{% if mimir_distributor is defined %}
|
||||
distributor:
|
||||
{{ mimir_distributor | to_nice_yaml(indent=2, sort_keys=False) | indent(2, False)}}
|
||||
{% endif %}
|
||||
|
||||
{% if mimir_ingester is defined %}
|
||||
ingester:
|
||||
{{ mimir_ingester | to_nice_yaml(indent=2, sort_keys=False) | indent(2, False)}}
|
||||
{% endif %}
|
||||
|
||||
{% if mimir_querier is defined %}
|
||||
querier:
|
||||
{{ mimir_querier | to_nice_yaml(indent=2, sort_keys=False) | indent(2, False)}}
|
||||
{% endif %}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue