mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add new grafana dashboard lookup plugin (#41319)
This commit is contained in:
parent
562ff66a98
commit
9faadce0b2
1 changed files with 178 additions and 0 deletions
178
lib/ansible/plugins/lookup/grafana_dashboard.py
Normal file
178
lib/ansible/plugins/lookup/grafana_dashboard.py
Normal file
|
@ -0,0 +1,178 @@
|
|||
# (c) 2018 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = """
|
||||
lookup: grafana_dashboard
|
||||
author: Thierry Salle (@seuf)
|
||||
version_added: "2.7"
|
||||
short_description: list or search grafana dashboards
|
||||
description:
|
||||
- This lookup returns a list of grafana dashboards with possibility to filter them by query.
|
||||
options:
|
||||
grafana_url:
|
||||
description: url of grafana.
|
||||
env:
|
||||
- name: GRAFANA_URL
|
||||
default: http://127.0.0.1:3000
|
||||
grafana_api_key:
|
||||
description:
|
||||
- api key of grafana.
|
||||
- when C(grafana_api_key) is set, the options C(grafan_user), C(grafana_password) and C(grafana_org_id) are ignored.
|
||||
- Attention, please remove the two == at the end of the grafana_api_key
|
||||
- because ansible lookup plugins options are splited on = (see example).
|
||||
env:
|
||||
- name: GRAFANA_API_KEY
|
||||
grafana_user:
|
||||
description: grafana authentication user.
|
||||
env:
|
||||
- name: GRAFANA_USER
|
||||
default: admin
|
||||
grafana_password:
|
||||
description: grafana authentication password.
|
||||
env:
|
||||
- name: GRAFANA_PASSWORD
|
||||
default: admin
|
||||
grafana_org_id:
|
||||
description: grafana organisation id.
|
||||
env:
|
||||
- name: GRAFANA_ORG_ID
|
||||
default: 1
|
||||
search:
|
||||
description: optional filter for dashboard search.
|
||||
env:
|
||||
- name: GRAFANA_DASHBOARD_SEARCH
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
- name: get project foo grafana dashboards
|
||||
set_fact:
|
||||
grafana_dashboards: "{{ lookup('grafana_dashboard', 'grafana_url=http://grafana.company.com grafana_user=admin grafana_password=admin search=foo') }}"
|
||||
|
||||
- name: get all grafana dashboards
|
||||
set_fact:
|
||||
grafana_dashboards: "{{ lookup('grafana_dashboard', 'grafana_url=http://grafana.company.com grafana_api_key=' ~ grafana_api_key|replace('==', '')) }}"
|
||||
"""
|
||||
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
from ansible.errors import AnsibleError, AnsibleParserError
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.module_utils.urls import open_url
|
||||
from ansible.module_utils._text import to_bytes
|
||||
from ansible.module_utils.six.moves.urllib.error import HTTPError
|
||||
|
||||
try:
|
||||
from __main__ import display
|
||||
except ImportError:
|
||||
from ansible.utils.display import Display
|
||||
display = Display()
|
||||
|
||||
|
||||
ANSIBLE_GRAFANA_URL = 'http://127.0.0.1:3000'
|
||||
ANSIBLE_GRAFANA_API_KEY = None
|
||||
ANSIBLE_GRAFANA_USER = 'admin'
|
||||
ANSIBLE_GRAFANA_PASSWORD = 'admin'
|
||||
ANSIBLE_GRAFANA_ORG_ID = 1
|
||||
ANSIBLE_GRAFANA_DASHBOARD_SEARCH = None
|
||||
|
||||
if os.getenv('GRAFANA_URL') is not None:
|
||||
ANSIBLE_GRAFANA_URL = os.environ['GRAFANA_URL']
|
||||
|
||||
if os.getenv('GRAFANA_API_KEY') is not None:
|
||||
ANSIBLE_GRAFANA_API_KEY = os.environ['GRAFANA_API_KEY']
|
||||
|
||||
if os.getenv('GRAFANA_USER') is not None:
|
||||
ANSIBLE_GRAFANA_USER = os.environ['GRAFANA_USER']
|
||||
|
||||
if os.getenv('GRAFANA_PASSWORD') is not None:
|
||||
ANSIBLE_GRAFANA_PASSWORD = os.environ['GRAFANA_PASSWORD']
|
||||
|
||||
if os.getenv('GRAFANA_ORG_ID') is not None:
|
||||
ANSIBLE_GRAFANA_ORG_ID = os.environ['GRAFANA_ORG_ID']
|
||||
|
||||
if os.getenv('GRAFANA_DASHBOARD_SEARCH') is not None:
|
||||
ANSIBLE_GRAFANA_DASHBOARD_SEARCH = os.environ['GRAFANA_DASHBOARD_SEARCH']
|
||||
|
||||
|
||||
class GrafanaAPIException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class GrafanaAPI:
|
||||
def __init__(self, **kwargs):
|
||||
self.grafana_url = kwargs.get('grafana_url', ANSIBLE_GRAFANA_URL)
|
||||
self.grafana_api_key = kwargs.get('grafana_api_key', ANSIBLE_GRAFANA_API_KEY)
|
||||
self.grafana_user = kwargs.get('grafana_user', ANSIBLE_GRAFANA_USER)
|
||||
self.grafana_password = kwargs.get('grafana_password', ANSIBLE_GRAFANA_PASSWORD)
|
||||
self.grafana_org_id = kwargs.get('grafana_org_id', ANSIBLE_GRAFANA_ORG_ID)
|
||||
self.search = kwargs.get('search', ANSIBLE_GRAFANA_DASHBOARD_SEARCH)
|
||||
|
||||
def grafana_switch_organisation(self, headers):
|
||||
try:
|
||||
r = open_url('%s/api/user/using/%s' % (self.grafana_url, self.grafana_org_id), headers=headers, method='POST')
|
||||
except HTTPError as e:
|
||||
raise GrafanaAPIException('Unable to switch to organization %s : %s' % (self.grafana_org_id, str(e)))
|
||||
if r.getcode() != 200:
|
||||
raise GrafanaAPIException('Unable to switch to organization %s : %s' % (self.grafana_org_id, str(r.getcode())))
|
||||
|
||||
def grafana_headers(self):
|
||||
headers = {'content-type': 'application/json; charset=utf8'}
|
||||
if self.grafana_api_key:
|
||||
headers['Authorization'] = "Bearer %s==" % self.grafana_api_key
|
||||
else:
|
||||
auth = base64.b64encode(to_bytes('%s:%s' % (self.grafana_user, self.grafana_password)).replace('\n', ''))
|
||||
headers['Authorization'] = 'Basic %s' % auth
|
||||
self.grafana_switch_organisation(headers)
|
||||
|
||||
return headers
|
||||
|
||||
def grafana_list_dashboards(self):
|
||||
# define http headers
|
||||
headers = self.grafana_headers()
|
||||
|
||||
dashboard_list = []
|
||||
try:
|
||||
if self.search:
|
||||
r = open_url('%s/api/search?query=%s' % (self.grafana_url, self.search), headers=headers, method='GET')
|
||||
else:
|
||||
r = open_url('%s/api/search/' % self.grafana_url, headers=headers, method='GET')
|
||||
except HTTPError as e:
|
||||
raise GrafanaAPIException('Unable to search dashboards : %s' % str(e))
|
||||
if r.getcode() == 200:
|
||||
try:
|
||||
dashboard_list = json.loads(r.read())
|
||||
except Exception as e:
|
||||
raise GrafanaAPIException('Unable to parse json list %s' % str(e))
|
||||
else:
|
||||
raise GrafanaAPIException('Unable to list grafana dashboards : %s' % str(r.getcode()))
|
||||
|
||||
return dashboard_list
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def run(self, terms, variables=None, **kwargs):
|
||||
|
||||
grafana_args = terms[0].split(' ')
|
||||
grafana_dict = {}
|
||||
ret = []
|
||||
|
||||
for param in grafana_args:
|
||||
try:
|
||||
key, value = param.split('=')
|
||||
except ValueError:
|
||||
raise AnsibleError("grafana_dashboard lookup plugin needs key=value pairs, but received %s" % terms)
|
||||
grafana_dict[key] = value
|
||||
|
||||
grafana = GrafanaAPI(**grafana_dict)
|
||||
|
||||
ret = grafana.grafana_list_dashboards()
|
||||
|
||||
return ret
|
Loading…
Reference in a new issue