]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/tests/test_rgw_client.py
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / pybind / mgr / dashboard / tests / test_rgw_client.py
CommitLineData
11fdf7f2 1# -*- coding: utf-8 -*-
9f95a23c 2# pylint: disable=too-many-public-methods
522d829b 3import errno
f67539c2
TL
4from unittest import TestCase
5from unittest.mock import Mock, patch
11fdf7f2 6
522d829b 7from .. import mgr
f67539c2
TL
8from ..exceptions import DashboardException
9from ..services.rgw_client import NoCredentialsException, \
10 NoRgwDaemonsException, RgwClient, _parse_frontend_config
9f95a23c 11from ..settings import Settings
a4b75251 12from ..tests import CLICommandTestMixin, RgwStub
f91f0fd5
TL
13
14
f67539c2
TL
15@patch('dashboard.services.rgw_client.RgwClient._get_user_id', Mock(
16 return_value='dummy_admin'))
aee94f69
TL
17@patch('dashboard.services.ceph_service.CephService.send_command', Mock(
18 return_value=''))
522d829b
TL
19class RgwClientTest(TestCase, CLICommandTestMixin):
20 _dashboard_user_realm1_access_key = 'VUOFXZFK24H81ISTVBTR'
21 _dashboard_user_realm1_secret_key = '0PGsCvXPGWS3AGgibUZEcd9efLrbbshlUkY3jruR'
22 _dashboard_user_realm2_access_key = 'OMDR282VYLBC1ZYMYDL0'
23 _dashboard_user_realm2_secret_key = 'N3thf7jAiwQ90PsPrhC2DIcvCFOsBXtBvPJJMdC3'
24 _radosgw_admin_result_error = (-errno.EINVAL, '', 'fake error')
25 _radosgw_admin_result_no_realms = (0, {}, '')
26 _radosgw_admin_result_realms = (0, {"realms": ["realm1", "realm2"]}, '')
27 _radosgw_admin_result_user_realm1 = (
28 0,
29 {
30 "keys": [
31 {
32 "user": "dashboard",
33 "access_key": _dashboard_user_realm1_access_key,
34 "secret_key": _dashboard_user_realm1_secret_key
35 }
36 ],
37 "system": "true"
38 },
39 '')
40 _radosgw_admin_result_user_realm2 = (
41 0,
42 {
43 "keys": [
44 {
45 "user": "dashboard",
46 "access_key": _dashboard_user_realm2_access_key,
47 "secret_key": _dashboard_user_realm2_secret_key
48 }
49 ],
50 "system": "true"
51 },
52 '')
53
11fdf7f2 54 def setUp(self):
f67539c2 55 RgwStub.get_daemons()
92f5a8d4
TL
56 self.mock_kv_store()
57 self.CONFIG_KEY_DICT.update({
58 'RGW_API_ACCESS_KEY': 'klausmustermann',
59 'RGW_API_SECRET_KEY': 'supergeheim',
92f5a8d4 60 })
11fdf7f2 61
522d829b
TL
62 def test_configure_credentials_error(self):
63 self.CONFIG_KEY_DICT.update({
64 'RGW_API_ACCESS_KEY': '',
65 'RGW_API_SECRET_KEY': '',
66 })
67 # Get no realms, get no user, user creation fails.
68 mgr.send_rgwadmin_command.side_effect = [
69 self._radosgw_admin_result_error,
70 self._radosgw_admin_result_error,
71 self._radosgw_admin_result_error,
72 ]
73 with self.assertRaises(NoCredentialsException) as cm:
74 RgwClient.admin_instance()
75 self.assertIn('No RGW credentials found', str(cm.exception))
76
77 def test_configure_credentials_error_with_realms(self):
78 self.CONFIG_KEY_DICT.update({
79 'RGW_API_ACCESS_KEY': '',
80 'RGW_API_SECRET_KEY': '',
81 })
82 # Get realms, get no user, user creation fails.
83 mgr.send_rgwadmin_command.side_effect = [
84 self._radosgw_admin_result_realms,
85 self._radosgw_admin_result_error,
86 self._radosgw_admin_result_error,
87 self._radosgw_admin_result_error,
88 self._radosgw_admin_result_error,
89 ]
90 with self.assertRaises(NoCredentialsException) as cm:
91 RgwClient.admin_instance()
92 self.assertIn('No RGW credentials found', str(cm.exception))
93
94 def test_set_rgw_credentials_command(self):
95 # Get no realms, get user.
96 mgr.send_rgwadmin_command.side_effect = [
97 self._radosgw_admin_result_error,
98 self._radosgw_admin_result_user_realm1
99 ]
100 result = self.exec_cmd('set-rgw-credentials')
101 self.assertEqual(result, 'RGW credentials configured')
102 self.assertEqual(Settings.RGW_API_ACCESS_KEY, self._dashboard_user_realm1_access_key)
103 self.assertEqual(Settings.RGW_API_SECRET_KEY, self._dashboard_user_realm1_secret_key)
104
105 # Get no realms, get no user, user creation.
106 mgr.send_rgwadmin_command.side_effect = [
107 self._radosgw_admin_result_error,
108 self._radosgw_admin_result_error,
109 self._radosgw_admin_result_user_realm1
110 ]
111 result = self.exec_cmd('set-rgw-credentials')
112 self.assertEqual(result, 'RGW credentials configured')
113 self.assertEqual(Settings.RGW_API_ACCESS_KEY, self._dashboard_user_realm1_access_key)
114 self.assertEqual(Settings.RGW_API_SECRET_KEY, self._dashboard_user_realm1_secret_key)
115
116 # Get realms, get users.
117 mgr.send_rgwadmin_command.side_effect = [
118 self._radosgw_admin_result_realms,
119 self._radosgw_admin_result_user_realm1,
120 self._radosgw_admin_result_user_realm2
121 ]
122 result = self.exec_cmd('set-rgw-credentials')
123 self.assertEqual(result, 'RGW credentials configured')
124 self.assertEqual(Settings.RGW_API_ACCESS_KEY, {
125 'realm1': self._dashboard_user_realm1_access_key,
126 'realm2': self._dashboard_user_realm2_access_key
127 })
128 self.assertEqual(Settings.RGW_API_SECRET_KEY, {
129 'realm1': self._dashboard_user_realm1_secret_key,
130 'realm2': self._dashboard_user_realm2_secret_key
131 })
132
133 # Get realms, get no users, users' creation.
134 mgr.send_rgwadmin_command.side_effect = [
135 self._radosgw_admin_result_realms,
136 self._radosgw_admin_result_error,
137 self._radosgw_admin_result_user_realm1,
138 self._radosgw_admin_result_error,
139 self._radosgw_admin_result_user_realm2
140 ]
141 result = self.exec_cmd('set-rgw-credentials')
142 self.assertEqual(result, 'RGW credentials configured')
143 self.assertEqual(Settings.RGW_API_ACCESS_KEY, {
144 'realm1': self._dashboard_user_realm1_access_key,
145 'realm2': self._dashboard_user_realm2_access_key
146 })
147 self.assertEqual(Settings.RGW_API_SECRET_KEY, {
148 'realm1': self._dashboard_user_realm1_secret_key,
149 'realm2': self._dashboard_user_realm2_secret_key
150 })
151
152 # Get realms, get no users, realm 2 user creation fails.
153 mgr.send_rgwadmin_command.side_effect = [
154 self._radosgw_admin_result_realms,
155 self._radosgw_admin_result_error,
156 self._radosgw_admin_result_user_realm1,
157 self._radosgw_admin_result_error,
158 self._radosgw_admin_result_error,
159 ]
160 result = self.exec_cmd('set-rgw-credentials')
161 self.assertEqual(result, 'RGW credentials configured')
162 self.assertEqual(Settings.RGW_API_ACCESS_KEY, {
163 'realm1': self._dashboard_user_realm1_access_key,
164 })
165 self.assertEqual(Settings.RGW_API_SECRET_KEY, {
166 'realm1': self._dashboard_user_realm1_secret_key,
167 })
168
11fdf7f2 169 def test_ssl_verify(self):
9f95a23c 170 Settings.RGW_API_SSL_VERIFY = True
11fdf7f2
TL
171 instance = RgwClient.admin_instance()
172 self.assertTrue(instance.session.verify)
173
174 def test_no_ssl_verify(self):
9f95a23c 175 Settings.RGW_API_SSL_VERIFY = False
11fdf7f2
TL
176 instance = RgwClient.admin_instance()
177 self.assertFalse(instance.session.verify)
9f95a23c 178
f67539c2
TL
179 def test_no_daemons(self):
180 RgwStub.get_mgr_no_services()
181 with self.assertRaises(NoRgwDaemonsException) as cm:
182 RgwClient.admin_instance()
183 self.assertIn('No RGW service is running.', str(cm.exception))
184
9f95a23c 185 @patch.object(RgwClient, '_get_daemon_zone_info')
f91f0fd5 186 def test_get_placement_targets_from_zone(self, zone_info):
9f95a23c
TL
187 zone_info.return_value = {
188 'id': 'a0df30ea-4b5b-4830-b143-2bedf684663d',
189 'placement_pools': [
190 {
191 'key': 'default-placement',
192 'val': {
193 'index_pool': 'default.rgw.buckets.index',
194 'storage_classes': {
195 'STANDARD': {
196 'data_pool': 'default.rgw.buckets.data'
197 }
198 }
199 }
200 }
f91f0fd5 201 ]
9f95a23c
TL
202 }
203
9f95a23c
TL
204 instance = RgwClient.admin_instance()
205 expected_result = {
f67539c2 206 'zonegroup': 'zonegroup1',
9f95a23c
TL
207 'placement_targets': [
208 {
209 'name': 'default-placement',
210 'data_pool': 'default.rgw.buckets.data'
211 }
212 ]
213 }
214 self.assertEqual(expected_result, instance.get_placement_targets())
215
e306af50
TL
216 @patch.object(RgwClient, '_get_realms_info')
217 def test_get_realms(self, realms_info):
218 realms_info.side_effect = [
219 {
220 'default_info': '51de8373-bc24-4f74-a9b7-8e9ef4cb71f7',
221 'realms': [
222 'realm1',
223 'realm2'
224 ]
225 },
226 {}
227 ]
228 instance = RgwClient.admin_instance()
229
230 self.assertEqual(['realm1', 'realm2'], instance.get_realms())
231 self.assertEqual([], instance.get_realms())
232
b3b6e05e
TL
233 def test_set_bucket_locking_error(self):
234 instance = RgwClient.admin_instance()
235 test_params = [
236 ('COMPLIANCE', 'null', None, 'must be a positive integer'),
237 ('COMPLIANCE', None, 'null', 'must be a positive integer'),
238 ('COMPLIANCE', -1, None, 'must be a positive integer'),
239 ('COMPLIANCE', None, -1, 'must be a positive integer'),
240 ('COMPLIANCE', 1, 1, 'You can\'t specify both at the same time'),
241 ('COMPLIANCE', None, None, 'You must specify at least one'),
242 ('COMPLIANCE', 0, 0, 'You must specify at least one'),
243 (None, 1, 0, 'must be either COMPLIANCE or GOVERNANCE'),
244 ('', 1, 0, 'must be either COMPLIANCE or GOVERNANCE'),
245 ('FAKE_MODE', 1, 0, 'must be either COMPLIANCE or GOVERNANCE')
246 ]
247 for params in test_params:
248 mode, days, years, error_msg = params
249 with self.assertRaises(DashboardException) as cm:
250 instance.set_bucket_locking(
251 bucket_name='test',
252 mode=mode,
253 retention_period_days=days,
254 retention_period_years=years
255 )
256 self.assertIn(error_msg, str(cm.exception))
257
258 @patch('dashboard.rest_client._Request', Mock())
259 def test_set_bucket_locking_success(self):
260 instance = RgwClient.admin_instance()
261 test_params = [
262 ('Compliance', '1', None),
263 ('Governance', 1, None),
264 ('COMPLIANCE', None, '1'),
265 ('GOVERNANCE', None, 1),
266 ]
267 for params in test_params:
268 mode, days, years = params
269 self.assertIsNone(instance.set_bucket_locking(
270 bucket_name='test',
271 mode=mode,
272 retention_period_days=days,
273 retention_period_years=years
274 ))
275
9f95a23c 276
f67539c2 277class RgwClientHelperTest(TestCase):
9f95a23c
TL
278 def test_parse_frontend_config_1(self):
279 self.assertEqual(_parse_frontend_config('beast port=8000'), (8000, False))
280
281 def test_parse_frontend_config_2(self):
282 self.assertEqual(_parse_frontend_config('beast port=80 port=8000'), (80, False))
283
284 def test_parse_frontend_config_3(self):
285 self.assertEqual(_parse_frontend_config('beast ssl_port=443 port=8000'), (443, True))
286
287 def test_parse_frontend_config_4(self):
288 self.assertEqual(_parse_frontend_config('beast endpoint=192.168.0.100:8000'), (8000, False))
289
290 def test_parse_frontend_config_5(self):
291 self.assertEqual(_parse_frontend_config('beast endpoint=[::1]'), (80, False))
292
293 def test_parse_frontend_config_6(self):
294 self.assertEqual(_parse_frontend_config(
295 'beast ssl_endpoint=192.168.0.100:8443'), (8443, True))
296
297 def test_parse_frontend_config_7(self):
298 self.assertEqual(_parse_frontend_config('beast ssl_endpoint=192.168.0.100'), (443, True))
299
300 def test_parse_frontend_config_8(self):
301 self.assertEqual(_parse_frontend_config(
302 'beast ssl_endpoint=[::1]:8443 endpoint=192.0.2.3:80'), (8443, True))
303
304 def test_parse_frontend_config_9(self):
305 self.assertEqual(_parse_frontend_config(
306 'beast port=8080 endpoint=192.0.2.3:80'), (8080, False))
307
308 def test_parse_frontend_config_10(self):
309 self.assertEqual(_parse_frontend_config(
310 'beast ssl_endpoint=192.0.2.3:8443 port=8080'), (8443, True))
311
312 def test_parse_frontend_config_11(self):
313 self.assertEqual(_parse_frontend_config('civetweb port=8000s'), (8000, True))
314
315 def test_parse_frontend_config_12(self):
316 self.assertEqual(_parse_frontend_config('civetweb port=443s port=8000'), (443, True))
317
318 def test_parse_frontend_config_13(self):
319 self.assertEqual(_parse_frontend_config('civetweb port=192.0.2.3:80'), (80, False))
320
321 def test_parse_frontend_config_14(self):
322 self.assertEqual(_parse_frontend_config('civetweb port=172.5.2.51:8080s'), (8080, True))
323
324 def test_parse_frontend_config_15(self):
325 self.assertEqual(_parse_frontend_config('civetweb port=[::]:8080'), (8080, False))
326
327 def test_parse_frontend_config_16(self):
328 self.assertEqual(_parse_frontend_config('civetweb port=ip6-localhost:80s'), (80, True))
329
330 def test_parse_frontend_config_17(self):
331 self.assertEqual(_parse_frontend_config('civetweb port=[2001:0db8::1234]:80'), (80, False))
332
333 def test_parse_frontend_config_18(self):
334 self.assertEqual(_parse_frontend_config('civetweb port=[::1]:8443s'), (8443, True))
335
336 def test_parse_frontend_config_19(self):
337 self.assertEqual(_parse_frontend_config('civetweb port=127.0.0.1:8443s+8000'), (8443, True))
338
339 def test_parse_frontend_config_20(self):
340 self.assertEqual(_parse_frontend_config('civetweb port=127.0.0.1:8080+443s'), (8080, False))
341
342 def test_parse_frontend_config_21(self):
343 with self.assertRaises(LookupError) as ctx:
344 _parse_frontend_config('civetweb port=xyz')
345 self.assertEqual(str(ctx.exception),
346 'Failed to determine RGW port from "civetweb port=xyz"')
347
348 def test_parse_frontend_config_22(self):
349 with self.assertRaises(LookupError) as ctx:
350 _parse_frontend_config('civetweb')
351 self.assertEqual(str(ctx.exception), 'Failed to determine RGW port from "civetweb"')
352
353 def test_parse_frontend_config_23(self):
354 with self.assertRaises(LookupError) as ctx:
355 _parse_frontend_config('mongoose port=8080')
356 self.assertEqual(str(ctx.exception),
357 'Failed to determine RGW port from "mongoose port=8080"')