From 54cef2ed2cb498726b75ff0e3ad793c21366234c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Soko=C5=82owski?= Date: Tue, 1 Dec 2020 17:47:20 +0100 Subject: [PATCH] add grafana role files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jakub SokoĊ‚owski --- README.md | 39 +++++++++++++++++++++++++++ defaults/main.yml | 41 ++++++++++++++++++++++++++++ handlers/main.yml | 5 ++++ tasks/config.yml | 48 +++++++++++++++++++++++++++++++++ tasks/consul.yml | 14 ++++++++++ tasks/container.yml | 16 +++++++++++ tasks/main.yml | 4 +++ templates/backend.yml.j2 | 23 ++++++++++++++++ templates/elasticsearch.yml | 24 +++++++++++++++++ templates/grafana.ini.j2 | 54 +++++++++++++++++++++++++++++++++++++ 10 files changed, 268 insertions(+) create mode 100644 README.md create mode 100644 defaults/main.yml create mode 100644 handlers/main.yml create mode 100644 tasks/config.yml create mode 100644 tasks/consul.yml create mode 100644 tasks/container.yml create mode 100644 tasks/main.yml create mode 100644 templates/backend.yml.j2 create mode 100644 templates/elasticsearch.yml create mode 100644 templates/grafana.ini.j2 diff --git a/README.md b/README.md new file mode 100644 index 0000000..8365ac4 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# Description + +This role configures a docker container running [Grafana](http://docs.grafana.org/) as a metrics dashboard. + +It connects to a configured instance of [Prometheus](https://prometheus.io/docs/introduction/overview/) or [Cortex](https://cortexmetrics.io/) to query for metrics. + +# Configuration + +The main settings that matter are: +```yaml +grafana_domain: 'grafana.example.org' +grafana_version: '7.3.4' +``` +You should also configure OAuth: +```yaml +grafana_oauth_id: '123qwe123qwe123' +grafana_oauth_secret: 'qweasdqweasdqweasdqweasd +``` +Optional email configuration might be useful: +```yaml +grafana_smtp_enabled: true +grafana_smtp_from_addr: 'grafana@example.org' +grafana_smtp_from_name: ~ +grafana_smtp_host: ~ +grafana_smtp_port: ~ +grafana_smtp_user: ~ +grafana_smtp_pass: ~ +``` +You can optionally allow anonymous access: +```yaml +grafana_anonymous: true +``` + +# Details + +Configuration consists of two templates: + +* `grafana.ini.j2` - Grafana main configuration file. +* `backends.yml.j2` - Initial configuration of the query backend(s). diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..1cea1be --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,41 @@ +--- +grafana_domain: ~ + +grafana_version: '7.3.4' +grafana_image: 'grafana/grafana:{{ grafana_version }}' +grafana_cont_name: grafana +grafana_cont_vol: '/docker/grafana' +grafana_cont_links: [] +grafana_port: 9400 +# see: http://docs.grafana.org/installation/docker/#migration-from-a-previous-version-of-the-docker-container-to-5-1-or-later +grafana_cont_uid: 472 +# adjust for dockremap +grafana_host_uid: '{{ 100000 + grafana_cont_uid | int }}' + +# OAuth secrets +grafana_oauth_id: ~ +grafana_oauth_secret: ~ + +# SMTP for invite emails +grafana_smtp_enabled: false +grafana_smtp_from_addr: ~ +grafana_smtp_from_name: ~ +grafana_smtp_host: ~ +grafana_smtp_port: ~ +grafana_smtp_user: ~ +grafana_smtp_pass: ~ + +# optional anonymous access +grafana_anonymous: false + +# for disabling graph snapshots +grafana_snaphots_enabled: true + +# plugins to clone into the plugins directory +grafana_plugins: + - https://github.com/GoshPosh/grafana-meta-queries/archive/0.0.3.zip + +# generic container settings +cont_state: started +cont_restart: false +cont_recreate: false diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..214937f --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart grafana + docker_container: + name: '{{ grafana_cont_name }}' + restart: true diff --git a/tasks/config.yml b/tasks/config.yml new file mode 100644 index 0000000..e3c2002 --- /dev/null +++ b/tasks/config.yml @@ -0,0 +1,48 @@ +--- +- name: Create grafana directories + file: + path: '{{ item }}' + state: directory + owner: '{{ grafana_host_uid }}' + group: docker + mode: 0775 + recurse: true + with_items: + - '{{ grafana_cont_vol }}' + - '{{ grafana_cont_vol }}/etc/provisioning/datasources' + - '{{ grafana_cont_vol }}/lib/plugins' + - '{{ grafana_cont_vol }}/lib/dashboards' + +- name: Copy grafana config file + template: + src: 'grafana.ini.j2' + dest: '{{ grafana_cont_vol }}/etc/grafana.ini' + owner: '{{ grafana_host_uid }}' + group: docker + register: cont_conf + +- name: Generate datasource config file + template: + src: backend.yml.j2 + dest: '{{ grafana_cont_vol }}/etc/provisioning/datasources/backend.yml' + owner: '{{ grafana_host_uid }}' + group: docker + notify: restart grafana + +- name: Generate ElasticSearch datasource config file + template: + src: elasticsearch.yml + dest: '{{ grafana_cont_vol }}/etc/provisioning/datasources/elasticsearch.yml' + owner: '{{ grafana_host_uid }}' + group: docker + when: grafana_es_source_container | d(False) + notify: restart grafana + +- name: Install plugins from zip archives + unarchive: + src: '{{ item }}' + dest: '{{ grafana_cont_vol }}/lib/plugins' + owner: '{{ grafana_host_uid }}' + group: docker + remote_src: true + with_items: '{{ grafana_plugins }}' diff --git a/tasks/consul.yml b/tasks/consul.yml new file mode 100644 index 0000000..b389344 --- /dev/null +++ b/tasks/consul.yml @@ -0,0 +1,14 @@ +--- +- name: Create Consul service definition + include_role: name=consul-service + vars: + consul_config_name: 'grafana' + consul_services: + - name: 'grafana' + tags: ['monitor', 'metrics-view'] + port: '{{ grafana_port }}' + checks: + - id: grafana-health + name: Grafana current health + type: http + http: 'http://localhost:{{ grafana_port }}/api/health' diff --git a/tasks/container.yml b/tasks/container.yml new file mode 100644 index 0000000..ff0d6e2 --- /dev/null +++ b/tasks/container.yml @@ -0,0 +1,16 @@ +--- +- name: Start grafana container + docker_container: + name: '{{ grafana_cont_name }}' + image: '{{ grafana_image }}' + pull: true + restart_policy: always + state: '{{ cont_state }}' + recreate: '{{ cont_recreate }}' + restart: '{{ cont_conf.changed | default(cont_restart) }}' + ports: + - '127.0.0.1:{{ grafana_port }}:3000' + links: '{{ grafana_cont_links }}' + volumes: + - '{{ grafana_cont_vol }}/lib:/var/lib/grafana' + - '{{ grafana_cont_vol }}/etc:/etc/grafana' diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..dae944c --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,4 @@ +--- +- import_tasks: config.yml +- import_tasks: container.yml +- import_tasks: consul.yml diff --git a/templates/backend.yml.j2 b/templates/backend.yml.j2 new file mode 100644 index 0000000..4e94595 --- /dev/null +++ b/templates/backend.yml.j2 @@ -0,0 +1,23 @@ +apiVersion: 1 + +deleteDatasources: +{% for service in prometheus_services.json %} + - id: {{ loop.index }} +{% endfor %} + +datasources: +{% for service in prometheus_services.json %} +- name: {{ service.Node }} + type: prometheus + orgId: 1 + access: proxy + url: http://{{ service.ServiceAddress }}:{{ service.ServicePort }}/{{ service.ServiceMeta.path | d("") }} + withCredentials: false + isDefault: {{ loop.first }} + jsonData: + tlsAuth: false + tlsAuthWithCACert: false + version: 1 + editable: true + +{% endfor %} diff --git a/templates/elasticsearch.yml b/templates/elasticsearch.yml new file mode 100644 index 0000000..fbe6510 --- /dev/null +++ b/templates/elasticsearch.yml @@ -0,0 +1,24 @@ +apiVersion: 1 + +deleteDatasources: + - id: 1 + +datasources: +- name: ElasticSearch + type: elasticsearch + orgId: 1 + database: '[logstash-]YYYY.MM.DD' + access: proxy + url: http://elasticsearch:{{ grafana_es_source_port }} + withCredentials: false + isDefault: false + jsonData: + tlsAuth: false + tlsAuthWithCACert: false + esVersion: 70 + interval: 'Daily' + timeField: '@timestamp' + logMessageField: 'message' + logLevelField: 'severity_name' + version: 1 + editable: true diff --git a/templates/grafana.ini.j2 b/templates/grafana.ini.j2 new file mode 100644 index 0000000..c7eaa80 --- /dev/null +++ b/templates/grafana.ini.j2 @@ -0,0 +1,54 @@ +[server] +domain = {{ grafana_domain | mandatory }}/ +root_url = https://{{ grafana_domain | mandatory }}/ + +[security] +disable_gravatar = true +allow_sign_up = false +admin_user = {{ grafana_username | mandatory }} +# This works only when container is created the first time +admin_password = {{ grafana_password | mandatory }} + +[users] +allow_sign_up = false +auto_assign_org = true +auto_assign_org_id = status-im +auto_assign_org_role = Editor + +{% if grafana_smtp_enabled %} +[smtp] +enabled = true +from_address = {{ grafana_smtp_from_addr }} +from_name = {{ grafana_smtp_from_name }} +host = {{ grafana_smtp_host | mandatory }}:{{ grafana_smtp_port | mandatory }} +user = {{ grafana_smtp_user | mandatory }} +password = {{ grafana_smtp_pass | mandatory }} +{% endif %} + +[snapshots] +external_enabled = {{ grafana_snaphots_enabled | to_json }} + +[auth] +disable_login_form = true +oauth_auto_login = true +signout_redirect_url = https://{{ grafana_domain | mandatory }}/ + +{% if grafana_anonymous %} +[auth.anonymous] +enabled = true +org_name = status-im +org_role = Viewer +{% endif %} + +[auth.github] +enabled = true +allow_sign_up = true +client_id = {{ grafana_oauth_id | mandatory }} +client_secret = {{ grafana_oauth_secret | mandatory }} +scopes = user:email,read:org +auth_url = https://github.com/login/oauth/authorize +token_url = https://github.com/login/oauth/access_token +api_url = https://api.github.com/user +allow_sign_up = true +# space-delimited organization names +allowed_organizations = status-im