Merge lp:~soren/surveilr/extend-client into lp:surveilr
- extend-client
- Merge into trunk
Proposed by
Soren Hansen
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Soren Hansen | ||||
Approved revision: | 29 | ||||
Merged at revision: | 29 | ||||
Proposed branch: | lp:~soren/surveilr/extend-client | ||||
Merge into: | lp:surveilr | ||||
Diff against target: |
701 lines (+448/-98) 4 files modified
surveilr/admin.py (+55/-3) surveilr/api/client.py (+108/-24) surveilr/tests/api/test_client.py (+204/-52) surveilr/tests/test_admin.py (+81/-19) |
||||
To merge this branch: | bzr merge lp:~soren/surveilr/extend-client | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Soren Hansen | Pending | ||
Review via email: mp+90631@code.launchpad.net |
Commit message
Extend client to deal with Services and Metrics, and expose get() and delete() methods.
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'surveilr/admin.py' | |||
2 | --- surveilr/admin.py 2012-01-28 21:09:53 +0000 | |||
3 | +++ surveilr/admin.py 2012-01-29 23:36:23 +0000 | |||
4 | @@ -96,14 +96,63 @@ | |||
5 | 96 | print '--user %s --api_key %s' % (user.user_id, user.key) | 96 | print '--user %s --api_key %s' % (user.user_id, user.key) |
6 | 97 | 97 | ||
7 | 98 | 98 | ||
8 | 99 | class ShowUser(Command): | ||
9 | 100 | def __call__(self): | ||
10 | 101 | user = self.client.get_user(self.args[0]) | ||
11 | 102 | |||
12 | 103 | print 'User:' | ||
13 | 104 | print 'ID:', user.user_id | ||
14 | 105 | print 'Admin:', user.admin | ||
15 | 106 | |||
16 | 107 | |||
17 | 108 | class DeleteUser(Command): | ||
18 | 109 | def __call__(self): | ||
19 | 110 | self.client.delete_user(self.args[0]) | ||
20 | 111 | print 'User deleted' | ||
21 | 112 | |||
22 | 113 | |||
23 | 114 | class ShowService(Command): | ||
24 | 115 | def __call__(self): | ||
25 | 116 | service = self.client.get_service(self.args[0]) | ||
26 | 117 | |||
27 | 118 | print 'Service:' | ||
28 | 119 | print 'ID:', service.id | ||
29 | 120 | print 'Name:', service.name | ||
30 | 121 | print 'Plugins:', service.plugins | ||
31 | 122 | |||
32 | 123 | |||
33 | 124 | class DeleteService(Command): | ||
34 | 125 | def __call__(self): | ||
35 | 126 | self.client.delete_service(self.args[0]) | ||
36 | 127 | print 'Service deleted' | ||
37 | 128 | |||
38 | 129 | |||
39 | 130 | class CreateService(Command): | ||
40 | 131 | def get_optparser(self): | ||
41 | 132 | optparser = super(CreateService, self).get_optparser() | ||
42 | 133 | optparser.add_option('-p', action='append', dest='plugins', | ||
43 | 134 | help='Make the new user an admin') | ||
44 | 135 | return optparser | ||
45 | 136 | |||
46 | 137 | def __call__(self): | ||
47 | 138 | service = self.client.new_service(self.args[0], | ||
48 | 139 | self.options.plugins) | ||
49 | 140 | print 'Service:' | ||
50 | 141 | print 'ID:', service.id | ||
51 | 142 | |||
52 | 143 | |||
53 | 144 | def usage(): | ||
54 | 145 | for cmd_name in commands: | ||
55 | 146 | cmd = commands[cmd_name]() | ||
56 | 147 | print cmd.optparser.get_usage().strip() | ||
57 | 148 | |||
58 | 149 | |||
59 | 99 | def main(argv=None): | 150 | def main(argv=None): |
60 | 100 | if argv is None: # pragma: nocover | 151 | if argv is None: # pragma: nocover |
61 | 101 | argv = sys.argv[1:] | 152 | argv = sys.argv[1:] |
62 | 102 | 153 | ||
63 | 103 | if not len(argv): | 154 | if not len(argv): |
67 | 104 | for cmd_name in commands: | 155 | usage() |
65 | 105 | cmd = commands[cmd_name]() | ||
66 | 106 | print cmd.optparser.get_usage().strip() | ||
68 | 107 | return False | 156 | return False |
69 | 108 | 157 | ||
70 | 109 | if argv[0] in commands: | 158 | if argv[0] in commands: |
71 | @@ -114,6 +163,9 @@ | |||
72 | 114 | except surveilr.api.client.UnauthorizedError: | 163 | except surveilr.api.client.UnauthorizedError: |
73 | 115 | print 'Action not permitted' | 164 | print 'Action not permitted' |
74 | 116 | return False | 165 | return False |
75 | 166 | else: | ||
76 | 167 | usage() | ||
77 | 168 | return False | ||
78 | 117 | 169 | ||
79 | 118 | 170 | ||
80 | 119 | if __name__ == '__main__': # pragma: nocover | 171 | if __name__ == '__main__': # pragma: nocover |
81 | 120 | 172 | ||
82 | === modified file 'surveilr/api/client.py' | |||
83 | --- surveilr/api/client.py 2012-01-28 21:09:53 +0000 | |||
84 | +++ surveilr/api/client.py 2012-01-29 23:36:23 +0000 | |||
85 | @@ -34,8 +34,22 @@ | |||
86 | 34 | self.auth = auth | 34 | self.auth = auth |
87 | 35 | 35 | ||
88 | 36 | def new_user(self, *args, **kwargs): | 36 | def new_user(self, *args, **kwargs): |
91 | 37 | user = User.new(self, *args, **kwargs) | 37 | return User.new(self, *args, **kwargs) |
92 | 38 | return user | 38 | |
93 | 39 | def get_user(self, *args, **kwargs): | ||
94 | 40 | return User.get(self, *args, **kwargs) | ||
95 | 41 | |||
96 | 42 | def delete_user(self, *args, **kwargs): | ||
97 | 43 | return User.delete(self, *args, **kwargs) | ||
98 | 44 | |||
99 | 45 | def new_service(self, *args, **kwargs): | ||
100 | 46 | return Service.new(self, *args, **kwargs) | ||
101 | 47 | |||
102 | 48 | def get_service(self, *args, **kwargs): | ||
103 | 49 | return Service.get(self, *args, **kwargs) | ||
104 | 50 | |||
105 | 51 | def delete_service(self, *args, **kwargs): | ||
106 | 52 | return Service.delete(self, *args, **kwargs) | ||
107 | 39 | 53 | ||
108 | 40 | def send_req(self, url_tail, method, body): | 54 | def send_req(self, url_tail, method, body): |
109 | 41 | http = httplib2.Http() | 55 | http = httplib2.Http() |
110 | @@ -49,13 +63,6 @@ | |||
111 | 49 | raise UnauthorizedError(resp.reason) | 63 | raise UnauthorizedError(resp.reason) |
112 | 50 | return contents | 64 | return contents |
113 | 51 | 65 | ||
114 | 52 | def req(self, obj_type, action, data): | ||
115 | 53 | if action == 'create': | ||
116 | 54 | method = 'POST' | ||
117 | 55 | url_tail = '/%ss' % (obj_type.url_part) | ||
118 | 56 | |||
119 | 57 | return self.send_req(url_tail, method=method, body=json.dumps(data)) | ||
120 | 58 | |||
121 | 59 | 66 | ||
122 | 60 | class SurveilrDirectClient(SurveilrClient): | 67 | class SurveilrDirectClient(SurveilrClient): |
123 | 61 | def __init__(self, *args, **kwargs): | 68 | def __init__(self, *args, **kwargs): |
124 | @@ -73,27 +80,104 @@ | |||
125 | 73 | 80 | ||
126 | 74 | 81 | ||
127 | 75 | class APIObject(object): | 82 | class APIObject(object): |
129 | 76 | def __init__(self, client): | 83 | keys = [] |
130 | 84 | |||
131 | 85 | def __init__(self, client, **kwargs): | ||
132 | 77 | self.client = client | 86 | self.client = client |
136 | 78 | 87 | for key in self.keys: | |
137 | 79 | def req(self, action, data): | 88 | setattr(self, key, kwargs[key]) |
138 | 80 | return self.client.req(type(self), action, data) | 89 | |
139 | 90 | @classmethod | ||
140 | 91 | def req(cls, client, action, data, parent=None): | ||
141 | 92 | if action == 'create': | ||
142 | 93 | kwargs = {'method': 'POST', 'body': json.dumps(data)} | ||
143 | 94 | url_tail = '/%ss' % (cls.url_part) | ||
144 | 95 | elif action == 'get': | ||
145 | 96 | kwargs = {'method': 'GET'} | ||
146 | 97 | url_tail = '/%ss/%s' % (cls.url_part, data) | ||
147 | 98 | elif action == 'delete': | ||
148 | 99 | kwargs = {'method': 'DELETE'} | ||
149 | 100 | url_tail = '/%ss/%s' % (cls.url_part, data) | ||
150 | 101 | |||
151 | 102 | if parent is not None: | ||
152 | 103 | url_tail = parent.instance_url_tail() + url_tail | ||
153 | 104 | |||
154 | 105 | return client.send_req(url_tail, **kwargs) | ||
155 | 106 | |||
156 | 107 | def instance_url_tail(self): | ||
157 | 108 | return '/%ss/%s' % (self.url_part, self.id) | ||
158 | 109 | |||
159 | 110 | @classmethod | ||
160 | 111 | def delete(cls, client, id): | ||
161 | 112 | return cls.req(client, 'delete', id) | ||
162 | 113 | |||
163 | 114 | @classmethod | ||
164 | 115 | def get(cls, client, id): | ||
165 | 116 | return cls.json_deserialise(client, cls.req(client, 'get', id)) | ||
166 | 117 | |||
167 | 118 | def __repr__(self): | ||
168 | 119 | return ('<%s object%s>' % | ||
169 | 120 | (self.__class__.__name__, | ||
170 | 121 | ''.join([', %s=%r' % | ||
171 | 122 | (key, getattr(self, key)) for key in self.keys]))) | ||
172 | 81 | 123 | ||
173 | 82 | 124 | ||
174 | 83 | class User(APIObject): | 125 | class User(APIObject): |
175 | 84 | url_part = 'user' | 126 | url_part = 'user' |
176 | 127 | keys = ['id', 'key', 'admin'] | ||
177 | 85 | 128 | ||
184 | 86 | def __init__(self, client, obj_data=None): | 129 | @classmethod |
185 | 87 | self.client = client | 130 | def json_deserialise(cls, client, s): |
186 | 88 | obj_data = json.loads(obj_data) | 131 | d = json.loads(s) |
187 | 89 | self.user_id = obj_data['id'] | 132 | return cls(client, id=d.get('id'), |
188 | 90 | self.key = obj_data['key'] | 133 | key=d.get('key'), |
189 | 91 | self.admin = obj_data['admin'] | 134 | admin=d.get('admin', False)) |
190 | 92 | 135 | ||
191 | 93 | @classmethod | 136 | @classmethod |
192 | 94 | def new(cls, client, admin=False): | 137 | def new(cls, client, admin=False): |
198 | 95 | return cls(client, client.req(cls, 'create', {'admin': admin})) | 138 | return cls.json_deserialise(client, |
199 | 96 | 139 | cls.req(client, | |
200 | 97 | def __repr__(self): | 140 | 'create', |
201 | 98 | return ('<User object, user_id=%r, key=%r, admin=%r>' % | 141 | {'admin': admin})) |
202 | 99 | (self.user_id, self.key, self.admin)) | 142 | |
203 | 143 | |||
204 | 144 | class Service(APIObject): | ||
205 | 145 | url_part = 'service' | ||
206 | 146 | keys = ['id', 'name', 'plugins'] | ||
207 | 147 | |||
208 | 148 | @classmethod | ||
209 | 149 | def json_deserialise(cls, client, s): | ||
210 | 150 | d = json.loads(s) | ||
211 | 151 | return cls(client, id=d.get('id'), | ||
212 | 152 | name=d.get('name'), | ||
213 | 153 | plugins=d.get('plugins', [])) | ||
214 | 154 | |||
215 | 155 | @classmethod | ||
216 | 156 | def new(cls, client, name, plugins=None): | ||
217 | 157 | return cls.json_deserialise(client, | ||
218 | 158 | cls.req(client, 'create', | ||
219 | 159 | {'name': name, | ||
220 | 160 | 'plugins': plugins})) | ||
221 | 161 | |||
222 | 162 | def new_metric(self, *args, **kwargs): | ||
223 | 163 | return Metric.new(self.client, self, *args, **kwargs) | ||
224 | 164 | |||
225 | 165 | |||
226 | 166 | class Metric(APIObject): | ||
227 | 167 | url_part = 'metric' | ||
228 | 168 | keys = ['id', 'service', 'timestamp', 'metrics'] | ||
229 | 169 | |||
230 | 170 | @classmethod | ||
231 | 171 | def json_deserialise(cls, client, s): | ||
232 | 172 | d = json.loads(s) | ||
233 | 173 | return cls(client, id=d.get('id'), | ||
234 | 174 | service=d.get('service'), | ||
235 | 175 | timestamp=d.get('timestamp'), | ||
236 | 176 | metrics=d.get('metrics')) | ||
237 | 177 | |||
238 | 178 | @classmethod | ||
239 | 179 | def new(cls, client, service, metrics): | ||
240 | 180 | return cls.json_deserialise(client, | ||
241 | 181 | cls.req(client, 'create', | ||
242 | 182 | {'metrics': metrics}, | ||
243 | 183 | parent=service)) | ||
244 | 100 | 184 | ||
245 | === modified file 'surveilr/tests/api/test_client.py' | |||
246 | --- surveilr/tests/api/test_client.py 2012-01-28 21:09:53 +0000 | |||
247 | +++ surveilr/tests/api/test_client.py 2012-01-29 23:36:23 +0000 | |||
248 | @@ -5,7 +5,7 @@ | |||
249 | 5 | from surveilr.api import client | 5 | from surveilr.api import client |
250 | 6 | 6 | ||
251 | 7 | 7 | ||
253 | 8 | class APIClientTests(tests.TestCase): | 8 | class SurveilrClientTests(tests.TestCase): |
254 | 9 | test_url = 'http://somewhere:1234/else' | 9 | test_url = 'http://somewhere:1234/else' |
255 | 10 | test_auth = ('foo', 'bar') | 10 | test_auth = ('foo', 'bar') |
256 | 11 | 11 | ||
257 | @@ -16,19 +16,31 @@ | |||
258 | 16 | auth = self.test_auth | 16 | auth = self.test_auth |
259 | 17 | return client.SurveilrClient(self.test_url, self.test_auth) | 17 | return client.SurveilrClient(self.test_url, self.test_auth) |
260 | 18 | 18 | ||
271 | 19 | @mock.patch('surveilr.api.client.User') | 19 | def test_client_class_actions(self): |
272 | 20 | def test_new_user(self, User): | 20 | """client.{new,get,delete}_{user,service} proxied to class methods""" |
273 | 21 | test_args = ('foo', 'bar', 'baz') | 21 | |
274 | 22 | test_kwargs = {'foo': 'bar', | 22 | for op in ['delete', 'new', 'get']: |
275 | 23 | 'baz': 'wibble'} | 23 | for t in ['User', 'Service']: |
276 | 24 | 24 | @mock.patch('surveilr.api.client.%s' % t) | |
277 | 25 | api_client = self._get_client() | 25 | def test_action(cls): |
278 | 26 | user = api_client.new_user(*test_args, **test_kwargs) | 26 | test_args = ('foo', 'bar', 'baz') |
279 | 27 | User.new.assert_called_with(api_client, *test_args, **test_kwargs) | 27 | test_kwargs = {'foo': 'bar', |
280 | 28 | self.assertEquals(user, User.new.return_value) | 28 | 'baz': 'wibble'} |
281 | 29 | api_client = self._get_client() | ||
282 | 30 | client_obj_func = getattr(api_client, | ||
283 | 31 | '%s_%s' % (op, t.lower())) | ||
284 | 32 | |||
285 | 33 | user = client_obj_func(*test_args, **test_kwargs) | ||
286 | 34 | |||
287 | 35 | cls_func = getattr(cls, op) | ||
288 | 36 | cls_func.assert_called_with(api_client, *test_args, | ||
289 | 37 | **test_kwargs) | ||
290 | 38 | self.assertEquals(user, cls_func.return_value) | ||
291 | 39 | test_action() | ||
292 | 29 | 40 | ||
293 | 30 | @mock.patch('surveilr.api.client.httplib2') | 41 | @mock.patch('surveilr.api.client.httplib2') |
294 | 31 | def test_send_req(self, httplib2): | 42 | def test_send_req(self, httplib2): |
295 | 43 | # Setup | ||
296 | 32 | api_client = self._get_client() | 44 | api_client = self._get_client() |
297 | 33 | 45 | ||
298 | 34 | class FakeResponse(object): | 46 | class FakeResponse(object): |
299 | @@ -37,16 +49,24 @@ | |||
300 | 37 | 49 | ||
301 | 38 | http = httplib2.Http.return_value | 50 | http = httplib2.Http.return_value |
302 | 39 | http.request.return_value = (FakeResponse(200), 'resp') | 51 | http.request.return_value = (FakeResponse(200), 'resp') |
303 | 52 | |||
304 | 53 | # Exercise | ||
305 | 40 | client_response = api_client.send_req('tail', 'METHOD', 'body') | 54 | client_response = api_client.send_req('tail', 'METHOD', 'body') |
306 | 55 | |||
307 | 56 | # Verify that the credentials are passed | ||
308 | 41 | http.add_credentials.assert_called_with(*self.test_auth) | 57 | http.add_credentials.assert_called_with(*self.test_auth) |
309 | 58 | # Verify that the given method is used, the body is passed correctly, | ||
310 | 59 | # and that the url is constructed correctlyi | ||
311 | 42 | http.request.assert_called_with(self.test_url + '/tail', | 60 | http.request.assert_called_with(self.test_url + '/tail', |
312 | 43 | method='METHOD', | 61 | method='METHOD', |
313 | 44 | body='body') | 62 | body='body') |
314 | 45 | 63 | ||
315 | 64 | # Verify that the response comes back intact | ||
316 | 46 | self.assertEquals(client_response, 'resp') | 65 | self.assertEquals(client_response, 'resp') |
317 | 47 | 66 | ||
318 | 48 | @mock.patch('surveilr.api.client.httplib2') | 67 | @mock.patch('surveilr.api.client.httplib2') |
319 | 49 | def test_send_req_403_reraises_unauthorized_error(self, httplib2): | 68 | def test_send_req_403_reraises_unauthorized_error(self, httplib2): |
320 | 69 | # Setup | ||
321 | 50 | api_client = self._get_client() | 70 | api_client = self._get_client() |
322 | 51 | 71 | ||
323 | 52 | class FakeResponse(object): | 72 | class FakeResponse(object): |
324 | @@ -57,58 +77,190 @@ | |||
325 | 57 | 77 | ||
326 | 58 | http = httplib2.Http.return_value | 78 | http = httplib2.Http.return_value |
327 | 59 | http.request.return_value = (FakeResponse(403), 'resp') | 79 | http.request.return_value = (FakeResponse(403), 'resp') |
328 | 80 | |||
329 | 81 | # Exercise and verify | ||
330 | 60 | self.assertRaises(client.UnauthorizedError, | 82 | self.assertRaises(client.UnauthorizedError, |
331 | 61 | api_client.send_req, 'tail', 'METHOD', 'body') | 83 | api_client.send_req, 'tail', 'METHOD', 'body') |
332 | 62 | 84 | ||
343 | 63 | def test_req(self): | 85 | def test_req_create_with_parend(self): |
344 | 64 | api_client = self._get_client() | 86 | api_client = self._get_client() |
345 | 65 | 87 | ||
346 | 66 | test_data = {'foo': ['bar', 'baz', 2]} | 88 | test_data = {'foo': ['bar', 'baz', 2]} |
347 | 67 | 89 | ||
348 | 68 | class FakeObjType(object): | 90 | class FakeObjType(client.APIObject): |
349 | 69 | url_part = 'stuff' | 91 | url_part = 'stuff' |
350 | 70 | 92 | ||
351 | 71 | with mock.patch_object(api_client, 'send_req') as send_req: | 93 | parent = FakeObjType(api_client) |
352 | 72 | api_client.req(FakeObjType(), 'create', test_data) | 94 | parent.id = 7 |
353 | 95 | with mock.patch_object(api_client, 'send_req') as send_req: | ||
354 | 96 | FakeObjType(api_client).req(api_client, 'create', test_data, | ||
355 | 97 | parent=parent) | ||
356 | 98 | self.assertEquals(send_req.call_args[0][0], '/stuffs/7/stuffs') | ||
357 | 99 | self.assertEquals(send_req.call_args[1]['method'], 'POST') | ||
358 | 100 | self.assertEquals(json.loads(send_req.call_args[1]['body']), | ||
359 | 101 | test_data) | ||
360 | 102 | |||
361 | 103 | def test_req_create(self): | ||
362 | 104 | api_client = self._get_client() | ||
363 | 105 | |||
364 | 106 | test_data = {'foo': ['bar', 'baz', 2]} | ||
365 | 107 | |||
366 | 108 | class FakeObjType(client.APIObject): | ||
367 | 109 | url_part = 'stuff' | ||
368 | 110 | |||
369 | 111 | with mock.patch_object(api_client, 'send_req') as send_req: | ||
370 | 112 | FakeObjType(api_client).req(api_client, 'create', test_data) | ||
371 | 73 | self.assertEquals(send_req.call_args[0][0], '/stuffs') | 113 | self.assertEquals(send_req.call_args[0][0], '/stuffs') |
372 | 74 | self.assertEquals(send_req.call_args[1]['method'], 'POST') | 114 | self.assertEquals(send_req.call_args[1]['method'], 'POST') |
373 | 75 | self.assertEquals(json.loads(send_req.call_args[1]['body']), | 115 | self.assertEquals(json.loads(send_req.call_args[1]['body']), |
374 | 76 | test_data) | 116 | test_data) |
375 | 77 | 117 | ||
377 | 78 | def test_apiobject(self): | 118 | def test_req_get(self): |
378 | 119 | api_client = self._get_client() | ||
379 | 120 | |||
380 | 121 | class FakeObjType(client.APIObject): | ||
381 | 122 | url_part = 'stuff' | ||
382 | 123 | |||
383 | 124 | with mock.patch_object(api_client, 'send_req') as send_req: | ||
384 | 125 | FakeObjType(api_client).req(api_client, 'get', 'someid') | ||
385 | 126 | self.assertEquals(send_req.call_args[0][0], '/stuffs/someid') | ||
386 | 127 | self.assertEquals(send_req.call_args[1]['method'], 'GET') | ||
387 | 128 | |||
388 | 129 | def test_req_delete(self): | ||
389 | 130 | api_client = self._get_client() | ||
390 | 131 | |||
391 | 132 | class FakeObjType(client.APIObject): | ||
392 | 133 | url_part = 'stuff' | ||
393 | 134 | |||
394 | 135 | with mock.patch_object(api_client, 'send_req') as send_req: | ||
395 | 136 | FakeObjType(api_client).req(api_client, 'delete', 'someid') | ||
396 | 137 | self.assertEquals(send_req.call_args[0][0], '/stuffs/someid') | ||
397 | 138 | self.assertEquals(send_req.call_args[1]['method'], 'DELETE') | ||
398 | 139 | |||
399 | 140 | |||
400 | 141 | class APIObjectTests(tests.TestCase): | ||
401 | 142 | def _test_req(self): | ||
402 | 79 | client_obj = mock.Mock() | 143 | client_obj = mock.Mock() |
403 | 80 | data = mock.Sentinel() | 144 | data = mock.Sentinel() |
404 | 81 | 145 | ||
405 | 82 | class TestObject(client.APIObject): | 146 | class TestObject(client.APIObject): |
407 | 83 | pass | 147 | url_part = 'test' |
408 | 84 | 148 | ||
409 | 85 | obj = TestObject(client_obj) | 149 | obj = TestObject(client_obj) |
410 | 86 | obj.req('ACTION', data) | 150 | obj.req('ACTION', data) |
411 | 87 | 151 | ||
412 | 88 | client_obj.req.assert_called_with(TestObject, 'ACTION', data) | 152 | client_obj.req.assert_called_with(TestObject, 'ACTION', data) |
413 | 89 | 153 | ||
419 | 90 | 154 | def _test_get_or_delete(self, op, req_return=None): | |
420 | 91 | class APITypeTests(tests.TestCase): | 155 | client_obj = mock.Mock() |
421 | 92 | def _test_user_new(self, admin): | 156 | |
422 | 93 | client_obj = mock.Mock() | 157 | class TestObject(client.APIObject): |
423 | 94 | client_obj.req.return_value = json.dumps({'id': 'testid', | 158 | url_part = 'test' |
424 | 159 | |||
425 | 160 | @classmethod | ||
426 | 161 | def json_deserialise(inner_self, client, s): | ||
427 | 162 | self.assertEquals(s, 'lots of json') | ||
428 | 163 | |||
429 | 164 | req = mock.Mock() | ||
430 | 165 | |||
431 | 166 | TestObject.req.return_value = req_return | ||
432 | 167 | |||
433 | 168 | getattr(TestObject, op)(client_obj, 'testid') | ||
434 | 169 | TestObject.req.assert_called_with(client_obj, op, 'testid') | ||
435 | 170 | |||
436 | 171 | def test_delete(self): | ||
437 | 172 | self._test_get_or_delete('delete') | ||
438 | 173 | |||
439 | 174 | def test_get(self): | ||
440 | 175 | self._test_get_or_delete('get', 'lots of json') | ||
441 | 176 | |||
442 | 177 | |||
443 | 178 | class UserTests(tests.TestCase): | ||
444 | 179 | def _test_new(self, admin): | ||
445 | 180 | # Setup | ||
446 | 181 | client_obj = mock.Mock() | ||
447 | 182 | with mock.patch_object(client.User, 'req') as client_req: | ||
448 | 183 | client_req.return_value = json.dumps({'id': 'testid', | ||
449 | 95 | 'key': 'testkey', | 184 | 'key': 'testkey', |
450 | 96 | 'admin': admin}) | 185 | 'admin': admin}) |
453 | 97 | user = client.User.new(client_obj) | 186 | |
454 | 98 | client_obj.req.assert_called_with(client.User, 'create', | 187 | # Exercise |
455 | 188 | user = client.User.new(client_obj) | ||
456 | 189 | |||
457 | 190 | # Verify | ||
458 | 191 | client_req.assert_called_with(client_obj, 'create', | ||
459 | 99 | {'admin': False}) | 192 | {'admin': False}) |
460 | 100 | 193 | ||
466 | 101 | self.assertEquals(user.user_id, 'testid') | 194 | self.assertEquals(user.id, 'testid') |
467 | 102 | self.assertEquals(user.key, 'testkey') | 195 | self.assertEquals(user.key, 'testkey') |
468 | 103 | self.assertEquals(user.admin, admin) | 196 | self.assertEquals(user.admin, admin) |
469 | 104 | self.assertEquals(repr(user), "<User object, user_id=u'testid', " | 197 | self.assertEquals(repr(user), "<User object, id=u'testid', " |
470 | 105 | "key=u'testkey', admin=%r>" % user.admin) | 198 | "key=u'testkey', admin=%r>" % |
471 | 199 | user.admin) | ||
472 | 106 | 200 | ||
473 | 107 | def test_user_new_admin(self): | 201 | def test_user_new_admin(self): |
475 | 108 | self._test_user_new(True) | 202 | self._test_new(True) |
476 | 109 | 203 | ||
477 | 110 | def test_user_new_not_admin(self): | 204 | def test_user_new_not_admin(self): |
479 | 111 | self._test_user_new(False) | 205 | self._test_new(False) |
480 | 206 | |||
481 | 207 | |||
482 | 208 | class ServiceTests(tests.TestCase): | ||
483 | 209 | def test_new(self): | ||
484 | 210 | # Setup | ||
485 | 211 | test_plugins = ['http://h:1/p'] | ||
486 | 212 | client_obj = mock.Mock() | ||
487 | 213 | with mock.patch_object(client.Service, 'req') as service_req: | ||
488 | 214 | service_req.return_value = json.dumps({'id': 'testid', | ||
489 | 215 | 'name': 'testname', | ||
490 | 216 | 'plugins': test_plugins}) | ||
491 | 217 | |||
492 | 218 | # Exercise | ||
493 | 219 | service = client.Service.new(client_obj, 'testname', | ||
494 | 220 | plugins=test_plugins) | ||
495 | 221 | |||
496 | 222 | # Verify | ||
497 | 223 | service_req.assert_called_with(client_obj, 'create', | ||
498 | 224 | {'name': 'testname', | ||
499 | 225 | 'plugins': test_plugins}) | ||
500 | 226 | |||
501 | 227 | self.assertEquals(service.id, 'testid') | ||
502 | 228 | self.assertEquals(service.name, 'testname') | ||
503 | 229 | self.assertEquals(service.plugins, test_plugins) | ||
504 | 230 | self.assertEquals(repr(service), "<Service object, id=u'testid', " | ||
505 | 231 | "name=u'testname', " | ||
506 | 232 | "plugins=[u'http://h:1/p']>") | ||
507 | 233 | |||
508 | 234 | |||
509 | 235 | class MetricTests(tests.TestCase): | ||
510 | 236 | def test_service_metric_new(self): | ||
511 | 237 | # Setup | ||
512 | 238 | client_obj = mock.Mock() | ||
513 | 239 | service_obj = client.Service(client_obj, id='testid', | ||
514 | 240 | name='testname', plugins=[]) | ||
515 | 241 | |||
516 | 242 | with mock.patch_object(client, 'Metric') as Metric: | ||
517 | 243 | service_obj.new_metric({'foo': 1234}) | ||
518 | 244 | |||
519 | 245 | Metric.new.assert_called_with(client_obj, service_obj, | ||
520 | 246 | {'foo': 1234}) | ||
521 | 247 | |||
522 | 248 | |||
523 | 249 | def test_new(self): | ||
524 | 250 | # Setup | ||
525 | 251 | client_obj = mock.Mock() | ||
526 | 252 | service_obj = mock.Sentinel() | ||
527 | 253 | with mock.patch_object(client.Metric, 'req') as metric_req: | ||
528 | 254 | metric_req.return_value = json.dumps({}) | ||
529 | 255 | |||
530 | 256 | # Exercise | ||
531 | 257 | client.Metric.new(client_obj, service_obj, {'something': 1234}) | ||
532 | 258 | |||
533 | 259 | # Verify | ||
534 | 260 | metric_req.assert_called_with(client_obj, | ||
535 | 261 | 'create', | ||
536 | 262 | {'metrics': {'something': 1234}}, | ||
537 | 263 | parent=service_obj) | ||
538 | 112 | 264 | ||
539 | 113 | 265 | ||
540 | 114 | class DirectClientTests(tests.TestCase): | 266 | class DirectClientTests(tests.TestCase): |
541 | @@ -122,18 +274,18 @@ | |||
542 | 122 | from webob import Request | 274 | from webob import Request |
543 | 123 | 275 | ||
544 | 124 | api_client = client.SurveilrDirectClient({}) | 276 | api_client = client.SurveilrDirectClient({}) |
560 | 125 | api_client.app = mock.Mock() | 277 | with mock.patch_object(api_client, 'app') as app: |
561 | 126 | response = mock.Mock() | 278 | response = mock.Mock() |
562 | 127 | response.body = 'response' | 279 | response.body = 'response' |
563 | 128 | api_client.app.return_value = response | 280 | app.return_value = response |
564 | 129 | 281 | ||
565 | 130 | client_response = api_client.send_req('tail', 'METHOD', 'body') | 282 | client_response = api_client.send_req('tail', 'METHOD', 'body') |
566 | 131 | 283 | ||
567 | 132 | args = api_client.app.call_args[0] | 284 | args = app.call_args[0] |
568 | 133 | self.assertEquals(type(args[0]), Request) | 285 | self.assertEquals(type(args[0]), Request) |
569 | 134 | 286 | ||
570 | 135 | req = args[0] | 287 | req = args[0] |
571 | 136 | self.assertEquals(req.path, 'tail') | 288 | self.assertEquals(req.path, 'tail') |
572 | 137 | self.assertEquals(req.method, 'METHOD') | 289 | self.assertEquals(req.method, 'METHOD') |
573 | 138 | self.assertEquals(req.body, 'body') | 290 | self.assertEquals(req.body, 'body') |
574 | 139 | self.assertEquals(client_response, 'response') | 291 | self.assertEquals(client_response, 'response') |
575 | 140 | 292 | ||
576 | === modified file 'surveilr/tests/test_admin.py' | |||
577 | --- surveilr/tests/test_admin.py 2012-01-28 21:09:53 +0000 | |||
578 | +++ surveilr/tests/test_admin.py 2012-01-29 23:36:23 +0000 | |||
579 | @@ -126,24 +126,6 @@ | |||
580 | 126 | 126 | ||
581 | 127 | self.assertIsNone(auth) | 127 | self.assertIsNone(auth) |
582 | 128 | 128 | ||
583 | 129 | def test_CreateUser_admin(self): | ||
584 | 130 | create_user = admin.CreateUser() | ||
585 | 131 | |||
586 | 132 | create_user.init(['--admin']) | ||
587 | 133 | create_user.client = mock.Mock() | ||
588 | 134 | create_user() | ||
589 | 135 | |||
590 | 136 | create_user.client.new_user.assert_called_with(admin=True) | ||
591 | 137 | |||
592 | 138 | def test_CreateUser_non_admin(self): | ||
593 | 139 | create_user = admin.CreateUser() | ||
594 | 140 | |||
595 | 141 | create_user.init([]) | ||
596 | 142 | create_user.client = mock.Mock() | ||
597 | 143 | create_user() | ||
598 | 144 | |||
599 | 145 | create_user.client.new_user.assert_called_with(admin=False) | ||
600 | 146 | |||
601 | 147 | def _replace_stdout_with_stringio(self): | 129 | def _replace_stdout_with_stringio(self): |
602 | 148 | saved_stdout = sys.stdout | 130 | saved_stdout = sys.stdout |
603 | 149 | 131 | ||
604 | @@ -163,12 +145,23 @@ | |||
605 | 163 | self.assertEquals(sys.stdout.getvalue(), | 145 | self.assertEquals(sys.stdout.getvalue(), |
606 | 164 | 'Action not permitted\n') | 146 | 'Action not permitted\n') |
607 | 165 | 147 | ||
609 | 166 | def test_cmd_list(self): | 148 | def test_cmd_list_if_no_command_given(self): |
610 | 167 | self._replace_stdout_with_stringio() | 149 | self._replace_stdout_with_stringio() |
611 | 168 | ret = admin.main([]) | 150 | ret = admin.main([]) |
612 | 169 | 151 | ||
613 | 170 | self.assertEquals(ret, False) | 152 | self.assertEquals(ret, False) |
614 | 171 | stdout = sys.stdout.getvalue() | 153 | stdout = sys.stdout.getvalue() |
615 | 154 | self._check_cmd_list(stdout) | ||
616 | 155 | |||
617 | 156 | def test_cmd_list_if_invalid_command_given(self): | ||
618 | 157 | self._replace_stdout_with_stringio() | ||
619 | 158 | ret = admin.main(['this is not a valid command']) | ||
620 | 159 | |||
621 | 160 | self.assertEquals(ret, False) | ||
622 | 161 | stdout = sys.stdout.getvalue() | ||
623 | 162 | self._check_cmd_list(stdout) | ||
624 | 163 | |||
625 | 164 | def _check_cmd_list(self, stdout): | ||
626 | 172 | self.assertEquals(len(stdout.split('\n')) - 1, len(admin.commands)) | 165 | self.assertEquals(len(stdout.split('\n')) - 1, len(admin.commands)) |
627 | 173 | 166 | ||
628 | 174 | expected_commands = set(admin.commands.keys()) | 167 | expected_commands = set(admin.commands.keys()) |
629 | @@ -180,3 +173,72 @@ | |||
630 | 180 | found_commands.add(cmd) | 173 | found_commands.add(cmd) |
631 | 181 | 174 | ||
632 | 182 | self.assertEquals(expected_commands, found_commands) | 175 | self.assertEquals(expected_commands, found_commands) |
633 | 176 | |||
634 | 177 | def test_CreateUser_admin(self): | ||
635 | 178 | create_user = admin.CreateUser() | ||
636 | 179 | |||
637 | 180 | create_user.init(['--admin']) | ||
638 | 181 | create_user.client = mock.Mock() | ||
639 | 182 | create_user() | ||
640 | 183 | |||
641 | 184 | create_user.client.new_user.assert_called_with(admin=True) | ||
642 | 185 | |||
643 | 186 | def test_CreateUser_non_admin(self): | ||
644 | 187 | create_user = admin.CreateUser() | ||
645 | 188 | |||
646 | 189 | create_user.init([]) | ||
647 | 190 | create_user.client = mock.Mock() | ||
648 | 191 | create_user() | ||
649 | 192 | |||
650 | 193 | create_user.client.new_user.assert_called_with(admin=False) | ||
651 | 194 | |||
652 | 195 | def test_CreateService_no_plugins(self): | ||
653 | 196 | create_service = admin.CreateService() | ||
654 | 197 | |||
655 | 198 | create_service.init(['servicename']) | ||
656 | 199 | create_service.client = mock.Mock() | ||
657 | 200 | create_service() | ||
658 | 201 | |||
659 | 202 | create_service.client.new_service.assert_called_with('servicename', | ||
660 | 203 | None) | ||
661 | 204 | |||
662 | 205 | def test_CreateService_with_plugins(self): | ||
663 | 206 | create_service = admin.CreateService() | ||
664 | 207 | |||
665 | 208 | plugins = ['http://foo/bar', 'http://baz/wibble'] | ||
666 | 209 | |||
667 | 210 | args = ['servicename'] | ||
668 | 211 | for plugin in plugins: | ||
669 | 212 | args += ['-p', plugin] | ||
670 | 213 | |||
671 | 214 | create_service.init(args) | ||
672 | 215 | create_service.client = mock.Mock() | ||
673 | 216 | create_service() | ||
674 | 217 | |||
675 | 218 | create_service.client.new_service.assert_called_with('servicename', | ||
676 | 219 | plugins) | ||
677 | 220 | |||
678 | 221 | def test_ShowUser(self): | ||
679 | 222 | self._test_Show_or_Delete('show', 'user') | ||
680 | 223 | |||
681 | 224 | def test_ShowService(self): | ||
682 | 225 | self._test_Show_or_Delete('show', 'service') | ||
683 | 226 | |||
684 | 227 | def test_DeleteUser(self): | ||
685 | 228 | self._test_Show_or_Delete('delete', 'user') | ||
686 | 229 | |||
687 | 230 | def test_DeleteService(self): | ||
688 | 231 | self._test_Show_or_Delete('delete', 'service') | ||
689 | 232 | |||
690 | 233 | def _test_Show_or_Delete(self, show_or_delete, type_name): | ||
691 | 234 | cmd = getattr(admin, '%s%s' % (show_or_delete.capitalize(), | ||
692 | 235 | type_name.capitalize()))() | ||
693 | 236 | |||
694 | 237 | cmd.init(['testid']) | ||
695 | 238 | cmd.client = mock.Mock() | ||
696 | 239 | cmd() | ||
697 | 240 | |||
698 | 241 | method_prefix = show_or_delete == 'show' and 'get' or 'delete' | ||
699 | 242 | method_name = '%s_%s' % (method_prefix, type_name) | ||
700 | 243 | method = getattr(cmd.client, method_name) | ||
701 | 244 | method.assert_called_with('testid') |