1 from __future__
import absolute_import
8 from ceph
.deployment
.service_spec
import ServiceSpec
9 from ceph
.deployment
import inventory
10 from ceph
.utils
import datetime_now
12 from test_orchestrator
import TestOrchestrator
as _TestOrchestrator
13 from tests
import mock
15 from orchestrator
import raise_if_exception
, Completion
, ProgressReference
16 from orchestrator
import InventoryHost
, DaemonDescription
, ServiceDescription
17 from orchestrator
import OrchestratorValidationError
18 from orchestrator
.module
import to_format
, preview_table_osd
21 def _test_resource(data
, resource_class
, extra
=None):
22 # ensure we can deserialize and serialize
23 rsc
= resource_class
.from_json(data
)
27 # if there is an unexpected data provided
29 with pytest
.raises(OrchestratorValidationError
):
30 resource_class
.from_json(data
)
45 'rejected_reasons': [],
50 _test_resource(json_data
, InventoryHost
, {'abc': False})
51 for devices
in json_data
['devices']:
52 _test_resource(devices
, inventory
.Device
)
54 json_data
= [{}, {'name': 'host0', 'addr': '1.2.3.4'}, {'devices': []}]
55 for data
in json_data
:
56 with pytest
.raises(OrchestratorValidationError
):
57 InventoryHost
.from_json(data
)
60 def test_daemon_description():
66 _test_resource(json_data
, DaemonDescription
, {'abc': False})
71 c
._exception
= ZeroDivisionError()
72 with pytest
.raises(ZeroDivisionError):
77 p
= Completion(value
=3)
82 def test_promise_then():
83 p
= Completion(value
=3).then(lambda three
: three
+ 1)
88 def test_promise_mondatic_then():
89 p
= Completion(value
=3)
90 p
.then(lambda three
: Completion(value
=three
+ 1))
95 def some_complex_completion():
96 c
= Completion(value
=3).then(
97 lambda three
: Completion(value
=three
+ 1).then(
98 lambda four
: four
+ 1))
102 def test_promise_mondatic_then_combined():
103 p
= some_complex_completion()
108 def test_promise_flat():
110 p
.then(lambda r1
: Completion(value
=r1
+ ' there').then(
111 lambda r11
: r11
+ '!'))
113 assert p
.result
== 'hello there!'
116 def test_side_effect():
123 Completion(value
=3).then(run
).finalize()
128 c
= some_complex_completion()
129 mgr
= mock
.MagicMock()
130 mgr
.process
= lambda cs
: [c
.finalize(None) for c
in cs
]
133 c
._last
_promise
().then(
134 on_complete
=ProgressReference(message
='hello world',
136 completion
=lambda: Completion(
137 on_complete
=lambda _
: progress_val
))
139 mgr
.remote
.assert_called_with('progress', 'update', c
.progress_reference
.progress_id
, 'hello world', 0.0, [
140 ('origin', 'orchestrator')])
143 mgr
.remote
.assert_called_with('progress', 'complete', c
.progress_reference
.progress_id
)
145 c
.progress_reference
.update()
146 mgr
.remote
.assert_called_with('progress', 'update', c
.progress_reference
.progress_id
,
147 'hello world', progress_val
, [('origin', 'orchestrator')])
148 assert not c
.progress_reference
.effective
151 c
.progress_reference
.update()
152 assert c
.progress_reference
.effective
153 mgr
.remote
.assert_called_with('progress', 'complete', c
.progress_reference
.progress_id
)
156 def test_with_progress():
157 mgr
= mock
.MagicMock()
158 mgr
.process
= lambda cs
: [c
.finalize(None) for c
in cs
]
165 return execute(x
* 2)
167 return Completion
.with_progress(
173 c
= Completion(on_complete
=lambda x
: x
* 10).then(run
)._first
_promise
175 assert c
.result
== '40'
176 c
.progress_reference
.update()
177 assert c
.progress_reference
.effective
180 def test_exception():
185 c
= Completion(value
=3).then(run
)
187 with pytest
.raises(KeyError):
188 raise_if_exception(c
)
192 c
= Completion().then(lambda _
: 3)
193 c
._first
_promise
.fail(KeyError())
194 assert isinstance(c
.exception
, KeyError)
196 with pytest
.raises(ValueError,
197 match
='Invalid State: called fail, but Completion is already finished: {}'.format(
198 str(ZeroDivisionError()))):
199 c
._first
_promise
.fail(ZeroDivisionError())
202 def test_pretty_print():
203 mgr
= mock
.MagicMock()
204 mgr
.process
= lambda cs
: [c
.finalize(None) for c
in cs
]
209 c
= Completion(value
=1, on_complete
=add_one
).then(
211 ).add_progress('message', mgr
)
213 assert c
.pretty_print() == """<Completion>[
216 ProgressReference(...),
219 assert c
.pretty_print() == """<Completion>[
222 (done) ProgressReference('2'),
225 p
= some_complex_completion()
226 assert p
.pretty_print() == """<Completion>[
231 assert p
.pretty_print() == """<Completion>[
234 (done) lambda x: x(5),
235 (done) lambda x: x(5),
242 to
= _TestOrchestrator('', 0, 0)
243 completion
= to
.apply([
244 ServiceSpec(service_type
='nfs'),
245 ServiceSpec(service_type
='nfs'),
246 ServiceSpec(service_type
='nfs'),
248 completion
.finalize(42)
249 assert completion
.result
== [None, None, None]
253 y
= """daemon_type: crash
257 status_desc: starting
260 - 2020-06-10T10:08:22.933241Z daemon:crash.ubuntu [INFO] "Deployed crash.ubuntu on
268 container_image_id: 74803e884bea289d2d2d3ebdf6d37cd560499e955595695b1390a89800f4e37a
269 container_image_name: docker.io/ceph/daemon-base:latest-master-devel
270 created: '2020-06-10T10:37:31.051288Z'
271 last_refresh: '2020-06-10T10:57:40.715637Z'
275 - 2020-06-10T10:37:31.139159Z service:crash [INFO] "service was created"
277 types
= (DaemonDescription
, ServiceDescription
)
279 for y
, cls
in zip(y
.split('---\n'), types
):
280 data
= yaml
.safe_load(y
)
281 object = cls
.from_json(data
)
283 assert to_format(object, 'yaml', False, cls
) == y
284 assert to_format([object], 'yaml', True, cls
) == y
286 j
= json
.loads(to_format(object, 'json', False, cls
))
287 assert to_format(cls
.from_json(j
), 'yaml', False, cls
) == y
290 def test_event_multiline():
291 from .._interface
import OrchestratorEvent
292 e
= OrchestratorEvent(datetime_now(), 'service', 'subject', 'ERROR', 'message')
293 assert OrchestratorEvent
.from_json(e
.to_json()) == e
295 e
= OrchestratorEvent(datetime_now(), 'service',
296 'subject', 'ERROR', 'multiline\nmessage')
297 assert OrchestratorEvent
.from_json(e
.to_json()) == e
300 def test_preview_table_osd_smoke():
303 'service_type': 'osd',
314 "block_db": "/dev/nvme0n1",
315 "block_db_size": "66.67 GB",
317 "data_size": "300.00 GB",
321 "block_db": "/dev/nvme0n1",
322 "block_db_size": "66.67 GB",
324 "data_size": "300.00 GB",
328 "block_db": "/dev/nvme0n1",
329 "block_db_size": "66.67 GB",
331 "data_size": "300.00 GB",
340 preview_table_osd(data
)