From bf829c21ea4b9666693038d78e76b913262abc7f Mon Sep 17 00:00:00 2001
From: Bjarke Madsen <bjarke.madsen@geant.org>
Date: Tue, 23 Mar 2021 16:20:59 +0100
Subject: [PATCH] Delete dashboards/folders if excluded

---
 brian_dashboard_manager/grafana/provision.py | 64 ++++++++++++++++----
 1 file changed, 51 insertions(+), 13 deletions(-)

diff --git a/brian_dashboard_manager/grafana/provision.py b/brian_dashboard_manager/grafana/provision.py
index bdb0e29..b16f773 100644
--- a/brian_dashboard_manager/grafana/provision.py
+++ b/brian_dashboard_manager/grafana/provision.py
@@ -13,10 +13,12 @@ from brian_dashboard_manager.grafana.organization import \
     get_organizations, create_organization, create_api_token, \
     delete_api_token, delete_expired_api_tokens, set_home_dashboard
 from brian_dashboard_manager.grafana.dashboard import \
-    get_dashboard_definitions, create_dashboard, find_dashboard
+    get_dashboard_definitions, create_dashboard, find_dashboard, \
+    delete_dashboard
 from brian_dashboard_manager.grafana.datasource import \
     check_provisioned, create_datasource
-from brian_dashboard_manager.grafana.folder import find_folder
+from brian_dashboard_manager.grafana.folder import find_folder, \
+    delete_folder
 from brian_dashboard_manager.inventory_provider.interfaces import \
     get_interfaces
 from brian_dashboard_manager.templating.nren_access import generate_nrens
@@ -42,7 +44,8 @@ def generate_all_nrens(token_request, nrens, folder_id, datasource_name):
 
 
 def provision_folder(token_request, folder_name,
-                     dash, excluded_interfaces, datasource_name):
+                     dash, excluded_interfaces, datasource_name,
+                     excluded_dashboards):
 
     folder = find_folder(token_request, folder_name)
 
@@ -59,9 +62,19 @@ def provision_folder(token_request, folder_name,
     data = get_interface_data(relevant_interfaces, parse_func)
     dash_data = get_dashboard_data(data, datasource_name, tag, errors)
 
+    if not isinstance(excluded_dashboards, list):
+        excluded_dashboards = []
+    else:
+        excluded_dashboards = list(
+            map(lambda s: s.lower(), excluded_dashboards))
+
     with ThreadPoolExecutor(max_workers=4) as executor:
         for dashboard in dash_data:
             rendered = render_dashboard(dashboard)
+            if rendered.get('title').lower() in excluded_dashboards:
+                executor.submit(delete_dashboard, token_request,
+                                rendered, folder['id'])
+                continue
             executor.submit(create_dashboard, token_request,
                             rendered, folder['id'])
 
@@ -211,14 +224,25 @@ def provision(config):
         }
         # Provision dashboards, overwriting existing ones.
         datasource_name = datasource.get('name', 'PollerInfluxDB')
+        excluded_folders = org_config.get('excluded_folders', {})
 
         with ProcessPoolExecutor(max_workers=4) as executor:
             for folder_name, dash in dashboards.items():
+                exclude = excluded_folders.get(folder_name)
+                if exclude:
+                    if isinstance(exclude, bool):
+                        # boolean True -> entire folder excluded
+                        # list -> dashboard names not to provision
+                        executor.submit(
+                            delete_folder, token_request, folder_name)
+                        continue
+
                 logger.info(
                     f'Provisioning {org["name"]}/{folder_name} dashboards')
                 executor.submit(provision_folder, token_request,
                                 folder_name, dash,
-                                excluded_interfaces, datasource_name)
+                                excluded_interfaces, datasource_name,
+                                exclude)
 
         aggregate_dashboards = {
             'CLS PEERS': {
@@ -243,15 +267,27 @@ def provision(config):
             }
         }
 
-        with ProcessPoolExecutor(max_workers=4) as executor:
-            aggregate_folder = find_folder(token_request, 'Aggregates')
-            for agg_type, dash in aggregate_dashboards.items():
-                logger.info(
-                    f'Provisioning {org["name"]}' +
-                    f'/Aggregate {agg_type} dashboards')
-                executor.submit(provision_aggregate, token_request, agg_type,
-                                aggregate_folder, dash,
-                                excluded_interfaces, datasource_name)
+        exclude_agg = excluded_folders.get('Aggregates', [])
+
+        if isinstance(exclude_agg, bool) and exclude_agg:
+            # don't provision aggregate folder
+            delete_folder(token_request, 'Aggregates')
+            pass
+        else:
+            with ProcessPoolExecutor(max_workers=4) as executor:
+                agg_folder = find_folder(token_request, 'Aggregates')
+                for agg_type, dash in aggregate_dashboards.items():
+                    if agg_type in exclude_agg:
+                        dash_name = f'Aggregates - {agg_type}'
+                        executor.submit(delete_dashboard,
+                                        token_request, dash_name,
+                                        agg_folder['id'])
+                        continue
+                    logger.info(f'Provisioning {org["name"]}' +
+                                f'/Aggregate {agg_type} dashboards')
+                    executor.submit(provision_aggregate, token_request,
+                                    agg_type, agg_folder, dash,
+                                    excluded_interfaces, datasource_name)
 
         # NREN Access dashboards
         # uses a different template than the above.
@@ -269,6 +305,8 @@ def provision(config):
                 if dashboard['title'].lower() == 'home':
                     dashboard['uid'] = 'home'
                 create_dashboard(token_request, dashboard)
+            else:
+                delete_dashboard(token_request, dashboard)
 
         # Home dashboard is always called "Home"
         # Make sure it's set for the organization
-- 
GitLab