Skip to content

Commit

Permalink
contact points and notifcation policy backup
Browse files Browse the repository at this point in the history
  • Loading branch information
ysde authored and Aaron Johnson committed Sep 20, 2023
1 parent 5e12194 commit 62821d5
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 14 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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):

Expand Down
File renamed without changes.
6 changes: 4 additions & 2 deletions grafana_backup/api_checks.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down Expand Up @@ -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:
Expand All @@ -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)
2 changes: 1 addition & 1 deletion grafana_backup/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
33 changes: 33 additions & 0 deletions grafana_backup/create_contact_point.py
Original file line number Diff line number Diff line change
@@ -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))




21 changes: 20 additions & 1 deletion grafana_backup/dashboardApi.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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))
Expand Down Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions grafana_backup/delete.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(',')
Expand Down
10 changes: 8 additions & 2 deletions grafana_backup/restore.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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(',')
Expand Down
26 changes: 19 additions & 7 deletions grafana_backup/save.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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


Expand All @@ -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(',')

Expand Down
60 changes: 60 additions & 0 deletions grafana_backup/save_contact_points.py
Original file line number Diff line number Diff line change
@@ -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()
58 changes: 58 additions & 0 deletions grafana_backup/save_notification_policies.py
Original file line number Diff line number Diff line change
@@ -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()
32 changes: 32 additions & 0 deletions grafana_backup/update_notification_policy.py
Original file line number Diff line number Diff line change
@@ -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))




0 comments on commit 62821d5

Please sign in to comment.