Skip to content

Commit

Permalink
PMM-1863 Use temporary API key during import. (percona#39)
Browse files Browse the repository at this point in the history
* PMM-1863 Use placeholders in SQL queries.

* PMM-1863 Use temporary key API during import.

* PMM-1863 Remove duplicate import.
  • Loading branch information
AlekSi authored and Oneiroi committed Dec 13, 2017
1 parent 6729a54 commit 7b5aedc
Showing 1 changed file with 53 additions and 24 deletions.
77 changes: 53 additions & 24 deletions import-dashboards.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,53 @@

# Grafana dashboard importer script.

import base64
import binascii
import hashlib
import json
import os
import random
import shutil
import sqlite3
import string
import subprocess
import sys
import requests
import time
import shutil
import subprocess

import requests

GRAFANA_DB_DIR = sys.argv[1] if len(sys.argv) > 1 else '/var/lib/grafana'
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
DASHBOARD_DIR = SCRIPT_DIR + '/dashboards/'
NEW_VERSION_FILE = SCRIPT_DIR + '/VERSION'
OLD_VERSION_FILE = GRAFANA_DB_DIR + '/PERCONA_DASHBOARDS_VERSION'
HOST = 'http://127.0.0.1:3000'


HOST = 'http://127.0.0.1:3000'
API_KEY = 'eyJrIjoiSjZXMmM0cUpQdFp0djJRUThWMlJzNlVXQmhwRjJvVm0iLCJuIjoiUE1NIERhc2hib2FyZCBJbXBvcnQiLCJpZCI6MX0='
DB_KEY = '6176c9bca5590c39fc29d54b4a72e9fac5e4e8fdb75965123668d420f7b07a2d9443ad60cb8d36a1084c0fc73f3c387c0415'
HEADERS = {'Authorization': 'Bearer %s' % (API_KEY,), 'Content-Type': 'application/json'}
def grafana_headers(api_key):
"""
Returns HTTP headers for all requests to Grafana.
"""

return {'Authorization': 'Bearer %s' % (api_key,), 'Content-Type': 'application/json'}


def get_api_key():
"""
Generates a new API key and returns its name, representation for API, and representation for DB.
Keep in sync with Grafana implementation:
* https://sourcegraph.com/github.com/grafana/grafana/-/blob/pkg/api/apikey.go
* https://sourcegraph.com/github.com/grafana/grafana/-/blob/pkg/components/apikeygen/apikeygen.go
* https://sourcegraph.com/github.com/grafana/grafana/-/blob/pkg/util/encoding.go
"""

alphanum = string.digits + string.ascii_uppercase + string.ascii_uppercase.lower()
name = 'PMM Import ' + ''.join(random.choice(alphanum) for _ in range(16))
key = ''.join(random.choice(alphanum) for _ in range(32))
api_key = base64.b64encode(json.dumps({'k': key, 'n': name, 'id': 1}))
db_key = binascii.hexlify(hashlib.pbkdf2_hmac('sha256', key, name, 10000, 50))
return (name, api_key, db_key)


def check_dashboards_version():
Expand Down Expand Up @@ -79,18 +106,18 @@ def wait_for_grafana_start():
sys.exit(-1)


def add_api_key():
def add_api_key(name, db_key):
con = sqlite3.connect(GRAFANA_DB_DIR + '/grafana.db')
cur = con.cursor()

cur.execute("REPLACE INTO api_key (org_id, name, key, role, created, updated) "
"VALUES (1, 'PMM Dashboard Import', '%s', 'Admin', datetime('now'), datetime('now'))" % (DB_KEY,))
"VALUES (1, ?, ?, 'Admin', datetime('now'), datetime('now'))", (name, db_key))

con.commit()
con.close()


def delete_api_key(upgrade):
def delete_api_key(db_key, upgrade):
con = sqlite3.connect(GRAFANA_DB_DIR + '/grafana.db')
cur = con.cursor()

