diff --git a/grafana_backup/cli.py b/grafana_backup/cli.py index e09e8458..7fdcef7c 100755 --- a/grafana_backup/cli.py +++ b/grafana_backup/cli.py @@ -13,8 +13,8 @@ {0} {1} Usage: - grafana-backup save [--config=<filename>] [--components=<folders,dashboards,datasources,alert-channels,organizations,users,snapshots,versions,annotations>] [--no-archive] - grafana-backup restore <archive_file> [--config=<filename>] [--components=<folders,dashboards,datasources,alert-channels,organizations,users,snapshots,annotations>] + grafana-backup save [--config=<filename>] [--components=<folders,folders_permissions,dashboards,datasources,alert-channels,organizations,users,snapshots,versions,annotations>] [--no-archive] + grafana-backup restore <archive_file> [--config=<filename>] [--components=<folders,folders_permissions,dashboards,datasources,alert-channels,organizations,users,snapshots,annotations>] grafana-backup delete [--config=<filename>] [--components=<folders,dashboards,datasources,alert-channels,snapshots,annotations>] grafana-backup pausealerts [--config=<filename>] grafana-backup unpausealerts <alerts_filename> [--config=<filename>] @@ -26,7 +26,7 @@ -h --help Show this help message and exit --version Get version information and exit --config=<filename> Override default configuration path - --components=<folders,dashboards,datasources,alert-channels,organizations,users,snapshots,versions,annotations> Comma separated list of individual components to backup + --components=<folders,folders_permissions,dashboards,datasources,alert-channels,organizations,users,snapshots,versions,annotations> Comma separated list of individual components to backup rather than backing up all components by default. Versions can only be saved not restored. --no-archive Skip archive creation and do not delete unarchived files (used for troubleshooting purposes) diff --git a/grafana_backup/dashboardApi.py b/grafana_backup/dashboardApi.py index b19dd895..ba5eb0d0 100755 --- a/grafana_backup/dashboardApi.py +++ b/grafana_backup/dashboardApi.py @@ -220,6 +220,19 @@ def get_folder(uid, grafana_url, http_get_headers, verify_ssl, client_cert, debu return (status_code, content) +def get_folder_permissions(uid, grafana_url, http_get_headers, verify_ssl, client_cert, debug): + (status_code, content) = send_grafana_get('{0}/api/folders/{1}/permissions'.format(grafana_url, uid), http_get_headers, + verify_ssl, client_cert, debug) + print("query folder permissions:{0}, status:{1}".format(uid, status_code)) + return (status_code, content) + + +def update_folder_permissions(payload, grafana_url, http_post_headers, verify_ssl, client_cert, debug): + items = json.dumps({'items': payload}) + return send_grafana_post('{0}/api/folders/{1}/permissions'.format(grafana_url,payload[0]['uid']), items, http_post_headers, verify_ssl, client_cert, + debug) + + def get_folder_id_from_old_folder_url(folder_url, grafana_url, http_post_headers, verify_ssl, client_cert, debug): if folder_url != "": # Get folder uid diff --git a/grafana_backup/restore.py b/grafana_backup/restore.py index 22f32849..20c492a0 100755 --- a/grafana_backup/restore.py +++ b/grafana_backup/restore.py @@ -1,6 +1,7 @@ from grafana_backup.create_org import main as create_org from grafana_backup.api_checks import main as api_checks from grafana_backup.create_folder import main as create_folder +from grafana_backup.update_folder_permissions import main as update_folder_permissions from grafana_backup.create_datasource import main as create_datasource from grafana_backup.create_dashboard import main as create_dashboard from grafana_backup.create_alert_channel import main as create_alert_channel @@ -120,3 +121,30 @@ def restore_components(args, settings, restore_functions, tmpdir): file_path = os.path.join(root, filename) print('restoring {0}: {1}'.format(ext, file_path)) restore_functions[ext](args, settings, file_path) + + +def restore_from_dir(args, arg_components, settings, restore_dir): + + restore_functions = { 'folder': create_folder, + 'folder_permissions': update_folder_permissions, + 'datasource': create_datasource, + 'dashboard': create_dashboard, + 'alert_channel': create_alert_channel, + 'organization': create_org, + 'user': create_user} + + if arg_components: + arg_components_list = arg_components.split(',') + + # Restore only the components that provided via an argument + # but must also exist in extracted archive + for ext in arg_components_list: + for file_path in glob('{0}/**/*.{1}'.format(restore_dir, ext[:-1]), recursive=True): + print('restoring {0}: {1}'.format(ext, file_path)) + restore_functions[ext[:-1]](args, settings, file_path) + else: + # Restore every component included in extracted archive + for ext in restore_functions.keys(): + for file_path in glob('{0}/**/*.{1}'.format(restore_dir, ext), recursive=True): + print('restoring {0}: {1}'.format(ext, file_path)) + restore_functions[ext](args, settings, file_path) diff --git a/grafana_backup/save_folders.py b/grafana_backup/save_folders.py index 8f787792..b257054b 100644 --- a/grafana_backup/save_folders.py +++ b/grafana_backup/save_folders.py @@ -1,5 +1,6 @@ import os -from grafana_backup.dashboardApi import search_folders, get_folder +import json +from grafana_backup.dashboardApi import search_folders, get_folder, get_folder_permissions from grafana_backup.commons import to_python2_and_3_compatible_string, print_horizontal_line, save_json @@ -41,9 +42,11 @@ def get_all_folders_in_grafana(grafana_url, http_get_headers, verify_ssl, client return [] -def save_folder_setting(folder_name, file_name, folder_settings, folder_path, pretty_print): +def save_folder_setting(folder_name, file_name, folder_settings, folder_permissions, folder_path, pretty_print): file_path = save_json(file_name, folder_settings, folder_path, 'folder', pretty_print) print("folder:{0} are saved to {1}".format(folder_name, file_path)) + file_path = save_json(file_name, folder_permissions, folder_path, 'folder_permissions', pretty_print) + print("folder permissions:{0} are saved to {1}".format(folder_name, file_path)) def get_individual_folder_setting_and_save(folders, folder_path, log_file, grafana_url, http_get_headers, verify_ssl, client_cert, debug, pretty_print, uid_support): @@ -55,13 +58,15 @@ def get_individual_folder_setting_and_save(folders, folder_path, log_file, grafa else: folder_uri = folder['uri'] - (status, content) = get_folder(folder['uid'], grafana_url, http_get_headers, verify_ssl, client_cert, debug) + (status_folder_settings, content_folder_settings) = get_folder(folder['uid'], grafana_url, http_get_headers, verify_ssl, client_cert, debug) + (status_folder_permissions, content_folder_permissions) = get_folder_permissions(folder['uid'], grafana_url, http_get_headers, verify_ssl, client_cert, debug) - if status == 200: + if status_folder_settings == 200 and status_folder_permissions == 200: save_folder_setting( to_python2_and_3_compatible_string(folder['title']), folder_uri, - content, + content_folder_settings, + content_folder_permissions, folder_path, pretty_print ) diff --git a/grafana_backup/save_orgs.py b/grafana_backup/save_orgs.py index 8322cbb8..b5dcaf27 100755 --- a/grafana_backup/save_orgs.py +++ b/grafana_backup/save_orgs.py @@ -14,7 +14,7 @@ def main(args, settings): pretty_print = settings.get('PRETTY_PRINT') folder_path = '{0}/organizations/{1}'.format(backup_dir, timestamp) - log_file = 'organaizations_{0}.txt'.format(timestamp) + log_file = 'organizations_{0}.txt'.format(timestamp) if http_get_headers_basic_auth: if not os.path.exists(folder_path): diff --git a/grafana_backup/update_folder_permissions.py b/grafana_backup/update_folder_permissions.py new file mode 100644 index 00000000..025a0d6c --- /dev/null +++ b/grafana_backup/update_folder_permissions.py @@ -0,0 +1,18 @@ +import json +from grafana_backup.dashboardApi import update_folder_permissions + + +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') + + with open(file_path, 'r') as f: + data = f.read() + + folder_permissions = json.loads(data) + if folder_permissions: + result = update_folder_permissions(folder_permissions, grafana_url, http_post_headers, verify_ssl, client_cert, debug) + print("update folder permissions {0}, status: {1}, msg: {2}".format(folder_permissions[0].get('title', ''), result[0], result[1]))