Skip to content
Snippets Groups Projects
Commit f749c757 authored by geant-release-service's avatar geant-release-service
Browse files

Finished release 0.65.

parents 9734c67a 66c3eade
No related branches found
No related tags found
No related merge requests found
......@@ -15,6 +15,7 @@ htmlcov
.tox
dist
docs/build
.coverage*
# logs
*.log
......@@ -6,6 +6,7 @@ Grafana Organization management helpers.
import logging
import random
import string
from requests.exceptions import HTTPError
from datetime import datetime
from typing import Dict, List, Union
......@@ -136,6 +137,78 @@ def delete_expired_api_tokens(request: AdminRequest) -> bool:
return True
def get_or_create_service_account(request: AdminRequest, org_id):
"""
Gets a service account for the given organization, or creates one if it does not exist.
:param request: AdminRequest object
:param org_id: organization ID
:param name: service account name
:return: service account definition
"""
switch_active_organization(request, org_id)
# get provision service account, if it exists
try:
service_accounts = request.get('api/serviceaccounts?perpage=10&page=1&query=provision').json()
if service_accounts and service_accounts.get('totalCount') > 0:
service_account = service_accounts.get('serviceAccounts')[0]
return service_account
except HTTPError as e:
if e.response.status_code != 404:
raise e
# create a service account for provisioning
try:
result = request.post(
'api/serviceaccounts', json={
'name': 'provision',
'role': 'Admin',
'isDisabled': False,
}).json()
except HTTPError as e:
print(e)
logger.info(f'Created provision service account for organization #{org_id}')
return result
def create_service_account_token(request: AdminRequest, service_account_id: int):
"""
Creates a new API token for the given service account.
:param request: AdminRequest object
:param service_account_id: service account ID
:return: Token definition
"""
data = {
'name': f'provision-token-{datetime.now().isoformat()}',
}
result = request.post(f'api/serviceaccounts/{service_account_id}/tokens', json=data).json()
token_id = result.get('id')
logger.debug(f'Created API token #{token_id} for service account #{service_account_id}')
return result
def delete_service_account(request: AdminRequest, service_account_id: int):
"""
Deletes a service account with the given ID.
:param request: AdminRequest object
:param service_account_id: service account ID
:return: delete response
"""
assert service_account_id is not None
result = request.delete(f'api/serviceaccounts/{service_account_id}')
logger.debug(f'Deleted service account #{service_account_id}')
return result
def set_home_dashboard(request: TokenRequest, is_staff):
"""
Sets the home dashboard for the organization
......
......@@ -18,7 +18,8 @@ from brian_dashboard_manager.services.api import fetch_services
from brian_dashboard_manager.grafana.organization import \
get_organizations, create_organization, create_api_token, \
delete_api_token, delete_expired_api_tokens, set_home_dashboard
delete_api_token, delete_expired_api_tokens, set_home_dashboard, \
get_or_create_service_account, delete_service_account, create_service_account_token
from brian_dashboard_manager.grafana.dashboard import list_dashboards, \
get_dashboard_definitions, create_dashboard, delete_dashboard
from brian_dashboard_manager.grafana.datasource import \
......@@ -814,10 +815,13 @@ def provision(config, raise_exceptions=False):
"""
start = time.time()
tokens = []
accounts = []
all_orgs = _provision_orgs(config)
request = AdminRequest(**config)
delete_expired_api_tokens(request)
try:
delete_expired_api_tokens(request)
except Exception:
pass # needed for older versions of grafana
def _find_org_config(org):
orgs_to_provision = config.get('organizations', DEFAULT_ORGANIZATIONS)
......@@ -840,10 +844,17 @@ def provision(config, raise_exceptions=False):
# message logged from _find_org_config
continue
token = create_api_token(request, org_id)
try:
token = create_api_token(request, org_id)
accounts.append((org_id, token))
except Exception:
# create a service account for provisioning (>grafana 11.0)
account = get_or_create_service_account(request, org_id)
token = create_service_account_token(request, account['id'])
accounts.append((org_id, account))
token_request = TokenRequest(token=token['key'], **config)
tokens.append((org_id, token['id']))
logger.debug(tokens)
logger.debug(accounts)
all_original_dashboards = list_dashboards(token_request)
all_original_dashboard_uids = {
......@@ -902,7 +913,11 @@ def provision(config, raise_exceptions=False):
folders_to_keep.update(ignored_folders)
delete_unknown_folders(token_request, folders_to_keep)
delete_api_token(request, token['id'], org_id=org_id)
try:
delete_api_token(request, token['id'], org_id=org_id)
except Exception:
# we're on a newer version of grafana
delete_service_account(request, account['id'])
except Exception:
logger.exception(f'Error when provisioning org {org["name"]}')
if raise_exceptions:
......
......@@ -262,11 +262,17 @@ def create_panel(
def create_infobox():
return {
"datasource": None,
"gridPos": {"h": 1, "w": 24, "x": 0, "y": 0},
"gridPos": {"h": 2, "w": 24, "x": 0, "y": 0},
"id": 1,
"options": {"content": "", "mode": "html"},
"options": {
"content": """
<center style="margin-top:5px;">
INFO: The average values displayed are only mean values for timescales of 2 days or less
</center>""",
"mode": "html"
},
"pluginVersion": "8.2.5",
"title": "INFO: The average values displayed are only mean values for timescales of 2 days or less",
"title": "",
"type": "text",
}
......
......@@ -2,6 +2,9 @@
All notable changes to this project will be documented in this file.
## [0.65] - 2024-09-23
- Support Grafana v11.3 layout & API changes
## [0.64] - 2024-08-14
- POL1-841 - Promote NREN Access Beta and keep Legacy dashboard for GEANT staff
......
......@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name='brian-dashboard-manager',
version="0.64",
version="0.65",
author='GEANT',
author_email='swd@geant.org',
description='',
......
......@@ -778,7 +778,7 @@ def test_provision_re_peer_dashboard(
panels = mock_grafana.dashboards_by_folder_uid[folder_uid][0]["panels"]
expected_types = ["text", "graph", "graph", "row", "graph", "graph", "row"]
assert [p["type"] for p in panels] == expected_types
assert "INFO" in panels[0]["title"]
assert "INFO" in panels[0]["options"]["content"]
assert "ingress" in panels[1]["title"]
assert "egress" in panels[2]["title"]
assert "Services" in panels[3]["title"]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment