Mercurial > kallithea
comparison rhodecode/bin/rhodecode_api.py @ 2379:7ac09514a178 beta
created rhodecode-api binary script for working with api via cli
- created docs
- moved the backup script to bin folder
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Sun, 03 Jun 2012 20:35:13 +0200 |
parents | |
children | e487d2a6aa38 |
comparison
equal
deleted
inserted
replaced
2378:04ef27ce939e | 2379:7ac09514a178 |
---|---|
1 # -*- coding: utf-8 -*- | |
2 """ | |
3 rhodecode.bin.backup_manager | |
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
5 | |
6 Api CLI client for RhodeCode | |
7 | |
8 :created_on: Jun 3, 2012 | |
9 :author: marcink | |
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com> | |
11 :license: GPLv3, see COPYING for more details. | |
12 """ | |
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 | |
15 # the Free Software Foundation, either version 3 of the License, or | |
16 # (at your option) any later version. | |
17 # | |
18 # This program is distributed in the hope that it will be useful, | |
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 # GNU General Public License for more details. | |
22 # | |
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/>. | |
25 | |
26 from __future__ import with_statement | |
27 import os | |
28 import sys | |
29 import random | |
30 import urllib2 | |
31 import pprint | |
32 import argparse | |
33 | |
34 try: | |
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 | |
45 | |
46 class RcConf(object): | |
47 """ | |
48 RhodeCode config for API | |
49 | |
50 conf = RcConf() | |
51 conf['key'] | |
52 | |
53 """ | |
54 | |
55 def __init__(self, autoload=True, autocreate=False, config=None): | |
56 self._conf_name = CONFIG_NAME | |
57 self._conf = {} | |
58 if autocreate: | |
59 self.make_config(config) | |
60 if autoload: | |
61 self._conf = self.load_config() | |
62 | |
63 def __getitem__(self, key): | |
64 return self._conf[key] | |
65 | |
66 def __nonzero__(self): | |
67 if self._conf: | |
68 return True | |
69 return False | |
70 | |
71 def __eq__(self): | |
72 return self._conf.__eq__() | |
73 | |
74 def __repr__(self): | |
75 return 'RcConf<%s>' % self._conf.__repr__() | |
76 | |
77 def make_config(self, config): | |
78 """ | |
79 Saves given config as a JSON dump in the _conf_name location | |
80 | |
81 :param config: | |
82 :type config: | |
83 """ | |
84 with open(self._conf_name, 'wb') as f: | |
85 json.dump(config, f, indent=4) | |
86 sys.stdout.write('Updated conf\n') | |
87 | |
88 def update_config(self, new_config): | |
89 """ | |
90 Reads the JSON config updates it's values with new_config and | |
91 saves it back as JSON dump | |
92 | |
93 :param new_config: | |
94 """ | |
95 config = {} | |
96 try: | |
97 with open(self._conf_name, 'rb') as conf: | |
98 config = json.load(conf) | |
99 except IOError, e: | |
100 sys.stderr.write(str(e) + '\n') | |
101 | |
102 config.update(new_config) | |
103 self.make_config(config) | |
104 | |
105 def load_config(self): | |
106 """ | |
107 Loads config from file and returns loaded JSON object | |
108 """ | |
109 try: | |
110 with open(self._conf_name, 'rb') as conf: | |
111 return json.load(conf) | |
112 except IOError, e: | |
113 #sys.stderr.write(str(e) + '\n') | |
114 pass | |
115 | |
116 | |
117 def api_call(apikey, apihost, method=None, **kw): | |
118 """ | |
119 Api_call wrapper for RhodeCode | |
120 | |
121 :param apikey: | |
122 :param apihost: | |
123 :param method: | |
124 """ | |
125 def _build_data(random_id): | |
126 """ | |
127 Builds API data with given random ID | |
128 | |
129 :param random_id: | |
130 :type random_id: | |
131 """ | |
132 return { | |
133 "id": random_id, | |
134 "api_key": apikey, | |
135 "method": method, | |
136 "args": kw | |
137 } | |
138 | |
139 if not method: | |
140 raise Exception('please specify method name !') | |
141 id_ = random.randrange(1, 200) | |
142 req = urllib2.Request('%s/_admin/api' % apihost, | |
143 data=json.dumps(_build_data(id_)), | |
144 headers={'content-type': 'text/plain'}) | |
145 print 'calling %s to %s' % (req.get_data(), apihost) | |
146 ret = urllib2.urlopen(req) | |
147 json_data = json.loads(ret.read()) | |
148 id_ret = json_data['id'] | |
149 _formatted_json = pprint.pformat(json_data) | |
150 if id_ret == id_: | |
151 print 'rhodecode said:\n%s' % (_formatted_json) | |
152 else: | |
153 raise Exception('something went wrong. ' | |
154 'ID mismatch got %s, expected %s | %s' % ( | |
155 id_ret, id_, _formatted_json)) | |
156 | |
157 | |
158 def argparser(argv): | |
159 usage = ("rhodecode_api [-h] [--apikey APIKEY] [--apihost APIHOST] " | |
160 "_create_config or METHOD <key:val> <key2:val> ...") | |
161 | |
162 parser = argparse.ArgumentParser(description='RhodeCode API cli', | |
163 usage=usage) | |
164 | |
165 ## config | |
166 group = parser.add_argument_group('config') | |
167 group.add_argument('--apikey', help='api access key') | |
168 group.add_argument('--apihost', help='api host') | |
169 | |
170 group = parser.add_argument_group('API') | |
171 group.add_argument('method', metavar='METHOD', type=str, | |
172 help='API method name to call followed by key:value attributes', | |
173 ) | |
174 | |
175 args, other = parser.parse_known_args() | |
176 return parser, args, other | |
177 | |
178 | |
179 def main(argv=None): | |
180 """ | |
181 Main execution function for cli | |
182 | |
183 :param argv: | |
184 :type argv: | |
185 """ | |
186 if argv is None: | |
187 argv = sys.argv | |
188 | |
189 conf = None | |
190 parser, args, other = argparser(argv) | |
191 | |
192 api_credentials_given = (args.apikey and args.apihost) | |
193 if args.method == '_create_config': | |
194 if not api_credentials_given: | |
195 raise parser.error('_create_config requires --apikey and --apihost') | |
196 conf = RcConf(autocreate=True, config={'apikey': args.apikey, | |
197 'apihost': args.apihost}) | |
198 sys.stdout.write('Create new config in %s\n' % CONFIG_NAME) | |
199 | |
200 if not conf: | |
201 conf = RcConf(autoload=True) | |
202 if not conf: | |
203 if not api_credentials_given: | |
204 parser.error('Could not find config file and missing ' | |
205 '--apikey or --apihost in params') | |
206 | |
207 apikey = args.apikey or conf['apikey'] | |
208 host = args.apihost or conf['apihost'] | |
209 method = args.method | |
210 margs = dict(map(lambda s: s.split(':', 1), other)) | |
211 | |
212 api_call(apikey, host, method, **margs) | |
213 return 0 | |
214 | |
215 if __name__ == '__main__': | |
216 sys.exit(main(sys.argv)) |