Expand All @@ -102,7 +129,7 @@ def delete_api_key(upgrade):
"SELECT 1, 1, 0, 0, id, '', '', datetime('now'), datetime('now') from dashboard WHERE slug='cross-server-graphs'")

# Delete key.
cur.execute("DELETE FROM api_key WHERE key='%s'" % (DB_KEY,))
cur.execute("DELETE FROM api_key WHERE key = ?", (db_key,))

con.commit()
con.close()
Expand Down Expand Up @@ -135,28 +162,28 @@ def fix_cloudwatch_datasource():
con.close()


def add_datasources():
r = requests.get('%s/api/datasources' % (HOST,), headers=HEADERS)
def add_datasources(api_key):
r = requests.get('%s/api/datasources' % (HOST,), headers=grafana_headers(api_key))
print r.status_code, r.content
ds = [x['name'] for x in json.loads(r.content)]
if 'Prometheus' not in ds:
data = json.dumps({'name': 'Prometheus', 'type': 'prometheus', 'url': 'http://127.0.0.1:9090/prometheus/', 'access': 'proxy', 'isDefault': True})
r = requests.post('%s/api/datasources' % HOST, data=data, headers=HEADERS)
r = requests.post('%s/api/datasources' % HOST, data=data, headers=grafana_headers(api_key))
print r.status_code, r.content
if r.status_code != 200:
print ' * Cannot add Prometheus Data Source'
sys.exit(-1)

if 'CloudWatch' not in ds:
data = json.dumps({'name': 'CloudWatch', 'type': 'cloudwatch', 'jsonData': {'authType': 'keys'}, 'access': 'proxy', 'isDefault': False})
r = requests.post('%s/api/datasources' % HOST, data=data, headers=HEADERS)
r = requests.post('%s/api/datasources' % HOST, data=data, headers=grafana_headers(api_key))
print r.status_code, r.content
if r.status_code != 200:
print ' * Cannot add CloudWatch Data Source'
sys.exit(-1)


def import_dashboards():
def import_dashboards(api_key):
# Import dashboards with overwrite.
files = []
for f in os.listdir(DASHBOARD_DIR):
Expand All @@ -177,7 +204,7 @@ def import_dashboards():
dash['refresh'] = '1m'

data = json.dumps({'dashboard': dash, 'overwrite': True})
r = requests.post('%s/api/dashboards/db' % HOST, data=data, headers=HEADERS)
r = requests.post('%s/api/dashboards/db' % HOST, data=data, headers=grafana_headers(api_key))
if r.status_code != 200:
print r.status_code, r.content
print ' * Cannot add %s Dashboard' % file_
Expand All @@ -194,11 +221,11 @@ def copy_apps():
shutil.copytree(source_dir, dest_dir)


def import_apps():
def import_apps(api_key):
for app in ['pmm-app']:
print app
data = json.dumps({'enabled': True})
r = requests.post('%s/api/plugins/%s/settings' % (HOST, app), data=data, headers=HEADERS)
r = requests.post('%s/api/plugins/%s/settings' % (HOST, app), data=data, headers=grafana_headers(api_key))
if r.status_code != 200:
print r.status_code, r.content
print ' * Cannot add %s app' % app
Expand All @@ -208,25 +235,27 @@ def import_apps():
def main():
upgrade = check_dashboards_version()

name, api_key, db_key = get_api_key()

# modify database when Grafana is stopped to avoid a data race
stop_grafana()
try:
copy_apps()
add_api_key()
add_api_key(name, db_key)
fix_cloudwatch_datasource()
finally:
start_grafana()

wait_for_grafana_start()

add_datasources()
import_apps()
import_dashboards()
add_datasources(api_key)
import_apps(api_key)
import_dashboards(api_key)

# modify database when Grafana is stopped to avoid a data race
stop_grafana()
try:
delete_api_key(upgrade)
delete_api_key(db_key, upgrade)
finally:
start_grafana()

Expand Down

0 comments on commit 7b5aedc

Please sign in to comment.