From 62821d5d62d5313a797c3fd6907a4380d856c207 Mon Sep 17 00:00:00 2001 From: ysde Date: Wed, 6 Sep 2023 13:57:39 +0800 Subject: [PATCH 1/4] contact points and notifcation policy backup --- README.md | 3 +- ...mple.json => grafanaSettings.example.json} | 0 grafana_backup/api_checks.py | 6 +- grafana_backup/archive.py | 2 +- grafana_backup/create_contact_point.py | 33 ++++++++++ grafana_backup/dashboardApi.py | 21 ++++++- grafana_backup/delete.py | 1 + grafana_backup/restore.py | 10 +++- grafana_backup/save.py | 26 +++++--- grafana_backup/save_contact_points.py | 60 +++++++++++++++++++ grafana_backup/save_notification_policies.py | 58 ++++++++++++++++++ grafana_backup/update_notification_policy.py | 32 ++++++++++ 12 files changed, 238 insertions(+), 14 deletions(-) rename examples/{grafana-backup.example.json => grafanaSettings.example.json} (100%) create mode 100644 grafana_backup/create_contact_point.py create mode 100644 grafana_backup/save_contact_points.py create mode 100644 grafana_backup/save_notification_policies.py create mode 100644 grafana_backup/update_notification_policy.py diff --git a/README.md b/README.md index 7ddb40e1..a5e5063a 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,8 @@ There are three ways to setup the configuration: 3. Use `~/.grafana-backup.json` to define variables in json format. ### Example Config -* Check out the [examples](examples) folder for more configuration details +* Copy [grafanaSettings.example.json](examples/grafanaSettings.example.json) and modify it for you to use, remove `azure`, `aws`, `gcp`, `influxdb` blocks (but keep the ones you used). +* Check out the [examples](examples) folder for more configuration details. **NOTE** If you use `environment variables`, you need to add the following to your `.bashrc` or execute once before using the tool (please change variables according to your setup): diff --git a/examples/grafana-backup.example.json b/examples/grafanaSettings.example.json similarity index 100% rename from examples/grafana-backup.example.json rename to examples/grafanaSettings.example.json diff --git a/grafana_backup/api_checks.py b/grafana_backup/api_checks.py index 2c1cd966..51591a54 100644 --- a/grafana_backup/api_checks.py +++ b/grafana_backup/api_checks.py @@ -1,5 +1,5 @@ from grafana_backup.commons import print_horizontal_line -from grafana_backup.dashboardApi import health_check, auth_check, uid_feature_check, paging_feature_check +from grafana_backup.dashboardApi import health_check, auth_check, uid_feature_check, paging_feature_check, contact_point_check def main(settings): @@ -30,6 +30,8 @@ def main(settings): paging_support = paging_feature_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug) if isinstance(paging_support, str): raise Exception(paging_support) + + is_contact_point_available = contact_point_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug) print_horizontal_line() if status == 200: @@ -38,4 +40,4 @@ def main(settings): print("[Pre-Check] Server status is NOT OK !!: {0}".format(json_resp)) print_horizontal_line() - return (status, json_resp, dashboard_uid_support, datasource_uid_support, paging_support) + return (status, json_resp, dashboard_uid_support, datasource_uid_support, paging_support, is_contact_point_available) diff --git a/grafana_backup/archive.py b/grafana_backup/archive.py index 1db698ac..2c61e63b 100755 --- a/grafana_backup/archive.py +++ b/grafana_backup/archive.py @@ -10,7 +10,7 @@ def main(args, settings): backup_files = list() for folder_name in ['folders', 'datasources', 'dashboards', 'alert_channels', 'organizations', 'users', 'snapshots', - 'dashboard_versions', 'annotations', 'library-elements', 'teams', 'team_members', 'alert_rules']: + 'dashboard_versions', 'annotations', 'library-elements', 'teams', 'team_members', 'alert_rules', 'contact_points', 'notification_policies']: backup_path = '{0}/{1}/{2}'.format(backup_dir, folder_name, timestamp) for file_path in glob(backup_path): diff --git a/grafana_backup/create_contact_point.py b/grafana_backup/create_contact_point.py new file mode 100644 index 00000000..f6ee81e9 --- /dev/null +++ b/grafana_backup/create_contact_point.py @@ -0,0 +1,33 @@ +import json +from grafana_backup.dashboardApi import create_contact_point, get_grafana_version +from packaging import version + +def main(args, settings, file_path): + grafana_url = settings.get('GRAFANA_URL') + http_post_headers = settings.get('HTTP_POST_HEADERS') + verify_ssl = settings.get('VERIFY_SSL') + client_cert = settings.get('CLIENT_CERT') + debug = settings.get('DEBUG') + + try: + grafana_version = get_grafana_version(grafana_url, verify_ssl) + except KeyError as error: + if not grafana_version: + raise Exception("Grafana version is not set.") from error + + minimum_version = version.parse('9.4.0') + + if minimum_version <= grafana_version: + with open(file_path, 'r') as f: + data = f.read() + + contact_points = json.loads(data) + for cp in contact_points: + result = create_contact_point(json.dumps(cp), grafana_url, http_post_headers, verify_ssl, client_cert, debug) + print("create contact_point: {0}, status: {1}, msg: {2}".format(cp['name'], result[0], result[1])) + else: + print("Unable to create contact points, requires Grafana version {0} or above. Current version is {1}".format(minimum_version, grafana_version)) + + + + diff --git a/grafana_backup/dashboardApi.py b/grafana_backup/dashboardApi.py index 58d7d8d7..cd1ee121 100755 --- a/grafana_backup/dashboardApi.py +++ b/grafana_backup/dashboardApi.py @@ -71,6 +71,14 @@ def get_first_dashboard_by_page(page): # No dashboards exist, disable paging feature return False, False +def contact_point_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug): + print("\n[Pre-Check] grafana contact_point api check") + (status, content) = search_contact_points(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + if status == 200: + return True + else: + return False + # Get first dashboard on first page (status, content) = get_first_dashboard_by_page(1) if status is False and content is False: @@ -92,7 +100,6 @@ def get_first_dashboard_by_page(page): # Compare both pages return dashboard_one_values != dashboard_two_values - def search_dashboard(page, limit, grafana_url, http_get_headers, verify_ssl, client_cert, debug): url = '{0}/api/search/?type=dash-db&limit={1}&page={2}'.format(grafana_url, limit, page) print("search dashboard in grafana: {0}".format(url)) @@ -434,6 +441,18 @@ def add_user_to_org(org_id, payload, grafana_url, http_post_headers, verify_ssl, return send_grafana_post('{0}/api/orgs/{1}/users'.format(grafana_url, org_id), payload, http_post_headers, verify_ssl, client_cert, debug) +def search_contact_points(grafana_url, http_get_headers, verify_ssl, client_cert, debug): + return send_grafana_get('{0}/api/v1/provisioning/contact-points'.format(grafana_url), http_get_headers, verify_ssl, client_cert, debug) + +def create_contact_point(json_palyload, grafana_url, http_post_headers, verify_ssl, client_cert, debug): + return send_grafana_post('{0}/api/v1/provisioning/contact-points'.format(grafana_url), json_palyload, http_post_headers, verify_ssl, client_cert, debug) + +def search_notification_policies(grafana_url, http_get_headers, verify_ssl, client_cert, debug): + return send_grafana_get('{0}/api/v1/provisioning/policies'.format(grafana_url), http_get_headers, verify_ssl, client_cert, debug) + +def update_notification_policy(json_palyload, grafana_url, http_post_headers, verify_ssl, client_cert, debug): + return send_grafana_put('{0}/api/v1/provisioning/policies'.format(grafana_url), json_palyload, http_post_headers, verify_ssl, client_cert, debug) + def get_grafana_version(grafana_url, verify_ssl, http_get_headers): r = requests.get('{0}/api/health'.format(grafana_url), verify=verify_ssl, headers=http_get_headers) if r.status_code == 200: diff --git a/grafana_backup/delete.py b/grafana_backup/delete.py index f6104e3f..866aeccb 100755 --- a/grafana_backup/delete.py +++ b/grafana_backup/delete.py @@ -34,6 +34,7 @@ def main(args, settings): settings.update({'DASHBOARD_UID_SUPPORT': dashboard_uid_support}) settings.update({'DATASOURCE_UID_SUPPORT': datasource_uid_support}) settings.update({'PAGING_SUPPORT': paging_support}) + if arg_components: arg_components_list = arg_components.split(',') diff --git a/grafana_backup/restore.py b/grafana_backup/restore.py index 01c7c07c..c148c469 100755 --- a/grafana_backup/restore.py +++ b/grafana_backup/restore.py @@ -12,6 +12,8 @@ from grafana_backup.create_team import main as create_team from grafana_backup.create_team_member import main as create_team_member from grafana_backup.create_library_element import main as create_library_element +from grafana_backup.create_contact_point import main as create_contact_point +from grafana_backup.update_notification_policy import main as update_notification_policy from grafana_backup.s3_download import main as s3_download from grafana_backup.azure_storage_download import main as azure_storage_download from grafana_backup.gcs_download import main as gcs_download @@ -39,7 +41,8 @@ def open_compressed_backup(compressed_backup): azure_storage_container_name = settings.get('AZURE_STORAGE_CONTAINER_NAME') gcs_bucket_name = settings.get('GCS_BUCKET_NAME') - (status, json_resp, dashboard_uid_support, datasource_uid_support, paging_support) = api_checks(settings) + (status, json_resp, dashboard_uid_support, datasource_uid_support, paging_support, contact_point_support) = api_checks(settings) + settings.update({'CONTACT_POINT_SUPPORT': contact_point_support}) # Do not continue if API is unavailable or token is not valid if not status == 200: @@ -90,6 +93,9 @@ def open_compressed_backup(compressed_backup): restore_functions['team_member'] = create_team_member restore_functions['folder_permission'] = update_folder_permissions restore_functions['alert_rule'] = create_alert_rule + restore_functions['contact_point'] = create_contact_point + # There are some issues of notification policy restore api, it will lock the notification policy page and cannot be edited. + # restore_functions['notification_policys'] = update_notification_policy if sys.version_info >= (3,): with tempfile.TemporaryDirectory() as tmpdir: @@ -108,7 +114,7 @@ def open_compressed_backup(compressed_backup): def restore_components(args, settings, restore_functions, tmpdir): - arg_components = args.get('--components', False) + arg_components = args.get('--components', []) if arg_components: arg_components_list = arg_components.replace("-", "_").split(',') diff --git a/grafana_backup/save.py b/grafana_backup/save.py index f7e5b2a5..d95c7855 100755 --- a/grafana_backup/save.py +++ b/grafana_backup/save.py @@ -7,6 +7,8 @@ from grafana_backup.save_snapshots import main as save_snapshots from grafana_backup.save_dashboard_versions import main as save_dashboard_versions from grafana_backup.save_annotations import main as save_annotations +from grafana_backup.save_contact_points import main as save_contact_points +from grafana_backup.save_notification_policies import main as save_notification_policies from grafana_backup.archive import main as archive from grafana_backup.s3_upload import main as s3_upload from grafana_backup.influx import main as influx @@ -17,6 +19,7 @@ from grafana_backup.save_team_members import main as save_team_members from grafana_backup.azure_storage_upload import main as azure_storage_upload from grafana_backup.gcs_upload import main as gcs_upload +from grafana_backup.commons import print_horizontal_line import sys @@ -37,19 +40,28 @@ def main(args, settings): 'library-elements': save_library_elements, 'teams': save_teams, 'team-members': save_team_members, - 'alert-rules': save_alert_rules} + 'alert-rules': save_alert_rules, + 'contact-points': save_contact_points, + 'notification-policy': save_notification_policies, + } - (status, json_resp, dashboard_uid_support, datasource_uid_support, paging_support) = api_checks(settings) + (status, + json_resp, + dashboard_uid_support, + datasource_uid_support, + paging_support, + contact_point_support) = api_checks(settings) + + settings.update({'DASHBOARD_UID_SUPPORT': dashboard_uid_support}) + settings.update({'DATASOURCE_UID_SUPPORT': datasource_uid_support}) + settings.update({'PAGING_SUPPORT': paging_support}) + settings.update({'CONTACT_POINT_SUPPORT': contact_point_support}) # Do not continue if API is unavailable or token is not valid if not status == 200: - print("server status is not ok: {0}".format(json_resp)) + print("grafana server status is not ok: {0}".format(json_resp)) sys.exit(1) - settings.update({'DASHBOARD_UID_SUPPORT': dashboard_uid_support}) - settings.update({'DATASOURCE_UID_SUPPORT': datasource_uid_support}) - settings.update({'PAGING_SUPPORT': paging_support}) - if arg_components: arg_components_list = arg_components.replace("_", "-").split(',') diff --git a/grafana_backup/save_contact_points.py b/grafana_backup/save_contact_points.py new file mode 100644 index 00000000..53f70171 --- /dev/null +++ b/grafana_backup/save_contact_points.py @@ -0,0 +1,60 @@ +import os +from grafana_backup.dashboardApi import search_contact_points, get_grafana_version +from grafana_backup.commons import to_python2_and_3_compatible_string, print_horizontal_line, save_json +from packaging import version + +def main(args, settings): + backup_dir = settings.get('BACKUP_DIR') + timestamp = settings.get('TIMESTAMP') + grafana_url = settings.get('GRAFANA_URL') + http_get_headers = settings.get('HTTP_GET_HEADERS') + verify_ssl = settings.get('VERIFY_SSL') + client_cert = settings.get('CLIENT_CERT') + debug = settings.get('DEBUG') + pretty_print = settings.get('PRETTY_PRINT') + folder_path = '{0}/contact_points/{1}'.format(backup_dir, timestamp) + log_file = 'contact_points_{0}.txt'.format(timestamp) + grafana_version_string = settings.get('GRAFANA_VERSION') + + if grafana_version_string: + grafana_version = version.parse(grafana_version_string) + + try: + grafana_version = get_grafana_version(grafana_url, verify_ssl) + except KeyError as error: + if not grafana_version: + raise Exception("Grafana version is not set.") from error + + minimum_version = version.parse('9.0.0') + if minimum_version <= grafana_version: + if not os.path.exists(folder_path): + os.makedirs(folder_path) + + contact_points = get_all_contact_points_in_grafana(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + save_contact_points('contact_points', contact_points, folder_path, pretty_print) + else: + print("Unable to save contact points, requires Grafana version {0} or above. Current version is {1}".format(minimum_version, grafana_version)) + + + if not os.path.exists(folder_path): + os.makedirs(folder_path) + + +def get_all_contact_points_in_grafana(grafana_url, http_get_headers, verify_ssl, client_cert, debug): + (status, content) = search_contact_points(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + if status == 200: + contact_points = content + print("There are {0} contact points: ".format(len(contact_points))) + for contact_point in contact_points: + print("name: {0}, type: {1}".format(to_python2_and_3_compatible_string(contact_point['name']), to_python2_and_3_compatible_string(contact_point['type']))) + return contact_points + else: + print("query contact points failed, status: {0}, msg: {1}".format(status, content)) + return [] + + +def save_contact_points(file_name, contact_points, folder_path, pretty_print): + file_path = save_json(file_name, contact_points, folder_path, 'contact_point', pretty_print) + print_horizontal_line() + print("contact points are saved to {0}".format(file_path)) + print_horizontal_line() diff --git a/grafana_backup/save_notification_policies.py b/grafana_backup/save_notification_policies.py new file mode 100644 index 00000000..7655878c --- /dev/null +++ b/grafana_backup/save_notification_policies.py @@ -0,0 +1,58 @@ +import os +from grafana_backup.dashboardApi import search_notification_policies, get_grafana_version +from grafana_backup.commons import to_python2_and_3_compatible_string, print_horizontal_line, save_json +from packaging import version + +def main(args, settings): + backup_dir = settings.get('BACKUP_DIR') + timestamp = settings.get('TIMESTAMP') + grafana_url = settings.get('GRAFANA_URL') + http_get_headers = settings.get('HTTP_GET_HEADERS') + verify_ssl = settings.get('VERIFY_SSL') + client_cert = settings.get('CLIENT_CERT') + debug = settings.get('DEBUG') + pretty_print = settings.get('PRETTY_PRINT') + folder_path = '{0}/notification_policies/{1}'.format(backup_dir, timestamp) + log_file = 'notification_policies_{0}.txt'.format(timestamp) + grafana_version_string = settings.get('GRAFANA_VERSION') + + if grafana_version_string: + grafana_version = version.parse(grafana_version_string) + + try: + grafana_version = get_grafana_version(grafana_url, verify_ssl) + except KeyError as error: + if not grafana_version: + raise Exception("Grafana version is not set.") from error + + minimum_version = version.parse('9.0.0') + if minimum_version <= grafana_version: + if not os.path.exists(folder_path): + os.makedirs(folder_path) + + notification_policies = get_all_notification_policies_in_grafana(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + save_notification_policies('notificatioin_policies', notification_policies, folder_path, pretty_print) + else: + print("Unable to save notification policies, requires Grafana version {0} or above. Current version is {1}".format(minimum_version, grafana_version)) + + + if not os.path.exists(folder_path): + os.makedirs(folder_path) + + +def get_all_notification_policies_in_grafana(grafana_url, http_get_headers, verify_ssl, client_cert, debug): + (status, content) = search_notification_policies(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + if status == 200: + notification_policies = content + print("Notification policies found") + return notification_policies + else: + print("query notification policies failed, status: {0}, msg: {1}".format(status, content)) + return [] + + +def save_notification_policies(file_name, notification_policies, folder_path, pretty_print): + file_path = save_json(file_name, notification_policies, folder_path, 'notification_policys', pretty_print) + print_horizontal_line() + print("notification policies are saved to {0}".format(file_path)) + print_horizontal_line() diff --git a/grafana_backup/update_notification_policy.py b/grafana_backup/update_notification_policy.py new file mode 100644 index 00000000..4072f26a --- /dev/null +++ b/grafana_backup/update_notification_policy.py @@ -0,0 +1,32 @@ +import json +from grafana_backup.dashboardApi import update_notification_policy, get_grafana_version +from packaging import version + +def main(args, settings, file_path): + grafana_url = settings.get('GRAFANA_URL') + http_post_headers = settings.get('HTTP_POST_HEADERS') + verify_ssl = settings.get('VERIFY_SSL') + client_cert = settings.get('CLIENT_CERT') + debug = settings.get('DEBUG') + + try: + grafana_version = get_grafana_version(grafana_url, verify_ssl) + except KeyError as error: + if not grafana_version: + raise Exception("Grafana version is not set.") from error + + minimum_version = version.parse('9.4.0') + + if minimum_version <= grafana_version: + with open(file_path, 'r') as f: + data = f.read() + + notification_policies = json.loads(data) + result = update_notification_policy(json.dumps(notification_policies), grafana_url, http_post_headers, verify_ssl, client_cert, debug) + print("update notification_policy, status: {0}, msg: {1}".format(result[0], result[1])) + else: + print("Unable to update notification policy, requires Grafana version {0} or above. Current version is {1}".format(minimum_version, grafana_version)) + + + + From 44204c225973df744522bcbbcd5a0e418a1c3b94 Mon Sep 17 00:00:00 2001 From: Aaron Johnson Date: Wed, 20 Sep 2023 16:41:29 -0500 Subject: [PATCH 2/4] autopep8 add_support_for_contact_point_and_notification --- grafana_backup/api_checks.py | 17 +-- grafana_backup/archive.py | 4 +- grafana_backup/create_contact_point.py | 14 +-- grafana_backup/dashboardApi.py | 105 +++++++++++++------ grafana_backup/delete.py | 4 +- grafana_backup/restore.py | 11 +- grafana_backup/save.py | 14 +-- grafana_backup/save_contact_points.py | 25 +++-- grafana_backup/save_notification_policies.py | 22 ++-- grafana_backup/update_notification_policy.py | 14 +-- 10 files changed, 145 insertions(+), 85 deletions(-) diff --git a/grafana_backup/api_checks.py b/grafana_backup/api_checks.py index 51591a54..490c889a 100644 --- a/grafana_backup/api_checks.py +++ b/grafana_backup/api_checks.py @@ -12,26 +12,31 @@ def main(settings): api_auth_check = settings.get('API_AUTH_CHECK') if api_health_check: - (status, json_resp) = health_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + (status, json_resp) = health_check(grafana_url, + http_get_headers, verify_ssl, client_cert, debug) if not status == 200: return (status, json_resp, None, None, None) if api_auth_check: - (status, json_resp) = auth_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + (status, json_resp) = auth_check(grafana_url, + http_get_headers, verify_ssl, client_cert, debug) if not status == 200: return (status, json_resp, None, None, None) - dashboard_uid_support, datasource_uid_support = uid_feature_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + dashboard_uid_support, datasource_uid_support = uid_feature_check( + grafana_url, http_get_headers, verify_ssl, client_cert, debug) if isinstance(dashboard_uid_support, str): raise Exception(dashboard_uid_support) if isinstance(datasource_uid_support, str): raise Exception(datasource_uid_support) - paging_support = paging_feature_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + paging_support = paging_feature_check( + grafana_url, http_get_headers, verify_ssl, client_cert, debug) if isinstance(paging_support, str): raise Exception(paging_support) - - is_contact_point_available = contact_point_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + + is_contact_point_available = contact_point_check( + grafana_url, http_get_headers, verify_ssl, client_cert, debug) print_horizontal_line() if status == 200: diff --git a/grafana_backup/archive.py b/grafana_backup/archive.py index 2c61e63b..1744e764 100755 --- a/grafana_backup/archive.py +++ b/grafana_backup/archive.py @@ -1,5 +1,7 @@ from glob import glob -import os, tarfile, shutil +import os +import tarfile +import shutil def main(args, settings): diff --git a/grafana_backup/create_contact_point.py b/grafana_backup/create_contact_point.py index f6ee81e9..d0a184a9 100644 --- a/grafana_backup/create_contact_point.py +++ b/grafana_backup/create_contact_point.py @@ -2,6 +2,7 @@ from grafana_backup.dashboardApi import create_contact_point, get_grafana_version from packaging import version + def main(args, settings, file_path): grafana_url = settings.get('GRAFANA_URL') http_post_headers = settings.get('HTTP_POST_HEADERS') @@ -23,11 +24,10 @@ def main(args, settings, file_path): contact_points = json.loads(data) for cp in contact_points: - result = create_contact_point(json.dumps(cp), grafana_url, http_post_headers, verify_ssl, client_cert, debug) - print("create contact_point: {0}, status: {1}, msg: {2}".format(cp['name'], result[0], result[1])) + result = create_contact_point(json.dumps( + cp), grafana_url, http_post_headers, verify_ssl, client_cert, debug) + print("create contact_point: {0}, status: {1}, msg: {2}".format( + cp['name'], result[0], result[1])) else: - print("Unable to create contact points, requires Grafana version {0} or above. Current version is {1}".format(minimum_version, grafana_version)) - - - - + print("Unable to create contact points, requires Grafana version {0} or above. Current version is {1}".format( + minimum_version, grafana_version)) diff --git a/grafana_backup/dashboardApi.py b/grafana_backup/dashboardApi.py index cd1ee121..ce8232a8 100755 --- a/grafana_backup/dashboardApi.py +++ b/grafana_backup/dashboardApi.py @@ -21,7 +21,8 @@ def auth_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug): def uid_feature_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug): # Get first dashboard on first page print("\n[Pre-Check] grafana uid feature check: calling 'search_dashboard'") - (status, content) = search_dashboard(1, 1, grafana_url, http_get_headers, verify_ssl, client_cert, debug) + (status, content) = search_dashboard(1, 1, grafana_url, + http_get_headers, verify_ssl, client_cert, debug) if status == 200 and len(content): if 'uid' in content[0]: dashboard_uid_support = True @@ -29,13 +30,15 @@ def uid_feature_check(grafana_url, http_get_headers, verify_ssl, client_cert, de dashboard_uid_support = False else: if len(content): - dashboard_uid_support = "get dashboards failed, status: {0}, msg: {1}".format(status, content) + dashboard_uid_support = "get dashboards failed, status: {0}, msg: {1}".format( + status, content) else: # No dashboards exist, disable uid feature dashboard_uid_support = False # Get first datasource print("\n[Pre-Check] grafana uid feature check: calling 'search_datasource'") - (status, content) = search_datasource(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + (status, content) = search_datasource(grafana_url, + http_get_headers, verify_ssl, client_cert, debug) if status == 200 and len(content): if 'uid' in content[0]: datasource_uid_support = True @@ -43,7 +46,8 @@ def uid_feature_check(grafana_url, http_get_headers, verify_ssl, client_cert, de datasource_uid_support = False else: if len(content): - datasource_uid_support = "get datasources failed, status: {0}, msg: {1}".format(status, content) + datasource_uid_support = "get datasources failed, status: {0}, msg: {1}".format( + status, content) else: # No datasources exist, disable uid feature datasource_uid_support = False @@ -55,14 +59,19 @@ def paging_feature_check(grafana_url, http_get_headers, verify_ssl, client_cert, print("\n[Pre-Check] grafana paging_feature_check: calling 'search_dashboard'") def get_first_dashboard_by_page(page): - (status, content) = search_dashboard(page, 1, grafana_url, http_get_headers, verify_ssl, client_cert, debug) + (status, content) = search_dashboard(page, 1, grafana_url, + http_get_headers, verify_ssl, client_cert, debug) if status == 200 and len(content): if sys.version_info[0] > 2: - content[0] = {k: to_python2_and_3_compatible_string(v) for k,v in content[0].items()} - dashboard_values = sorted(content[0].items(), key=lambda kv: str(kv[1])) + content[0] = {k: to_python2_and_3_compatible_string( + v) for k, v in content[0].items()} + dashboard_values = sorted( + content[0].items(), key=lambda kv: str(kv[1])) else: - content[0] = {k: to_python2_and_3_compatible_string(unicode(v)) for k,v in content[0].iteritems()} - dashboard_values = sorted(content[0].iteritems(), key=lambda kv: str(kv[1])) + content[0] = {k: to_python2_and_3_compatible_string( + unicode(v)) for k, v in content[0].iteritems()} + dashboard_values = sorted( + content[0].iteritems(), key=lambda kv: str(kv[1])) return True, dashboard_values else: if len(content): @@ -71,9 +80,11 @@ def get_first_dashboard_by_page(page): # No dashboards exist, disable paging feature return False, False + def contact_point_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug): print("\n[Pre-Check] grafana contact_point api check") - (status, content) = search_contact_points(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + (status, content) = search_contact_points( + grafana_url, http_get_headers, verify_ssl, client_cert, debug) if status == 200: return True else: @@ -100,8 +111,10 @@ def contact_point_check(grafana_url, http_get_headers, verify_ssl, client_cert, # Compare both pages return dashboard_one_values != dashboard_two_values + def search_dashboard(page, limit, grafana_url, http_get_headers, verify_ssl, client_cert, debug): - url = '{0}/api/search/?type=dash-db&limit={1}&page={2}'.format(grafana_url, limit, page) + url = '{0}/api/search/?type=dash-db&limit={1}&page={2}'.format( + grafana_url, limit, page) print("search dashboard in grafana: {0}".format(url)) return send_grafana_get(url, http_get_headers, verify_ssl, client_cert, debug) @@ -109,7 +122,8 @@ def search_dashboard(page, limit, grafana_url, http_get_headers, verify_ssl, cli def get_dashboard(board_uri, grafana_url, http_get_headers, verify_ssl, client_cert, debug): url = '{0}/api/dashboards/{1}'.format(grafana_url, board_uri) print("query dashboard uri: {0}".format(url)) - (status_code, content) = send_grafana_get(url, http_get_headers, verify_ssl, client_cert, debug) + (status_code, content) = send_grafana_get( + url, http_get_headers, verify_ssl, client_cert, debug) return (status_code, content) @@ -126,7 +140,7 @@ def create_library_element(library_element, grafana_url, http_post_headers, veri def delete_library_element(id_, grafana_url, http_get_headers, verify_ssl, client_cert, debug): return send_grafana_delete('{0}/api/library-elements/{1}'.format(grafana_url, id_), http_get_headers, - verify_ssl, client_cert) + verify_ssl, client_cert) def search_teams(grafana_url, http_get_headers, verify_ssl, client_cert, debug): @@ -142,7 +156,7 @@ def create_team(team, grafana_url, http_post_headers, verify_ssl, client_cert, d def delete_team(id_, grafana_url, http_get_headers, verify_ssl, client_cert, debug): return send_grafana_delete('{0}/api/teams/{1}'.format(grafana_url, id_), http_get_headers, - verify_ssl, client_cert) + verify_ssl, client_cert) def search_team_members(team_id, grafana_url, http_get_headers, verify_ssl, client_cert, debug): @@ -158,15 +172,17 @@ def create_team_member(user, team_id, grafana_url, http_post_headers, verify_ssl def delete_team_member(user_id, team_id, grafana_url, http_get_headers, verify_ssl, client_cert, debug): return send_grafana_delete('{0}/api/teams/{1}/members/{2}'.format(grafana_url, team_id, user_id), http_get_headers, - verify_ssl, client_cert) + verify_ssl, client_cert) def search_annotations(grafana_url, ts_from, ts_to, http_get_headers, verify_ssl, client_cert, debug): # there are two types of annotations # annotation: are user created, custom ones and can be managed via the api # alert: are created by Grafana itself, can NOT be managed by the api - url = '{0}/api/annotations?type=annotation&limit=5000&from={1}&to={2}'.format(grafana_url, ts_from, ts_to) - (status_code, content) = send_grafana_get(url, http_get_headers, verify_ssl, client_cert, debug) + url = '{0}/api/annotations?type=annotation&limit=5000&from={1}&to={2}'.format( + grafana_url, ts_from, ts_to) + (status_code, content) = send_grafana_get( + url, http_get_headers, verify_ssl, client_cert, debug) return (status_code, content) @@ -229,25 +245,27 @@ def delete_alert_channel_by_id(id_, grafana_url, http_post_headers, verify_ssl, def search_alerts(grafana_url, http_get_headers, verify_ssl, client_cert, debug): url = '{0}/api/alerts'.format(grafana_url) - (status_code, content) = send_grafana_get(url, http_get_headers, verify_ssl, client_cert, debug) + (status_code, content) = send_grafana_get( + url, http_get_headers, verify_ssl, client_cert, debug) return (status_code, content) def pause_alert(id_, grafana_url, http_post_headers, verify_ssl, client_cert, debug): url = '{0}/api/alerts/{1}/pause'.format(grafana_url, id_) payload = '{ "paused": true }' - (status_code, content) = send_grafana_post(url, payload, http_post_headers, verify_ssl, client_cert, debug) + (status_code, content) = send_grafana_post( + url, payload, http_post_headers, verify_ssl, client_cert, debug) return (status_code, content) def unpause_alert(id_, grafana_url, http_post_headers, verify_ssl, client_cert, debug): url = '{0}/api/alerts/{1}/pause'.format(grafana_url, id_) payload = '{ "paused": false }' - (status_code, content) = send_grafana_post(url, payload, http_post_headers, verify_ssl, client_cert, debug) + (status_code, content) = send_grafana_post( + url, payload, http_post_headers, verify_ssl, client_cert, debug) return (status_code, content) - def delete_folder(uid, grafana_url, http_post_headers, verify_ssl, client_cert, debug): return send_grafana_delete('{0}/api/folders/{1}'.format(grafana_url, uid), http_post_headers, verify_ssl, client_cert, debug) @@ -285,7 +303,8 @@ def search_snapshot(grafana_url, http_get_headers, verify_ssl, client_cert, debu def get_snapshot(key, grafana_url, http_get_headers, verify_ssl, client_cert, debug): url = '{0}/api/snapshots/{1}'.format(grafana_url, key) - (status_code, content) = send_grafana_get(url, http_get_headers, verify_ssl, client_cert, debug) + (status_code, content) = send_grafana_get( + url, http_get_headers, verify_ssl, client_cert, debug) return (status_code, content) @@ -340,7 +359,8 @@ def get_folder_id(dashboard, grafana_url, http_post_headers, verify_ssl, client_ try: folder_uid = dashboard['meta']['folderUid'] except (KeyError): - matches = re.search('dashboards\/f\/(.*)\/.*', dashboard['meta']['folderUrl']) + matches = re.search('dashboards\/f\/(.*)\/.*', + dashboard['meta']['folderUrl']) if matches is not None: folder_uid = matches.group(1) else: @@ -348,7 +368,8 @@ def get_folder_id(dashboard, grafana_url, http_post_headers, verify_ssl, client_ if (folder_uid != ""): print("debug: quering with uid {}".format(folder_uid)) - response = get_folder(folder_uid, grafana_url, http_post_headers, verify_ssl, client_cert, debug) + response = get_folder(folder_uid, grafana_url, + http_post_headers, verify_ssl, client_cert, debug) if isinstance(response[1], dict): folder_data = response[1] else: @@ -370,14 +391,16 @@ def create_folder(payload, grafana_url, http_post_headers, verify_ssl, client_ce def get_dashboard_versions(dashboard_id, grafana_url, http_get_headers, verify_ssl, client_cert, debug): (status_code, content) = send_grafana_get('{0}/api/dashboards/id/{1}/versions'.format(grafana_url, dashboard_id), http_get_headers, verify_ssl, client_cert, debug) - print("query dashboard versions: {0}, status: {1}".format(dashboard_id, status_code)) + print("query dashboard versions: {0}, status: {1}".format( + dashboard_id, status_code)) return (status_code, content) def get_version(dashboard_id, version_number, grafana_url, http_get_headers, verify_ssl, client_cert, debug): (status_code, content) = send_grafana_get('{0}/api/dashboards/id/{1}/versions/{2}'.format(grafana_url, dashboard_id, version_number), http_get_headers, verify_ssl, client_cert, debug) - print("query dashboard {0} version {1}, status: {2}".format(dashboard_id, version_number, status_code)) + print("query dashboard {0} version {1}, status: {2}".format( + dashboard_id, version_number, status_code)) return (status_code, content) @@ -413,7 +436,8 @@ def get_users(grafana_url, http_get_headers, verify_ssl, client_cert, debug): def set_user_role(user_id, role, grafana_url, http_post_headers, verify_ssl, client_cert, debug): json_payload = json.dumps({'role': role}) url = '{0}/api/org/users/{1}'.format(grafana_url, user_id) - r = requests.patch(url, headers=http_post_headers, data=json_payload, verify=verify_ssl, cert=client_cert) + r = requests.patch(url, headers=http_post_headers, + data=json_payload, verify=verify_ssl, cert=client_cert) return (r.status_code, r.json()) @@ -441,20 +465,26 @@ def add_user_to_org(org_id, payload, grafana_url, http_post_headers, verify_ssl, return send_grafana_post('{0}/api/orgs/{1}/users'.format(grafana_url, org_id), payload, http_post_headers, verify_ssl, client_cert, debug) + def search_contact_points(grafana_url, http_get_headers, verify_ssl, client_cert, debug): return send_grafana_get('{0}/api/v1/provisioning/contact-points'.format(grafana_url), http_get_headers, verify_ssl, client_cert, debug) + def create_contact_point(json_palyload, grafana_url, http_post_headers, verify_ssl, client_cert, debug): return send_grafana_post('{0}/api/v1/provisioning/contact-points'.format(grafana_url), json_palyload, http_post_headers, verify_ssl, client_cert, debug) + def search_notification_policies(grafana_url, http_get_headers, verify_ssl, client_cert, debug): return send_grafana_get('{0}/api/v1/provisioning/policies'.format(grafana_url), http_get_headers, verify_ssl, client_cert, debug) + def update_notification_policy(json_palyload, grafana_url, http_post_headers, verify_ssl, client_cert, debug): return send_grafana_put('{0}/api/v1/provisioning/policies'.format(grafana_url), json_palyload, http_post_headers, verify_ssl, client_cert, debug) + def get_grafana_version(grafana_url, verify_ssl, http_get_headers): - r = requests.get('{0}/api/health'.format(grafana_url), verify=verify_ssl, headers=http_get_headers) + r = requests.get('{0}/api/health'.format(grafana_url), + verify=verify_ssl, headers=http_get_headers) if r.status_code == 200: if 'version' in r.json().keys(): version_str = r.json()['version'] @@ -465,23 +495,29 @@ def get_grafana_version(grafana_url, verify_ssl, http_get_headers): if match: version_number = match.group(1) else: - raise Exception("version key found but string value could not be parsed, returned respone: {0}".format(r.json)) + raise Exception( + "version key found but string value could not be parsed, returned respone: {0}".format(r.json)) return version.parse(version_number) else: - raise KeyError("Unable to get version, returned respone: {0}".format(r.json)) + raise KeyError( + "Unable to get version, returned respone: {0}".format(r.json)) else: - raise Exception("Unable to get version, returned response: {0}".format(r.status_code)) + raise Exception( + "Unable to get version, returned response: {0}".format(r.status_code)) + def send_grafana_get(url, http_get_headers, verify_ssl, client_cert, debug): - r = requests.get(url, headers=http_get_headers, verify=verify_ssl, cert=client_cert) + r = requests.get(url, headers=http_get_headers, + verify=verify_ssl, cert=client_cert) if debug: log_response(r) return (r.status_code, r.json()) def send_grafana_post(url, json_payload, http_post_headers, verify_ssl=False, client_cert=None, debug=True): - r = requests.post(url, headers=http_post_headers, data=json_payload, verify=verify_ssl, cert=client_cert) + r = requests.post(url, headers=http_post_headers, + data=json_payload, verify=verify_ssl, cert=client_cert) if debug: log_response(r) try: @@ -491,7 +527,8 @@ def send_grafana_post(url, json_payload, http_post_headers, verify_ssl=False, cl def send_grafana_put(url, json_payload, http_post_headers, verify_ssl=False, client_cert=None, debug=True): - r = requests.put(url, headers=http_post_headers, data=json_payload, verify=verify_ssl, cert=client_cert) + r = requests.put(url, headers=http_post_headers, + data=json_payload, verify=verify_ssl, cert=client_cert) if debug: log_response(r) return (r.status_code, r.json()) diff --git a/grafana_backup/delete.py b/grafana_backup/delete.py index 866aeccb..da587606 100755 --- a/grafana_backup/delete.py +++ b/grafana_backup/delete.py @@ -24,7 +24,8 @@ def main(args, settings): 'library-elements': delete_library_elements, 'team-members': delete_team_members} - (status, json_resp, dashboard_uid_support, datasource_uid_support, paging_support) = api_checks(settings) + (status, json_resp, dashboard_uid_support, + datasource_uid_support, paging_support) = api_checks(settings) # Do not continue if API is unavailable or token is not valid if not status == 200: @@ -34,7 +35,6 @@ def main(args, settings): settings.update({'DASHBOARD_UID_SUPPORT': dashboard_uid_support}) settings.update({'DATASOURCE_UID_SUPPORT': datasource_uid_support}) settings.update({'PAGING_SUPPORT': paging_support}) - if arg_components: arg_components_list = arg_components.split(',') diff --git a/grafana_backup/restore.py b/grafana_backup/restore.py index c148c469..cc805e4c 100755 --- a/grafana_backup/restore.py +++ b/grafana_backup/restore.py @@ -41,7 +41,8 @@ def open_compressed_backup(compressed_backup): azure_storage_container_name = settings.get('AZURE_STORAGE_CONTAINER_NAME') gcs_bucket_name = settings.get('GCS_BUCKET_NAME') - (status, json_resp, dashboard_uid_support, datasource_uid_support, paging_support, contact_point_support) = api_checks(settings) + (status, json_resp, dashboard_uid_support, datasource_uid_support, + paging_support, contact_point_support) = api_checks(settings) settings.update({'CONTACT_POINT_SUPPORT': contact_point_support}) # Do not continue if API is unavailable or token is not valid @@ -80,9 +81,11 @@ def open_compressed_backup(compressed_backup): # Shell game magic warning: restore_function keys require the 's' # to be removed in order to match file extension names... restore_functions = collections.OrderedDict() - restore_functions['folder'] = create_folder # Folders must be restored before Library-Elements + # Folders must be restored before Library-Elements + restore_functions['folder'] = create_folder restore_functions['datasource'] = create_datasource - restore_functions['library_element'] = create_library_element # Library-Elements must be restored before dashboards + # Library-Elements must be restored before dashboards + restore_functions['library_element'] = create_library_element restore_functions['dashboard'] = create_dashboard restore_functions['alert_channel'] = create_alert_channel restore_functions['organization'] = create_org @@ -95,7 +98,7 @@ def open_compressed_backup(compressed_backup): restore_functions['alert_rule'] = create_alert_rule restore_functions['contact_point'] = create_contact_point # There are some issues of notification policy restore api, it will lock the notification policy page and cannot be edited. - # restore_functions['notification_policys'] = update_notification_policy + # restore_functions['notification_policys'] = update_notification_policy if sys.version_info >= (3,): with tempfile.TemporaryDirectory() as tmpdir: diff --git a/grafana_backup/save.py b/grafana_backup/save.py index d95c7855..70eb4028 100755 --- a/grafana_backup/save.py +++ b/grafana_backup/save.py @@ -34,7 +34,7 @@ def main(args, settings): 'organizations': save_orgs, 'users': save_users, 'snapshots': save_snapshots, - 'versions': save_dashboard_versions, # left for backwards compatibility + 'versions': save_dashboard_versions, # left for backwards compatibility 'dashboard-versions': save_dashboard_versions, 'annotations': save_annotations, 'library-elements': save_library_elements, @@ -45,13 +45,13 @@ def main(args, settings): 'notification-policy': save_notification_policies, } - (status, - json_resp, - dashboard_uid_support, - datasource_uid_support, - paging_support, + (status, + json_resp, + dashboard_uid_support, + datasource_uid_support, + paging_support, contact_point_support) = api_checks(settings) - + settings.update({'DASHBOARD_UID_SUPPORT': dashboard_uid_support}) settings.update({'DATASOURCE_UID_SUPPORT': datasource_uid_support}) settings.update({'PAGING_SUPPORT': paging_support}) diff --git a/grafana_backup/save_contact_points.py b/grafana_backup/save_contact_points.py index 53f70171..bd3ded69 100644 --- a/grafana_backup/save_contact_points.py +++ b/grafana_backup/save_contact_points.py @@ -3,6 +3,7 @@ from grafana_backup.commons import to_python2_and_3_compatible_string, print_horizontal_line, save_json from packaging import version + def main(args, settings): backup_dir = settings.get('BACKUP_DIR') timestamp = settings.get('TIMESTAMP') @@ -17,7 +18,7 @@ def main(args, settings): grafana_version_string = settings.get('GRAFANA_VERSION') if grafana_version_string: - grafana_version = version.parse(grafana_version_string) + grafana_version = version.parse(grafana_version_string) try: grafana_version = get_grafana_version(grafana_url, verify_ssl) @@ -30,31 +31,37 @@ def main(args, settings): if not os.path.exists(folder_path): os.makedirs(folder_path) - contact_points = get_all_contact_points_in_grafana(grafana_url, http_get_headers, verify_ssl, client_cert, debug) - save_contact_points('contact_points', contact_points, folder_path, pretty_print) + contact_points = get_all_contact_points_in_grafana( + grafana_url, http_get_headers, verify_ssl, client_cert, debug) + save_contact_points('contact_points', contact_points, + folder_path, pretty_print) else: - print("Unable to save contact points, requires Grafana version {0} or above. Current version is {1}".format(minimum_version, grafana_version)) - + print("Unable to save contact points, requires Grafana version {0} or above. Current version is {1}".format( + minimum_version, grafana_version)) if not os.path.exists(folder_path): os.makedirs(folder_path) def get_all_contact_points_in_grafana(grafana_url, http_get_headers, verify_ssl, client_cert, debug): - (status, content) = search_contact_points(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + (status, content) = search_contact_points( + grafana_url, http_get_headers, verify_ssl, client_cert, debug) if status == 200: contact_points = content print("There are {0} contact points: ".format(len(contact_points))) for contact_point in contact_points: - print("name: {0}, type: {1}".format(to_python2_and_3_compatible_string(contact_point['name']), to_python2_and_3_compatible_string(contact_point['type']))) + print("name: {0}, type: {1}".format(to_python2_and_3_compatible_string( + contact_point['name']), to_python2_and_3_compatible_string(contact_point['type']))) return contact_points else: - print("query contact points failed, status: {0}, msg: {1}".format(status, content)) + print("query contact points failed, status: {0}, msg: {1}".format( + status, content)) return [] def save_contact_points(file_name, contact_points, folder_path, pretty_print): - file_path = save_json(file_name, contact_points, folder_path, 'contact_point', pretty_print) + file_path = save_json(file_name, contact_points, + folder_path, 'contact_point', pretty_print) print_horizontal_line() print("contact points are saved to {0}".format(file_path)) print_horizontal_line() diff --git a/grafana_backup/save_notification_policies.py b/grafana_backup/save_notification_policies.py index 7655878c..38ab2811 100644 --- a/grafana_backup/save_notification_policies.py +++ b/grafana_backup/save_notification_policies.py @@ -3,6 +3,7 @@ from grafana_backup.commons import to_python2_and_3_compatible_string, print_horizontal_line, save_json from packaging import version + def main(args, settings): backup_dir = settings.get('BACKUP_DIR') timestamp = settings.get('TIMESTAMP') @@ -17,7 +18,7 @@ def main(args, settings): grafana_version_string = settings.get('GRAFANA_VERSION') if grafana_version_string: - grafana_version = version.parse(grafana_version_string) + grafana_version = version.parse(grafana_version_string) try: grafana_version = get_grafana_version(grafana_url, verify_ssl) @@ -30,29 +31,34 @@ def main(args, settings): if not os.path.exists(folder_path): os.makedirs(folder_path) - notification_policies = get_all_notification_policies_in_grafana(grafana_url, http_get_headers, verify_ssl, client_cert, debug) - save_notification_policies('notificatioin_policies', notification_policies, folder_path, pretty_print) + notification_policies = get_all_notification_policies_in_grafana( + grafana_url, http_get_headers, verify_ssl, client_cert, debug) + save_notification_policies( + 'notificatioin_policies', notification_policies, folder_path, pretty_print) else: - print("Unable to save notification policies, requires Grafana version {0} or above. Current version is {1}".format(minimum_version, grafana_version)) - + print("Unable to save notification policies, requires Grafana version {0} or above. Current version is {1}".format( + minimum_version, grafana_version)) if not os.path.exists(folder_path): os.makedirs(folder_path) def get_all_notification_policies_in_grafana(grafana_url, http_get_headers, verify_ssl, client_cert, debug): - (status, content) = search_notification_policies(grafana_url, http_get_headers, verify_ssl, client_cert, debug) + (status, content) = search_notification_policies( + grafana_url, http_get_headers, verify_ssl, client_cert, debug) if status == 200: notification_policies = content print("Notification policies found") return notification_policies else: - print("query notification policies failed, status: {0}, msg: {1}".format(status, content)) + print("query notification policies failed, status: {0}, msg: {1}".format( + status, content)) return [] def save_notification_policies(file_name, notification_policies, folder_path, pretty_print): - file_path = save_json(file_name, notification_policies, folder_path, 'notification_policys', pretty_print) + file_path = save_json(file_name, notification_policies, + folder_path, 'notification_policys', pretty_print) print_horizontal_line() print("notification policies are saved to {0}".format(file_path)) print_horizontal_line() diff --git a/grafana_backup/update_notification_policy.py b/grafana_backup/update_notification_policy.py index 4072f26a..e2e71062 100644 --- a/grafana_backup/update_notification_policy.py +++ b/grafana_backup/update_notification_policy.py @@ -2,6 +2,7 @@ from grafana_backup.dashboardApi import update_notification_policy, get_grafana_version from packaging import version + def main(args, settings, file_path): grafana_url = settings.get('GRAFANA_URL') http_post_headers = settings.get('HTTP_POST_HEADERS') @@ -22,11 +23,10 @@ def main(args, settings, file_path): data = f.read() notification_policies = json.loads(data) - result = update_notification_policy(json.dumps(notification_policies), grafana_url, http_post_headers, verify_ssl, client_cert, debug) - print("update notification_policy, status: {0}, msg: {1}".format(result[0], result[1])) + result = update_notification_policy(json.dumps( + notification_policies), grafana_url, http_post_headers, verify_ssl, client_cert, debug) + print("update notification_policy, status: {0}, msg: {1}".format( + result[0], result[1])) else: - print("Unable to update notification policy, requires Grafana version {0} or above. Current version is {1}".format(minimum_version, grafana_version)) - - - - + print("Unable to update notification policy, requires Grafana version {0} or above. Current version is {1}".format( + minimum_version, grafana_version)) From 8b554d90c287c69c02254c78e42d8fd32b35046a Mon Sep 17 00:00:00 2001 From: Aaron Johnson Date: Wed, 20 Sep 2023 16:49:50 -0500 Subject: [PATCH 3/4] fix placement of contact_point_check() --- grafana_backup/dashboardApi.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/grafana_backup/dashboardApi.py b/grafana_backup/dashboardApi.py index ce8232a8..82b61775 100755 --- a/grafana_backup/dashboardApi.py +++ b/grafana_backup/dashboardApi.py @@ -80,16 +80,6 @@ def get_first_dashboard_by_page(page): # No dashboards exist, disable paging feature return False, False - -def contact_point_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug): - print("\n[Pre-Check] grafana contact_point api check") - (status, content) = search_contact_points( - grafana_url, http_get_headers, verify_ssl, client_cert, debug) - if status == 200: - return True - else: - return False - # Get first dashboard on first page (status, content) = get_first_dashboard_by_page(1) if status is False and content is False: @@ -112,6 +102,16 @@ def contact_point_check(grafana_url, http_get_headers, verify_ssl, client_cert, return dashboard_one_values != dashboard_two_values +def contact_point_check(grafana_url, http_get_headers, verify_ssl, client_cert, debug): + print("\n[Pre-Check] grafana contact_point api check") + (status, content) = search_contact_points( + grafana_url, http_get_headers, verify_ssl, client_cert, debug) + if status == 200: + return True + else: + return False + + def search_dashboard(page, limit, grafana_url, http_get_headers, verify_ssl, client_cert, debug): url = '{0}/api/search/?type=dash-db&limit={1}&page={2}'.format( grafana_url, limit, page) From 3d29210385c31299e01767c37f5c0b32274246af Mon Sep 17 00:00:00 2001 From: Aaron Johnson Date: Wed, 20 Sep 2023 16:56:27 -0500 Subject: [PATCH 4/4] Uprev package version and update CHANGELOG.md --- CHANGELOG.md | 11 +++++++++++ grafana_backup/constants.py | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2135ed17..cf269486 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +# [1.4.0] - 2023-09-20 + +### Added +- add contact points and notifcation policy backup functionalities by @ysde in #238 +- added http headers to get_grafana_version request by @Mar8x in #239 + +### Changed +- added py3-packaging to slim docker image, reported by @tasiotas in #241 :tada: + +### Removed + # [1.3.3] - 2023-07-27 ### Added diff --git a/grafana_backup/constants.py b/grafana_backup/constants.py index 6f1ab989..5ff83733 100644 --- a/grafana_backup/constants.py +++ b/grafana_backup/constants.py @@ -7,5 +7,5 @@ homedir = os.environ["HOME"] PKG_NAME = "grafana-backup" -PKG_VERSION = "1.3.3" +PKG_VERSION = "1.4.0" JSON_CONFIG_PATH = "{0}/.grafana-backup.json".format(homedir)