Skip to content
Snippets Groups Projects
Commit 1466c212 authored by Bjarke Madsen's avatar Bjarke Madsen
Browse files

Only be dependent on grafana hostname

Use datasource-specific config instead of environment config
Add influxdb datasource config
Remove unused config keys
parent 1a1849a5
No related branches found
No related tags found
No related merge requests found
...@@ -4,24 +4,55 @@ import jsonschema ...@@ -4,24 +4,55 @@ import jsonschema
CONFIG_SCHEMA = { CONFIG_SCHEMA = {
"$schema": "http://json-schema.org/draft-07/schema#", "$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"influx-datasource": {
"type": "object",
"properties": {
"name": {"type": "string"},
"username": {"type": "string"},
"password": {"type": "string"},
"type": {"type": "string"},
"url": {"type": "string"},
"database": {"type": "string"},
"basicAuth": {"type": "boolean"},
"access": {"type": "string"},
"isDefault": {"type": "boolean"},
"readOnly": {"type": "boolean"}
},
"required": [
"name",
"type",
"url",
"database",
"basicAuth",
"access",
"isDefault",
"readOnly"
]
}
},
"type": "object", "type": "object",
"properties": { "properties": {
"admin_username": {"type": "string"}, "admin_username": {"type": "string"},
"admin_password": {"type": "string"}, "admin_password": {"type": "string"},
"hostname": {"type": "string"}, "hostname": {"type": "string"},
"listen_port": {"type": "integer"}, "listen_port": {"type": "integer"},
"grafana_port": {"type": "integer"},
"organizations": {"type": "array", "items": {"type": "string"}}, "organizations": {"type": "array", "items": {"type": "string"}},
"BRIAN_ENVIRONMENT": {"type": "string"} "datasources": {
"type": "object",
"properties": {
"influxdb": {"$ref": "#definitions/influx-datasource"}
},
"additionalProperties": False
},
}, },
"required": [ "required": [
"admin_username", "admin_username",
"admin_password", "admin_password",
"hostname", "hostname",
"listen_port",
"grafana_port",
"organizations", "organizations",
"BRIAN_ENVIRONMENT" "datasources"
], ],
"additionalProperties": False "additionalProperties": False
} }
...@@ -31,11 +62,10 @@ def defaults(): ...@@ -31,11 +62,10 @@ def defaults():
return { return {
"admin_username": "admin", "admin_username": "admin",
"admin_password": "admin", "admin_password": "admin",
"hostname": "localhost", "hostname": "localhost:3000",
"listen_port": 3001, "listen_port": 3001,
"grafana_port": 3000,
"organizations": ["Main Org."], "organizations": ["Main Org."],
"BRIAN_ENVIRONMENT": "test" "datasources": {}
} }
......
...@@ -74,10 +74,21 @@ def _get_dashboard(request: TokenRequest, uid: int): ...@@ -74,10 +74,21 @@ def _get_dashboard(request: TokenRequest, uid: int):
# supplied dashboards are JSON blobs exported from GUI with a UID. # supplied dashboards are JSON blobs exported from GUI with a UID.
def create_dashboard(request: TokenRequest, dashboard: Dict): def create_dashboard(request: TokenRequest, dashboard: Dict):
title = dashboard['title']
existing_dashboard = None existing_dashboard = None
if dashboard.get('uid') is not None: has_uid = dashboard.get('uid') is not None
if has_uid:
existing_dashboard = _get_dashboard(request, uid=dashboard['uid']) existing_dashboard = _get_dashboard(request, uid=dashboard['uid'])
# The title might not match the one that's provisioned with that UID.
# Try to find it by searching for the title instead.
if existing_dashboard is not None:
grafana_title = existing_dashboard['dashboard']['title']
different = grafana_title != title
else: else:
different = False
if existing_dashboard is None or different:
existing_dashboard = _search_dashboard(request, dashboard) existing_dashboard = _search_dashboard(request, dashboard)
if existing_dashboard: if existing_dashboard:
...@@ -92,7 +103,6 @@ def create_dashboard(request: TokenRequest, dashboard: Dict): ...@@ -92,7 +103,6 @@ def create_dashboard(request: TokenRequest, dashboard: Dict):
'dashboard': dashboard, 'dashboard': dashboard,
'overwrite': False 'overwrite': False
} }
title = dashboard["title"]
try: try:
action = "Updating" if existing_dashboard else "Provisioning" action = "Updating" if existing_dashboard else "Provisioning"
logger.info(f'{action} dashboard: {title}') logger.info(f'{action} dashboard: {title}')
......
import logging import logging
import re
import os import os
import json import json
from typing import Dict from typing import Dict
...@@ -44,10 +43,17 @@ def get_datasources(request: Request): ...@@ -44,10 +43,17 @@ def get_datasources(request: Request):
return request.get('api/datasources') return request.get('api/datasources')
def create_datasource(request: TokenRequest, datasource: Dict, environment): def create_datasource(request: TokenRequest, datasource: Dict, datasources):
try: try:
datasource["url"] = re.sub( ds_type = datasource["type"]
'test|uat|prod', environment, datasource["url"]) # find out which params
# we need to configure for this datasource type
config = datasources.get(ds_type, None)
if config is None:
logger.exception(
f'No datasource config could be found for {ds_type}')
return None
datasource.update(config)
r = request.post('api/datasources', json=datasource) r = request.post('api/datasources', json=datasource)
except HTTPError: except HTTPError:
logger.exception('Error when provisioning datasource') logger.exception('Error when provisioning datasource')
......
...@@ -43,11 +43,13 @@ def provision(config): ...@@ -43,11 +43,13 @@ def provision(config):
# Provision missing data sources # Provision missing data sources
for datasource in get_missing_datasource_definitions(token_request): for datasource in get_missing_datasource_definitions(token_request):
ds = create_datasource(token_request, if datasource:
datasource, ds = create_datasource(token_request,
config.get('BRIAN_ENVIRONMENT', 'test')) datasource,
if ds: config.get('datasources'))
logger.info(f'Provisioned datasource: {datasource["name"]}') if ds:
logger.info(
f'Provisioned datasource: {datasource["name"]}')
# Provision dashboards, overwriting existing ones. # Provision dashboards, overwriting existing ones.
for dashboard in get_dashboard_definitions(): for dashboard in get_dashboard_definitions():
......
...@@ -53,10 +53,10 @@ class Request(object): ...@@ -53,10 +53,10 @@ class Request(object):
class AdminRequest(Request): class AdminRequest(Request):
def __init__(self, hostname, grafana_port, admin_username, admin_password, def __init__(self, hostname, admin_username, admin_password,
**kwargs): **kwargs):
self.username = admin_username self.username = admin_username
url = f'{admin_username}:{admin_password}@{hostname}:{grafana_port}/' url = f'{admin_username}:{admin_password}@{hostname}/'
super().__init__('http://' + url) super().__init__('http://' + url)
def __str__(self): def __str__(self):
...@@ -64,10 +64,10 @@ class AdminRequest(Request): ...@@ -64,10 +64,10 @@ class AdminRequest(Request):
class TokenRequest(Request): class TokenRequest(Request):
def __init__(self, hostname, grafana_port, token: str, **kwargs): def __init__(self, hostname, token: str, **kwargs):
self.token = token self.token = token
super().__init__(f'http://{hostname}:{grafana_port}/', { super().__init__(f'http://{hostname}/', {
'Authorization': 'Bearer ' + token 'Authorization': 'Bearer ' + token
}) })
......
...@@ -8,18 +8,27 @@ import brian_dashboard_manager ...@@ -8,18 +8,27 @@ import brian_dashboard_manager
@pytest.fixture @pytest.fixture
def data_config(): def data_config():
return { return {
"admin_username": "admin", "admin_username": "fakeadmin",
"admin_password": "admin", "admin_password": "fakeadmin",
"hostname": "localhost", "hostname": "myfakehostname.org",
"listen_port": 65001,
"grafana_port": 65005,
"organizations": [ "organizations": [
'Testorg1', 'Testorg1',
'GÉANT Testorg2', 'GÉANT Testorg2',
'NRENsTestorg3', 'NRENsTestorg3',
'General Public' 'General Public'
], ],
"BRIAN_ENVIRONMENT": "test" "datasources": {
"influxdb": {
"name": "PollerInfluxDB",
"type": "influxdb",
"access": "proxy",
"url": "http://prod-poller-ui01.geant.org:8086",
"database": "poller",
"basicAuth": False,
"isDefault": True,
"readOnly": False
}
}
} }
......
...@@ -79,9 +79,6 @@ def test_create_prod_datasource(data_config): ...@@ -79,9 +79,6 @@ def test_create_prod_datasource(data_config):
def post_callback(request): def post_callback(request):
body = json.loads(request.body) body = json.loads(request.body)
# we are testing provisioning logic to prod, so the URL needs test ->
# prod translation.
assert body['url'] == 'http://prod-brian-datasource.geant.org:8086'
result = { result = {
'datasource': { 'datasource': {
'id': 1, 'id': 1,
...@@ -109,9 +106,12 @@ def test_create_prod_datasource(data_config): ...@@ -109,9 +106,12 @@ def test_create_prod_datasource(data_config):
url=request.BASE_URL + 'api/datasources', url=request.BASE_URL + 'api/datasources',
callback=post_callback) callback=post_callback)
data = provision.create_datasource(request, BODY, environment='prod') data = provision.create_datasource(
request, BODY, datasources=data_config['datasources'])
assert data is not None datasource_type = data['datasource']['type']
datasource_config_url = data_config['datasources'][datasource_type]['url']
assert data['datasource']['url'] == datasource_config_url
@responses.activate @responses.activate
...@@ -134,7 +134,8 @@ def test_create_prod_datasource_fails(data_config): ...@@ -134,7 +134,8 @@ def test_create_prod_datasource_fails(data_config):
url=request.BASE_URL + 'api/datasources', url=request.BASE_URL + 'api/datasources',
callback=lambda f: (400, {}, '')) callback=lambda f: (400, {}, ''))
data = provision.create_datasource(request, BODY, environment='prod') data = provision.create_datasource(
request, BODY, datasources=data_config['datasources'])
# if an error occured when provisioning a datasource, we log the response # if an error occured when provisioning a datasource, we log the response
# but return None # but return None
......
...@@ -11,7 +11,7 @@ from brian_dashboard_manager.grafana.utils.request import \ ...@@ -11,7 +11,7 @@ from brian_dashboard_manager.grafana.utils.request import \
def test_admin_request(data_config): def test_admin_request(data_config):
ENDPOINT = 'test/url/endpoint' ENDPOINT = 'test/url/endpoint'
request = AdminRequest(**data_config) request = AdminRequest(**data_config)
url = '{admin_username}:{admin_password}@{hostname}:{grafana_port}/'. \ url = '{admin_username}:{admin_password}@{hostname}/'. \
format(**data_config) format(**data_config)
assert request.BASE_URL == 'http://' + url assert request.BASE_URL == 'http://' + url
assert request.username == data_config['admin_username'] assert request.username == data_config['admin_username']
...@@ -33,7 +33,7 @@ def test_token_request(data_config): ...@@ -33,7 +33,7 @@ def test_token_request(data_config):
TOKEN = '123' TOKEN = '123'
ENDPOINT = 'test/url/endpoint' ENDPOINT = 'test/url/endpoint'
request = TokenRequest(**data_config, token=TOKEN) request = TokenRequest(**data_config, token=TOKEN)
assert request.BASE_URL == 'http://{hostname}:{grafana_port}/'.format( assert request.BASE_URL == 'http://{hostname}/'.format(
**data_config) **data_config)
assert request.token == TOKEN assert request.token == TOKEN
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment