##// END OF EJS Templates
api: decouple some parts from api CLI script...
marcink -
r3833:5055dd38 beta
parent child Browse files
Show More
@@ -0,0 +1,148 b''
1 """
2 Base utils for shell scripts
3 """
4 import os
5 import sys
6 import random
7 import urllib2
8 import pprint
9
10 try:
11 from rhodecode.lib.ext_json import json
12 except ImportError:
13 try:
14 import simplejson as json
15 except ImportError:
16 import json
17
18 CONFIG_NAME = '.rhodecode'
19 FORMAT_PRETTY = 'pretty'
20 FORMAT_JSON = 'json'
21
22
23 def api_call(apikey, apihost, format, method=None, **kw):
24 """
25 Api_call wrapper for RhodeCode
26
27 :param apikey:
28 :param apihost:
29 :param format: formatting, pretty means prints and pprint of json
30 json returns unparsed json
31 :param method:
32 """
33 def _build_data(random_id):
34 """
35 Builds API data with given random ID
36
37 :param random_id:
38 :type random_id:
39 """
40 return {
41 "id": random_id,
42 "api_key": apikey,
43 "method": method,
44 "args": kw
45 }
46
47 if not method:
48 raise Exception('please specify method name !')
49 id_ = random.randrange(1, 9999)
50 req = urllib2.Request('%s/_admin/api' % apihost,
51 data=json.dumps(_build_data(id_)),
52 headers={'content-type': 'text/plain'})
53 if format == FORMAT_PRETTY:
54 sys.stdout.write('calling %s to %s \n' % (req.get_data(), apihost))
55 ret = urllib2.urlopen(req)
56 raw_json = ret.read()
57 json_data = json.loads(raw_json)
58 id_ret = json_data['id']
59 _formatted_json = pprint.pformat(json_data)
60 if id_ret == id_:
61 if format == FORMAT_JSON:
62 sys.stdout.write(str(raw_json))
63 else:
64 sys.stdout.write('rhodecode returned:\n%s\n' % (_formatted_json))
65
66 else:
67 raise Exception('something went wrong. '
68 'ID mismatch got %s, expected %s | %s' % (
69 id_ret, id_, _formatted_json))
70
71
72 class RcConf(object):
73 """
74 RhodeCode config for API
75
76 conf = RcConf()
77 conf['key']
78
79 """
80
81 def __init__(self, config_location=None, autoload=True, autocreate=False,
82 config=None):
83 self._conf_name = CONFIG_NAME if not config_location else config_location
84 self._conf = {}
85 if autocreate:
86 self.make_config(config)
87 if autoload:
88 self._conf = self.load_config()
89
90 def __getitem__(self, key):
91 return self._conf[key]
92
93 def __nonzero__(self):
94 if self._conf:
95 return True
96 return False
97
98 def __eq__(self):
99 return self._conf.__eq__()
100
101 def __repr__(self):
102 return 'RcConf<%s>' % self._conf.__repr__()
103
104 def make_config(self, config):
105 """
106 Saves given config as a JSON dump in the _conf_name location
107
108 :param config:
109 :type config:
110 """
111 update = False
112 if os.path.exists(self._conf_name):
113 update = True
114 with open(self._conf_name, 'wb') as f:
115 json.dump(config, f, indent=4)
116
117 if update:
118 sys.stdout.write('Updated config in %s\n' % self._conf_name)
119 else:
120 sys.stdout.write('Created new config in %s\n' % self._conf_name)
121
122 def update_config(self, new_config):
123 """
124 Reads the JSON config updates it's values with new_config and
125 saves it back as JSON dump
126
127 :param new_config:
128 """
129 config = {}
130 try:
131 with open(self._conf_name, 'rb') as conf:
132 config = json.load(conf)
133 except IOError, e:
134 sys.stderr.write(str(e) + '\n')
135
136 config.update(new_config)
137 self.make_config(config)
138
139 def load_config(self):
140 """
141 Loads config from file and returns loaded JSON object
142 """
143 try:
144 with open(self._conf_name, 'rb') as conf:
145 return json.load(conf)
146 except IOError, e:
147 #sys.stderr.write(str(e) + '\n')
148 pass
@@ -1,249 +1,107 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.bin.backup_manager
3 rhodecode.bin.api
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~
5
5
6 Api CLI client for RhodeCode
6 Api CLI client for RhodeCode
7
7
8 :created_on: Jun 3, 2012
8 :created_on: Jun 3, 2012
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 from __future__ import with_statement
26 from __future__ import with_statement
27 import os
28 import sys
27 import sys
29 import random
30 import urllib2
31 import pprint
32 import argparse
28 import argparse
33
29
34 try:
30 from rhodecode.bin.base import api_call, RcConf, FORMAT_JSON, FORMAT_PRETTY
35 from rhodecode.lib.ext_json import json
36 except ImportError:
37 try:
38 import simplejson as json
39 except ImportError:
40 import json
41
42
43 CONFIG_NAME = '.rhodecode'
44 FORMAT_PRETTY = 'pretty'
45 FORMAT_JSON = 'json'
46
47
48 class RcConf(object):
49 """
50 RhodeCode config for API
51
52 conf = RcConf()
53 conf['key']
54
55 """
56
57 def __init__(self, config_location=None, autoload=True, autocreate=False,
58 config=None):
59 self._conf_name = CONFIG_NAME if not config_location else config_location
60 self._conf = {}
61 if autocreate:
62 self.make_config(config)
63 if autoload:
64 self._conf = self.load_config()
65
66 def __getitem__(self, key):
67 return self._conf[key]
68
69 def __nonzero__(self):
70 if self._conf:
71 return True
72 return False
73
74 def __eq__(self):
75 return self._conf.__eq__()
76
77 def __repr__(self):
78 return 'RcConf<%s>' % self._conf.__repr__()
79
80 def make_config(self, config):
81 """
82 Saves given config as a JSON dump in the _conf_name location
83
84 :param config:
85 :type config:
86 """
87 update = False
88 if os.path.exists(self._conf_name):
89 update = True
90 with open(self._conf_name, 'wb') as f:
91 json.dump(config, f, indent=4)
92
93 if update:
94 sys.stdout.write('Updated config in %s\n' % self._conf_name)
95 else:
96 sys.stdout.write('Created new config in %s\n' % self._conf_name)
97
98 def update_config(self, new_config):
99 """
100 Reads the JSON config updates it's values with new_config and
101 saves it back as JSON dump
102
103 :param new_config:
104 """
105 config = {}
106 try:
107 with open(self._conf_name, 'rb') as conf:
108 config = json.load(conf)
109 except IOError, e:
110 sys.stderr.write(str(e) + '\n')
111
112 config.update(new_config)
113 self.make_config(config)
114
115 def load_config(self):
116 """
117 Loads config from file and returns loaded JSON object
118 """
119 try:
120 with open(self._conf_name, 'rb') as conf:
121 return json.load(conf)
122 except IOError, e:
123 #sys.stderr.write(str(e) + '\n')
124 pass
125
126
127 def api_call(apikey, apihost, format, method=None, **kw):
128 """
129 Api_call wrapper for RhodeCode
130
131 :param apikey:
132 :param apihost:
133 :param format: formatting, pretty means prints and pprint of json
134 json returns unparsed json
135 :param method:
136 """
137 def _build_data(random_id):
138 """
139 Builds API data with given random ID
140
141 :param random_id:
142 :type random_id:
143 """
144 return {
145 "id": random_id,
146 "api_key": apikey,
147 "method": method,
148 "args": kw
149 }
150
151 if not method:
152 raise Exception('please specify method name !')
153 id_ = random.randrange(1, 9999)
154 req = urllib2.Request('%s/_admin/api' % apihost,
155 data=json.dumps(_build_data(id_)),
156 headers={'content-type': 'text/plain'})
157 if format == FORMAT_PRETTY:
158 sys.stdout.write('calling %s to %s \n' % (req.get_data(), apihost))
159 ret = urllib2.urlopen(req)
160 raw_json = ret.read()
161 json_data = json.loads(raw_json)
162 id_ret = json_data['id']
163 _formatted_json = pprint.pformat(json_data)
164 if id_ret == id_:
165 if format == FORMAT_JSON:
166 sys.stdout.write(str(raw_json))
167 else:
168 sys.stdout.write('rhodecode returned:\n%s\n' % (_formatted_json))
169
170 else:
171 raise Exception('something went wrong. '
172 'ID mismatch got %s, expected %s | %s' % (
173 id_ret, id_, _formatted_json))
174
31
175
32
176 def argparser(argv):
33 def argparser(argv):
177 usage = (
34 usage = (
178 "rhodecode_api [-h] [--format=FORMAT] [--apikey=APIKEY] [--apihost=APIHOST] "
35 "rhodecode-api [-h] [--format=FORMAT] [--apikey=APIKEY] [--apihost=APIHOST] "
179 " [--config=CONFIG] "
36 "[--config=CONFIG] [--save-config] "
180 "_create_config or METHOD <key:val> <key2:val> ..."
37 "METHOD <key:val> <key2:val> ...\n"
38 "Create config file: rhodecode-gist --apikey=<key> --apihost=http://rhodecode.server --save-config"
181 )
39 )
182
40
183 parser = argparse.ArgumentParser(description='RhodeCode API cli',
41 parser = argparse.ArgumentParser(description='RhodeCode API cli',
184 usage=usage)
42 usage=usage)
185
43
186 ## config
44 ## config
187 group = parser.add_argument_group('config')
45 group = parser.add_argument_group('config')
188 group.add_argument('--apikey', help='api access key')
46 group.add_argument('--apikey', help='api access key')
189 group.add_argument('--apihost', help='api host')
47 group.add_argument('--apihost', help='api host')
190 group.add_argument('--config', help='config file')
48 group.add_argument('--config', help='config file')
49 group.add_argument('--save-config', action='store_true', help='save the given config into a file')
191
50
192 group = parser.add_argument_group('API')
51 group = parser.add_argument_group('API')
193 group.add_argument('method', metavar='METHOD', type=str,
52 group.add_argument('method', metavar='METHOD', nargs='?', type=str, default=None,
194 help='API method name to call followed by key:value attributes',
53 help='API method name to call followed by key:value attributes',
195 )
54 )
196 group.add_argument('--format', dest='format', type=str,
55 group.add_argument('--format', dest='format', type=str,
197 help='output format default: `pretty` can '
56 help='output format default: `pretty` can '
198 'be also `%s`' % FORMAT_JSON,
57 'be also `%s`' % FORMAT_JSON,
199 default=FORMAT_PRETTY
58 default=FORMAT_PRETTY
200 )
59 )
201 args, other = parser.parse_known_args()
60 args, other = parser.parse_known_args()
202 return parser, args, other
61 return parser, args, other
203
62
204
63
205 def main(argv=None):
64 def main(argv=None):
206 """
65 """
207 Main execution function for cli
66 Main execution function for cli
208
67
209 :param argv:
68 :param argv:
210 :type argv:
69 :type argv:
211 """
70 """
212 if argv is None:
71 if argv is None:
213 argv = sys.argv
72 argv = sys.argv
214
73
215 conf = None
74 conf = None
216 parser, args, other = argparser(argv)
75 parser, args, other = argparser(argv)
217
76
218 api_credentials_given = (args.apikey and args.apihost)
77 api_credentials_given = (args.apikey and args.apihost)
219 if args.method == '_create_config':
78 if args.save_config:
220 if not api_credentials_given:
79 if not api_credentials_given:
221 raise parser.error('_create_config requires --apikey and --apihost')
80 raise parser.error('--save-config requires --apikey and --apihost')
222 conf = RcConf(config_location=args.config,
81 conf = RcConf(config_location=args.config,
223 autocreate=True, config={'apikey': args.apikey,
82 autocreate=True, config={'apikey': args.apikey,
224 'apihost': args.apihost})
83 'apihost': args.apihost})
84 sys.exit()
225
85
226 if not conf:
86 if not conf:
227 conf = RcConf(config_location=args.config, autoload=True)
87 conf = RcConf(config_location=args.config, autoload=True)
228 if not conf:
88 if not conf:
229 if not api_credentials_given:
89 if not api_credentials_given:
230 parser.error('Could not find config file and missing '
90 parser.error('Could not find config file and missing '
231 '--apikey or --apihost in params')
91 '--apikey or --apihost in params')
232
92
233 apikey = args.apikey or conf['apikey']
93 apikey = args.apikey or conf['apikey']
234 host = args.apihost or conf['apihost']
94 host = args.apihost or conf['apihost']
235 method = args.method
95 method = args.method
236 if method == '_create_config':
237 sys.exit()
238
96
239 try:
97 try:
240 margs = dict(map(lambda s: s.split(':', 1), other))
98 margs = dict(map(lambda s: s.split(':', 1), other))
241 except Exception:
99 except Exception:
242 sys.stderr.write('Error parsing arguments \n')
100 sys.stderr.write('Error parsing arguments \n')
243 sys.exit()
101 sys.exit()
244
102
245 api_call(apikey, host, args.format, method, **margs)
103 api_call(apikey, host, args.format, method, **margs)
246 return 0
104 return 0
247
105
248 if __name__ == '__main__':
106 if __name__ == '__main__':
249 sys.exit(main(sys.argv))
107 sys.exit(main(sys.argv))
General Comments 0
You need to be logged in to leave comments. Login now