Skip to content

Commit

Permalink
changes
Browse files Browse the repository at this point in the history
  • Loading branch information
peekjef72 committed Jan 27, 2022
1 parent 49f6538 commit 95fef17
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 129 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*/__pycache__/*
.eggs/*
*.egg-info/*
build/*
INFO.txt
76 changes: 67 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,43 @@ install with bitbuckt repo or github repo.
$ pip install git+https://github.com/peekjef72/grafana_api.git
```
## Configuration
The configuration is stored in a JSON file, with extended syntax that authorize comments in C++ style with // or /*... */.
The configuration is stored in a YAML file.

It contains 2 parts:
* **general**: for script env.
* **debug**: enable verbose (debug) trace (for dev only...)
* **export_suffix**: when exporting a dashboard, append that suffix to the file name. The suffix can contain plain text and pattern that is translated with strftime command.
* **export_path**: where to store the exported dashboards.
* **import_path**: where to load the dashboards before to import then into grafana server.
- **grafana**: for grafana access settings
* **protocal**, **host**, **port**: use to build the access url
* **verify_ssl**: to check ssl certificate or not
* **token**: APIKEY with admin right from Grafana to access the REST API.
* **search_api_limit**: the maximum element to retrieve on search over API.
- **grafana**: for grafana access settings; you can define several grafana acces with different api_key or grafana server url
* **label**: a label to refer this grafana server default at least
* **protocal**, **host**, **port**: use to build the access url
* **verify_ssl**: to check ssl certificate or not
* **token**: APIKEY with admin right from Grafana to access the REST API.
* **search_api_limit**: the maximum element to retrieve on search over API.

<details>
example:

```yaml
---

general:
debug: false
import_folder: test_import

grafana:
default:
protocol: http
host: localhost
port: 3000
token: "____APIKEY____"
search_api_limit: 5000
verify_ssl: true
...
```

</details>

## Usages
build a directory structure:
Expand All @@ -60,11 +85,44 @@ build a directory structure:

then enter into your directory and type in you commands.

**usage**: grafana-import [-h] [-b BASE_PATH] [-c CONFIG_FILE] [-d DASHBOARD_NAME]
[-f GRAFANA_FOLDER] [-i DASHBOARD_FILE] [-o] [-p] [-v]
[-V]
**usage**:
```shell
usage: grafana-import [-h] [-b BASE_PATH] [-c CONFIG_FILE] [-d DASHBOARD_NAME]
[-g GRAFANA_LABEL] [-f GRAFANA_FOLDER]
[-i DASHBOARD_FILE] [-o] [-p] [-v] [-V]
[ACTION]

play with grafana dashboards json files.

positional arguments:
ACTION action to perform. Is one of 'export' or 'import'
(default). export: lookup for dashboard name in
Grafana and dump it to local file. import: import a
local dashboard file (previously exported) to Grafana.

optional arguments:
-h, --help show this help message and exit
-b BASE_PATH, --base_path BASE_PATH
set base directory to find default files.
-c CONFIG_FILE, --config_file CONFIG_FILE
path to config files.
-d DASHBOARD_NAME, --dashboard_name DASHBOARD_NAME
name of dashboard to export.
-g GRAFANA_LABEL, --grafana_label GRAFANA_LABEL
label in the config file that represent the grafana to
connect to.
-f GRAFANA_FOLDER, --grafana_folder GRAFANA_FOLDER
the folder name where to import into Grafana.
-i DASHBOARD_FILE, --dashboard_file DASHBOARD_FILE
path to the dashboard file to import into Grafana.
-o, --overwrite if a dashboard with same name exists in folder,
overwrite it with this new one.
-p, --pretty use JSON indentation when exporting or extraction of
dashboards.
-v, --verbose verbose mode; display log message to stdout.
-V, --version display program version and exit..

```
import action preserves the version history.
Expand Down
84 changes: 50 additions & 34 deletions grafana_import/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#***********************************************************************************************


from grafana_import.constants import (PKG_NAME, PKG_VERSION, JSON_CONFIG_NAME)
from grafana_import.constants import (PKG_NAME, PKG_VERSION, CONFIG_NAME)

import argparse, json, sys, os, re, socket, logging
import unicodedata, traceback
Expand All @@ -26,7 +26,7 @@
from grafana_api.grafana_face import GrafanaFace
import grafana_api.grafana_api as GrafanaApi

from grafana_import.jsonConfig import jsonConfig
import yaml

#******************************************************************************************
config = None
Expand All @@ -36,9 +36,9 @@ def get_dashboard_content(config, args, grafana_api, dashboard_name):

try:
res = grafana_api.search.search_dashboards(
type_='dash-db'
, limit=config['grafana']['search_api_limit']
)
type_='dash-db',
limit=config['grafana']['search_api_limit'],
)
except Exception as e:
print("error: {}".format(traceback.format_exc()) )
# print("error: {} - message: {}".format(e.__doc__, e.message) )
Expand Down Expand Up @@ -127,7 +127,7 @@ def save_dashboard(config, args, base_path, dashboard_name, params, action):
class myArgs:
attrs = [ 'pattern'
, 'base_path', 'config_file'
, 'dashboard_name'
, 'grafana', 'dashboard_name'
, 'pretty', 'overwrite', 'verbose'
]
def __init__(self):
Expand Down Expand Up @@ -158,6 +158,10 @@ def main():
parser.add_argument('-d', '--dashboard_name'
, help='name of dashboard to export.')

parser.add_argument('-g', '--grafana_label'
, help='label in the config file that represent the grafana to connect to.'
, default='default')

