blob: 495d1277c1b6374c185973b2860599c14cec8d68 [file] [log] [blame]
nh202bc67bb192018-06-29 17:07:50 -07001# Copyright 2018 AT&T Corporation.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16import fixtures
17
18from oslo_serialization import jsonutils as json
19from tempest import clients
20from tempest.cmd import cleanup_service
21from tempest import config
22from tempest.tests import base
23from tempest.tests import fake_config
24from tempest.tests.lib import fake_credentials
25from tempest.tests.lib import fake_http
26
27
28class MockFunctionsBase(base.TestCase):
29
30 def _create_response(self, body, status, headers):
31 if status:
32 if body:
33 body = json.dumps(body)
34 resp = fake_http.fake_http_response(headers, status=status), body
35 return resp
36 else:
37 return body
38
39 def _create_fixtures(self, fixtures_to_make):
40 mocked_fixtures = []
41 for fixture in fixtures_to_make:
42 func, body, status = fixture
43 mocked_response = self._create_response(body, status, None)
44 if mocked_response == 'error':
45 mocked_func = self.useFixture(fixtures.MockPatch(
46 func, side_effect=Exception("error")))
47 else:
48 mocked_func = self.useFixture(fixtures.MockPatch(
49 func, return_value=mocked_response))
50 mocked_fixtures.append(mocked_func)
51 return mocked_fixtures
52
53 def run_function_with_mocks(self, function_to_run, functions_to_mock):
54 """Mock a service client function for testing.
55
56 :param function_to_run: The service client function to call.
57 :param functions_to_mock: a list of tuples containing the function
58 to mock, the response body, and the response status.
59 EX:
60 ('tempest.lib.common.rest_client.RestClient.get',
61 {'users': ['']},
62 200)
63 """
64 mocked_fixtures = self._create_fixtures(functions_to_mock)
65 func_return = function_to_run()
66 return func_return, mocked_fixtures
67
68
69class BaseCmdServiceTests(MockFunctionsBase):
70
71 def setUp(self):
72 super(BaseCmdServiceTests, self).setUp()
73 self.useFixture(fake_config.ConfigFixture())
74 self.patchobject(config, 'TempestConfigPrivate',
75 fake_config.FakePrivate)
76 self.useFixture(fixtures.MockPatch(
77 'tempest.cmd.cleanup_service._get_network_id',
78 return_value=''))
79 cleanup_service.init_conf()
80 self.conf_values = {"flavors": cleanup_service.CONF_FLAVORS[0],
81 "images": cleanup_service.CONF_IMAGES[0],
82 "projects": cleanup_service.CONF_PROJECTS[0],
83 "users": cleanup_service.CONF_USERS[0],
84 }
85
86 # Static list to ensure global service saved items are not deleted
87 saved_state = {"users": {u'32rwef64245tgr20121qw324bgg': u'Lightning'},
88 "flavors": {u'42': u'm1.tiny'},
89 "images": {u'34yhwr-4t3q': u'stratus-0.3.2-x86_64-disk'},
90 "roles": {u'3efrt74r45hn': u'president'},
91 "projects": {u'f38ohgp93jj032': u'manhattan'},
92 "domains": {u'default': u'Default'}
93 }
94 # Mocked methods
95 get_method = 'tempest.lib.common.rest_client.RestClient.get'
96 delete_method = 'tempest.lib.common.rest_client.RestClient.delete'
97 log_method = 'tempest.cmd.cleanup_service.LOG.exception'
98 # Override parameters
99 service_class = 'BaseService'
100 response = None
101 service_name = 'default'
102
103 def _create_cmd_service(self, service_type, is_save_state=False,
104 is_preserve=False, is_dry_run=False):
105 creds = fake_credentials.FakeKeystoneV3Credentials()
106 os = clients.Manager(creds)
107 return getattr(cleanup_service, service_type)(
108 os,
109 is_save_state=is_save_state,
110 is_preserve=is_preserve,
111 is_dry_run=is_dry_run,
112 data={},
113 saved_state_json=self.saved_state
114 )
115
116 def _test_delete(self, mocked_fixture_tuple_list, fail=False):
117 serv = self._create_cmd_service(self.service_class)
118 resp, fixtures = self.run_function_with_mocks(
119 serv.run,
120 mocked_fixture_tuple_list,
121 )
122 for fixture in fixtures:
123 if fail is False and fixture.mock.return_value == 'exception':
124 fixture.mock.assert_not_called()
125 elif self.service_name in self.saved_state.keys():
126 fixture.mock.assert_called_once()
127 for key in self.saved_state[self.service_name].keys():
128 self.assertNotIn(key, fixture.mock.call_args[0][0])
129 else:
130 fixture.mock.assert_called_once()
131 self.assertFalse(serv.data)
132
133 def _test_dry_run_true(self, mocked_fixture_tuple_list):
134 serv = self._create_cmd_service(self.service_class, is_dry_run=True)
135 _, fixtures = self.run_function_with_mocks(
136 serv.run,
137 mocked_fixture_tuple_list
138 )
139 for fixture in fixtures:
140 if fixture.mock.return_value == 'delete':
141 fixture.mock.assert_not_called()
142 elif self.service_name in self.saved_state.keys():
143 fixture.mock.assert_called_once()
144 for key in self.saved_state[self.service_name].keys():
145 self.assertNotIn(key, fixture.mock.call_args[0][0])
146 else:
147 fixture.mock.assert_called_once()
148
149 def _test_saved_state_true(self, mocked_fixture_tuple_list):
150 serv = self._create_cmd_service(self.service_class, is_save_state=True)
151 _, fixtures = self.run_function_with_mocks(
152 serv.run,
153 mocked_fixture_tuple_list
154 )
155 for item in self.response[self.service_name]:
156 self.assertIn(item['id'],
157 serv.data[self.service_name])
158 for fixture in fixtures:
159 fixture.mock.assert_called_once()
160
161 def _test_is_preserve_true(self, mocked_fixture_tuple_list):
162 serv = self._create_cmd_service(self.service_class, is_preserve=True)
163 resp, fixtures = self.run_function_with_mocks(
164 serv.list,
165 mocked_fixture_tuple_list
166 )
167 for fixture in fixtures:
168 fixture.mock.assert_called_once()
169 self.assertIn(resp[0], self.response[self.service_name])
170 for rsp in resp:
171 self.assertNotIn(rsp['id'], self.conf_values.values())
172 self.assertNotIn(rsp['name'], self.conf_values.values())
173
174
175class TestDomainService(BaseCmdServiceTests):
176
177 service_class = 'DomainService'
178 service_name = 'domains'
179 response = {
180 "domains": [
181 {
182 "description": "Destroy all humans",
183 "enabled": True,
184 "id": "5a75994a3",
185 "links": {
186 "self": "http://example.com/identity/v3/domains/5a75994a3"
187 },
188 "name": "Sky_net"
189 },
190 {
191 "description": "Owns users and tenants on Identity API",
192 "enabled": False,
193 "id": "default",
194 "links": {
195 "self": "http://example.com/identity/v3/domains/default"
196 },
197 "name": "Default"
198 }
199 ]
200 }
201
202 mock_update = ("tempest.lib.services.identity.v3."
203 "domains_client.DomainsClient.update_domain")
204
205 def test_delete_fail(self):
206 delete_mock = [(self.get_method, self.response, 200),
207 (self.delete_method, 'error', None),
208 (self.log_method, 'exception', None),
209 (self.mock_update, 'update', None)]
210 self._test_delete(delete_mock, fail=True)
211
212 def test_delete_pass(self):
213 delete_mock = [(self.get_method, self.response, 200),
214 (self.delete_method, None, 204),
215 (self.log_method, 'exception', None),
216 (self.mock_update, 'update', None)]
217 self._test_delete(delete_mock)
218
219 def test_dry_run(self):
220 dry_mock = [(self.get_method, self.response, 200),
221 (self.delete_method, "delete", None)]
222 self._test_dry_run_true(dry_mock)
223
224 def test_save_state(self):
225 self._test_saved_state_true([(self.get_method, self.response, 200)])
226
227
228class TestProjectsService(BaseCmdServiceTests):
229
230 service_class = 'ProjectService'
231 service_name = 'projects'
232 response = {
233 "projects": [
234 {
235 "is_domain": False,
236 "description": None,
237 "domain_id": "default",
238 "enabled": True,
239 "id": "f38ohgp93jj032",
240 "links": {
241 "self": "http://example.com/identity/v3/projects"
242 "/f38ohgp93jj032"
243 },
244 "name": "manhattan",
245 "parent_id": None
246 },
247 {
248 "is_domain": False,
249 "description": None,
250 "domain_id": "default",
251 "enabled": True,
252 "id": "098f89d3292ri4jf4",
253 "links": {
254 "self": "http://example.com/identity/v3/projects"
255 "/098f89d3292ri4jf4"
256 },
257 "name": "Apollo",
258 "parent_id": None
259 }
260 ]
261 }
262
263 def test_delete_fail(self):
264 delete_mock = [(self.get_method, self.response, 200),
265 (self.delete_method, 'error', None),
266 (self.log_method, 'exception', None)]
267 self._test_delete(delete_mock, fail=True)
268
269 def test_delete_pass(self):
270 delete_mock = [(self.get_method, self.response, 200),
271 (self.delete_method, None, 204),
272 (self.log_method, 'exception', None)]
273 self._test_delete(delete_mock)
274
275 def test_dry_run(self):
276 dry_mock = [(self.get_method, self.response, 200),
277 (self.delete_method, "delete", None)]
278 self._test_dry_run_true(dry_mock)
279
280 def test_save_state(self):
281 self._test_saved_state_true([(self.get_method, self.response, 200)])
282
283 def test_preserve_list(self):
284 self.response['projects'].append(
285 {
286 "is_domain": False,
287 "description": None,
288 "domain_id": "default",
289 "enabled": True,
290 "id": "r343q98h09f3092",
291 "links": {
292 "self": "http://example.com/identity/v3/projects"
293 "/r343q98h09f3092"
294 },
295 "name": cleanup_service.CONF_PROJECTS[0],
296 "parent_id": None
297 })
298 self._test_is_preserve_true([(self.get_method, self.response, 200)])
299
300
301class TestImagesService(BaseCmdServiceTests):
302
303 service_class = 'ImageService'
304 service_name = 'images'
305 response = {
306 "images": [
307 {
308 "status": "ACTIVE",
309 "name": "stratus-0.3.2-x86_64-disk",
310 "id": "34yhwr-4t3q",
311 "updated": "2014-11-03T16:40:10Z",
312 "links": [{
313 "href": "http://openstack.ex.com/v2/openstack/images/"
314 "34yhwr-4t3q",
315 "rel": "self"}],
316 "created": "2014-10-30T08:23:39Z",
317 "minDisk": 0,
318 "minRam": 0,
319 "progress": 0,
320 "metadata": {},
321 },
322 {
323 "status": "ACTIVE",
324 "name": "cirros-0.3.2-x86_64-disk",
325 "id": "1bea47ed-f6a9",
326 "updated": "2014-11-03T16:40:10Z",
327 "links": [{
328 "href": "http://openstack.ex.com/v2/openstack/images/"
329 "1bea47ed-f6a9",
330 "rel": "self"}],
331 "created": "2014-10-30T08:23:39Z",
332 "minDisk": 0,
333 "minRam": 0,
334 "progress": 0,
335 "metadata": {},
336 }
337 ]
338 }
339
340 def test_delete_fail(self):
341 delete_mock = [(self.get_method, self.response, 200),
342 (self.delete_method, 'error', None),
343 (self.log_method, 'exception', None)]
344 self._test_delete(delete_mock, fail=True)
345
346 def test_delete_pass(self):
347 delete_mock = [(self.get_method, self.response, 200),
348 (self.delete_method, None, 204),
349 (self.log_method, 'exception', None)]
350 self._test_delete(delete_mock)
351
352 def test_dry_run(self):
353 dry_mock = [(self.get_method, self.response, 200),
354 (self.delete_method, "delete", None)]
355 self._test_dry_run_true(dry_mock)
356
357 def test_save_state(self):
358 self._test_saved_state_true([(self.get_method, self.response, 200)])
359
360 def test_preserve_list(self):
361 self.response['images'].append(
362 {
363 "status": "ACTIVE",
364 "name": "cirros-0.3.2-x86_64-disk",
365 "id": cleanup_service.CONF_IMAGES[0],
366 "updated": "2014-11-03T16:40:10Z",
367 "links": [{
368 "href": "http://openstack.ex.com/v2/openstack/images/"
369 "None",
370 "rel": "self"}],
371 "created": "2014-10-30T08:23:39Z",
372 "minDisk": 0,
373 "minRam": 0,
374 "progress": 0,
375 "metadata": {},
376 })
377 self._test_is_preserve_true([(self.get_method, self.response, 200)])
378
379
380class TestFlavorService(BaseCmdServiceTests):
381
382 service_class = 'FlavorService'
383 service_name = 'flavors'
384 response = {
385 "flavors": [
386 {
387 "disk": 1,
388 "id": "42",
389 "links": [{
390 "href": "http://openstack.ex.com/v2/openstack/flavors/1",
391 "rel": "self"}, {
392 "href": "http://openstack.ex.com/openstack/flavors/1",
393 "rel": "bookmark"}],
394 "name": "m1.tiny",
395 "ram": 512,
396 "swap": 1,
397 "vcpus": 1
398 },
399 {
400 "disk": 2,
401 "id": "13",
402 "links": [{
403 "href": "http://openstack.ex.com/v2/openstack/flavors/2",
404 "rel": "self"}, {
405 "href": "http://openstack.ex.com/openstack/flavors/2",
406 "rel": "bookmark"}],
407 "name": "m1.tiny",
408 "ram": 512,
409 "swap": 1,
410 "vcpus": 1
411 }
412 ]
413 }
414
415 def test_delete_fail(self):
416 delete_mock = [(self.get_method, self.response, 200),
417 (self.delete_method, 'error', None),
418 (self.log_method, 'exception', None)]
419 self._test_delete(delete_mock, fail=True)
420
421 def test_delete_pass(self):
422 delete_mock = [(self.get_method, self.response, 200),
423 (self.delete_method, None, 202),
424 (self.log_method, 'exception', None)]
425 self._test_delete(delete_mock)
426
427 def test_dry_run(self):
428 dry_mock = [(self.get_method, self.response, 200),
429 (self.delete_method, "delete", None)]
430 self._test_dry_run_true(dry_mock)
431
432 def test_save_state(self):
433 self._test_saved_state_true([(self.get_method, self.response, 200)])
434
435 def test_preserve_list(self):
436 self.response['flavors'].append(
437 {
438 "disk": 3,
439 "id": cleanup_service.CONF_FLAVORS[0],
440 "links": [{
441 "href": "http://openstack.ex.com/v2/openstack/flavors/3",
442 "rel": "self"}, {
443 "href": "http://openstack.ex.com/openstack/flavors/3",
444 "rel": "bookmark"}],
445 "name": "m1.tiny",
446 "ram": 512,
447 "swap": 1,
448 "vcpus": 1
449 })
450 self._test_is_preserve_true([(self.get_method, self.response, 200)])
451
452
453class TestRoleService(BaseCmdServiceTests):
454
455 service_class = 'RoleService'
456 service_name = 'roles'
457 response = {
458 "roles": [
459 {
460 "domain_id": "FakeDomain",
461 "id": "3efrt74r45hn",
462 "name": "president",
463 "links": {
464 "self": "http://ex.com/identity/v3/roles/3efrt74r45hn"
465 }
466 },
467 {
468 "domain_id": 'FakeDomain',
469 "id": "39ruo5sdk040",
470 "name": "vice-p",
471 "links": {
472 "self": "http://ex.com/identity/v3/roles/39ruo5sdk040"
473 }
474 }
475 ]
476 }
477
478 def test_delete_fail(self):
479 delete_mock = [(self.get_method, self.response, 200),
480 (self.delete_method, 'error', None),
481 (self.log_method, 'exception', None)]
482 self._test_delete(delete_mock, fail=True)
483
484 def test_delete_pass(self):
485 delete_mock = [(self.get_method, self.response, 200),
486 (self.delete_method, None, 204),
487 (self.log_method, 'exception', None)]
488 self._test_delete(delete_mock)
489
490 def test_dry_run(self):
491 dry_mock = [(self.get_method, self.response, 200),
492 (self.delete_method, "delete", None)]
493 self._test_dry_run_true(dry_mock)
494
495 def test_save_state(self):
496 self._test_saved_state_true([(self.get_method, self.response, 200)])
497
498
499class TestUserService(BaseCmdServiceTests):
500
501 service_class = 'UserService'
502 service_name = 'users'
503 response = {
504 "users": [
505 {
506 "domain_id": "TempestDomain",
507 "enabled": True,
508 "id": "e812fb332456423fdv1b1320121qwe2",
509 "links": {
510 "self": "http://example.com/identity/v3/users/"
511 "e812fb332456423fdv1b1320121qwe2",
512 },
513 "name": "Thunder",
514 "password_expires_at": "3102-11-06T15:32:17.000000",
515 },
516 {
517 "domain_id": "TempestDomain",
518 "enabled": True,
519 "id": "32rwef64245tgr20121qw324bgg",
520 "links": {
521 "self": "http://example.com/identity/v3/users/"
522 "32rwef64245tgr20121qw324bgg",
523 },
524 "name": "Lightning",
525 "password_expires_at": "1893-11-06T15:32:17.000000",
526 }
527 ]
528 }
529
530 def test_delete_fail(self):
531 delete_mock = [(self.get_method, self.response, 200),
532 (self.delete_method, 'error', None),
533 (self.log_method, 'exception', None)]
534 self._test_delete(delete_mock, fail=True)
535
536 def test_delete_pass(self):
537 delete_mock = [(self.get_method, self.response, 200),
538 (self.delete_method, None, 204),
539 (self.log_method, 'exception', None)]
540 self._test_delete(delete_mock)
541
542 def test_dry_run(self):
543 dry_mock = [(self.get_method, self.response, 200),
544 (self.delete_method, "delete", None)]
545 self._test_dry_run_true(dry_mock)
546
547 def test_save_state(self):
548 self._test_saved_state_true([(self.get_method, self.response, 200)])
549
550 def test_preserve_list(self):
551 self.response['users'].append(
552 {
553 "domain_id": "TempestDomain",
554 "enabled": True,
555 "id": "23ads5tg3rtrhe30121qwhyth",
556 "links": {
557 "self": "http://example.com/identity/v3/users/"
558 "23ads5tg3rtrhe30121qwhyth",
559 },
560 "name": cleanup_service.CONF_USERS[0],
561 "password_expires_at": "1893-11-06T15:32:17.000000",
562 })
563 self._test_is_preserve_true([(self.get_method, self.response, 200)])