/
circonus_add.py
executable file
·147 lines (128 loc) · 4.51 KB
/
circonus_add.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python
"""
circonus_add.py - Read in a json file of circonus resources and bulk-add them
This command accepts a json formatted file, with multiple circonus resources
(check bundles, rule sets etc), and adds them to circonus in bulk. The command
accepts two different file formats:
* A list of resources, with the endpoint stored in the '_cid' attribute
* A json object, with the keys being the endpoint, and the values being
the resource itself. Duplicate keys _are_ allowed (for adding multiple
resources to the same endpoint).
The content of each resource is sent directly to the API. See the API
documentation for information on what this should contain, or use circonusvi
to take a look at existing resources for examples.
"""
import getopt
import json
import re
import sys
from circonusapi import circonusapi
from circonusapi import config
from circuslib import util
conf = config.load_config()
options = {
'account': conf.get('general', 'default_account'),
'debug': False
}
def usage():
print "Usage:"
print sys.argv[0], "[options] [FILENAME]"
print
print "Reads in a json file with a list of resources to add"
print
print " -a -- Specify which account to use"
print " -d -- Enable debug mode"
def parse_options():
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], "a:d?")
except getopt.GetoptError, err:
# print help information and exit:
print str(err) # will print something like "option -a not recognized"
usage()
sys.exit(2)
for o,a in opts:
if o == '-a':
options['account'] = a
if o == '-d':
options['debug'] = not options['debug']
if o == '-?':
usage()
sys.exit(0)
return args
def get_api():
token = conf.get('tokens', options['account'], None)
api = circonusapi.CirconusAPI(token)
if options['debug']:
api.debug = True
return api
def make_changes(changes):
for c in changes:
print "Making API Call: %s %s ..." % (c['action'], c['endpoint']),
if c['action'] == 'DELETE':
# We don't send any data along for deletions
c['data'] = None
try:
api.api_call(c['action'], c['endpoint'], c['data'])
except circonusapi.CirconusAPIError, e:
print "Error"
print " %s" % e
continue
print "Success"
def json_pairs_hook_dedup_keys(data):
# json decoder object_pairs_hook that allows duplicate keys, and makes
# any duplicate keys unique by appending /x1, /x1 and so on to the end.
# This is used when adding new items via the circonus api, you can just
# specify /check_bundle multiple times as the endpoint and won't get an
# error about duplicate keys when decoding the json. Separate code
# elsewhere automatically strips off the /x1 when selecting the endpoint
# to use for adding entries.
d = {}
ctr = 0
for k,v in data:
oldk = k
while k in d:
ctr += 1
k = "%s/x%s" % (oldk, ctr)
d[k] = v
return d
def load_json_file(filename):
with open(filename) as fh:
return json.load(fh, object_pairs_hook=json_pairs_hook_dedup_keys)
def fix_data_format(data):
"""We accept two formats for adding data:
A json list, where the '_cid' field is the endpoint to add. We strip off
any resource ID from the end.
A json object (python dict), where the keys are the endpoints to add.
Again we strip off any resource ID. The json parser also will accept
duplicate keys and dedup them upon loading.
This function converts the object/dict format into the list format, if
needed.
"""
if type(data) == dict:
new_data = []
for k, v in data.items():
v['_cid'] = k
new_data.append(v)
return new_data
return data
def make_additions(api, data):
for i in data:
endpoint = re.sub("(?!^)/.*", "", i['_cid'])
print "Making API Call: POST %s ..." % (endpoint),
try:
api.api_call("POST", endpoint, i)
except circonusapi.CirconusAPIError, e:
print "Error"
print " %s" % e
continue
print "Success"
if __name__ == '__main__':
args = parse_options()
if len(args) != 1:
usage()
sys.exit(2)
api = get_api()
data = load_json_file(args[0])
data = fix_data_format(data)
if util.confirm("%s additions, OK to continue?" % len(data)):
make_additions(api, data)