parser.add_argument('-f', '--grafana_folder'
, help='the folder name where to import into Grafana.')

Expand All @@ -172,7 +176,7 @@ def main():
, action='store_true'
, help='use JSON indentation when exporting or extraction of dashboards.')

parser.add_argument('-v ', '--verbose'
parser.add_argument('-v', '--verbose'
, action='store_true'
, help='verbose mode; display log message to stdout.')

Expand All @@ -193,18 +197,26 @@ def main():
if args.base_path is not None:
base_path = inArgs.base_path

config_file = base_path + '/' + JSON_CONFIG_NAME
config_file = os.path.join(base_path, CONFIG_NAME)
if args.config_file is not None:
config_file = inArgs.config_file
if not re.search(r'^(\.|\/)?/', config_file):
config_file = os.path.join(base_path,args.config_file)
else:
config_file = args.config_file

config = None
try:
with open(config_file, 'r') as cfg_fh:
try:
config = yaml.safe_load(cfg_fh)
except yaml.scanner.ScannerError as exc:
mark = exc.problem_mark
print("Yaml file parsing unsuccessul : %s - line: %s column: %s => %s" % (config_file, mark.line+1, mark.column+1, exc.problem) )
except Exception as exp:
print('ERROR: config file not read: %s' % str(exp))

confObj = jsonConfig(config_file)
if confObj is None:
print( 'init config failure !')
sys.exit(2)
config = confObj.load()
if config is None:
print( confObj.err_msg )
sys.exit(2)
sys.exit(1)

if args.verbose is None:
if 'debug' in config['general']:
Expand All @@ -220,7 +232,7 @@ def main():

if args.action == 'exporter' and ( not 'dashboard_name' in config['general'] or config['general']['dashboard_name'] is None) :
print("ERROR: no dashboard has been specified.")
sys.exit(2)
sys.exit(1)

#************
config['check_folder'] = False
Expand All @@ -232,29 +244,33 @@ def main():
if 'export_suffix' not in config['general'] or config['general']['export_suffix'] is None:
config['general']['export_suffix'] = "_%Y%m%d%H%M%S"

if not args.grafana_label in config['grafana']:
print("ERROR: invalid grafana config label has been specified (-g {0}).".format(args.grafana_label))
sys.exit(1)

#************
grafana_api = GrafanaFace(
auth=config['grafana']['token']
, host=config['grafana']['host']
, protocol=config['grafana']['protocol']
, port=config['grafana']['port']
, verify=config['grafana']['verify_ssl']
auth=config['grafana'][args.grafana_label]['token'],
host=config['grafana'][args.grafana_label]['host'],
protocol=config['grafana'][args.grafana_label]['protocol'],
port=config['grafana'][args.grafana_label]['port'],
verify=config['grafana'][args.grafana_label]['verify_ssl'],
)
try:
res = grafana_api.health.check()
if res['database'] != 'ok':
print("grafana health_check is not KO.")
sys.exit(2)
sys.exit(1)
elif args.verbose:
print("grafana health_check is OK.")
except e:
print("error: {} - message: {}".format(status_code, e.message) )
sys.exit(2)
except Exception as e:
print("ERROR: {} - message: {}".format(res, e.message) )
sys.exit(1)

if args.action == 'import':
if args.dashboard_file is None:
print('no file to import provided!')
sys.exit(2)
print('ERROR: no file to import provided!')
sys.exit(1)
import_path = ''
import_file = args.dashboard_file
if not re.search(r'^(?:(?:/)|(?:\.?\./))', import_file):
Expand All @@ -265,17 +281,17 @@ def main():
try:
input = open(import_path, 'r')
except OSError as e:
print('File {0} error: {1}.'.format(import_path, e.strerror))
sys.exit(2)
print('ERROR: File {0} error: {1}.'.format(import_path, e.strerror))
sys.exit(1)

data = input.read()
input.close()

try:
dash = json.loads(data)
except json.JSONDecodeError as e:
print("error reading '{0}': {1}".format(import_path, e))
sys.exit(2)
print("ERROR: reading '{0}': {1}".format(import_path, e))
sys.exit(1)

#** check dashboard existence
#** dash from file has no meta data (folder infos)
Expand Down Expand Up @@ -344,10 +360,10 @@ def main():
sys.exit(0)
else:
print("KO: dashboard {0} not imported into '{1}'.".format(dash['title'], config['general']['grafana_folder']))
sys.exit(2)
sys.exit(1)
else:
print("error invalid dashboard file '{0}': can't find dashboard uid".format(import_path))
sys.exit(2)
sys.exit(1)
else: # export
dash = get_dashboard_content(config, args, grafana_api, config['general']['dashboard_name'])
if dash is not None:
Expand Down
15 changes: 0 additions & 15 deletions grafana_import/conf/grafana-import.json

This file was deleted.

15 changes: 15 additions & 0 deletions grafana_import/conf/grafana-import.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---

general:
debug: false
import_folder: test_import

grafana:
default:
protocol: http
host: localhost
port: 3000
token: "____APIKEY____"
search_api_limit: 5000
verify_ssl: true

4 changes: 2 additions & 2 deletions grafana_import/constants.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
PKG_NAME = 'grafana-import'
PKG_VERSION = '0.0.1'
JSON_CONFIG_NAME = 'conf/grafana-import.json'
PKG_VERSION = '0.0.2'
CONFIG_NAME = 'conf/grafana-import.yml'
69 changes: 0 additions & 69 deletions grafana_import/jsonConfig.py

This file was deleted.

0 comments on commit 95fef17

Please sign in to comment.