Pin black version in tox.ini to 23.12.1
[osm/N2VC.git] / n2vc / tests / unit / utils.py
1 # Copyright 2020 Canonical Ltd.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 import asyncio
16
17 from n2vc.utils import Dict, N2VCDeploymentStatus
18 from n2vc.n2vc_conn import N2VCConnector
19 from unittest.mock import MagicMock
20
21
22 kubeconfig = """apiVersion: v1
23 clusters:
24 - cluster:
25 certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1\
26 JSURBVENDQWVtZ0F3SUJBZ0lKQUxjMk9xVUpwcnVCTUEwR0NTcUdTSWIzRFFFQk\
27 N3VUFNQmN4RlRBVEJnTlYKQkFNTURERXdMakUxTWk0eE9ETXVNVEFlRncweU1EQ\
28 TVNVEV4TkRJeU16VmFGdzB6TURBNU1Ea3hOREl5TXpWYQpNQmN4RlRBVEJnTlZC\
29 QU1NRERFd0xqRTFNaTR4T0RNdU1UQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQUR\
30 nZ0VQCkFEQ0NBUW9DZ2dFQkFNV0tyQkdxWlJRT0VONDExR2RESmY2ckZWRDcvMU\
31 xHNlZMWjNhd1BRdHBhRTRxdVdyNisKWjExTWwra2kwVEU1cGZFV3dKenVUZXlCU\
32 XVkUEpnYm1QTjF1VWROdGRiNlpocHEzeC9oT0hCMVJLNC9iSlNFUgpiZ0dITmN6\
33 MzR6SHRaZ1dwb2NPTXpPOW9oRUdhMTZUaDhmQWVxYU1CQTJRaklmeUFlaVp3VHJ\
34 nZ3BrY2dBMUlOCjBvQkdqSURnSGVoSU5tbGZOOURkQ3hNN1FNTmtSbzRXdE13bF\
35 JSRWZ4QnFiVkNpZGFjbVhhb1VPUjJPeFVmQWEKN1orSUU1TmN5ZFQ1TGovazdwd\
36 XZCVkdIa0JQWnE0TmlBa3R4aXd5NVB5R29GTk9mT0NrV2I2VnBzVzNhTlNJeAo4\
37 aXBITkc3enV3elc1TGQ5TkhQYWpRckZwdFZBSHpJNWNhRUNBd0VBQWFOUU1FNHd\
38 IUVlEVlIwT0JCWUVGQ1dVCkFaTXNaeE13L1k1OGlXMGZJWVAzcDdTYk1COEdBMV\
39 VkSXdRWU1CYUFGQ1dVQVpNc1p4TXcvWTU4aVcwZklZUDMKcDdTYk1Bd0dBMVVkR\
40 XdRRk1BTUJBZjh3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUJaMlYxMWowRzhh\
41 Z1Z6Twp2YWtKTGt4UGZ0UE1NMFFOaVRzZmV6RzlicnBkdEVLSjFyalFCblNXYTN\
42 WbThWRGZTYkhLQUNXaGh0OEhzcXhtCmNzdVQyOWUyaGZBNHVIOUxMdy9MVG5EdE\
43 tJSjZ6aWFzaTM5RGh3UGwwaExuamJRMjk4VVo5TGovVlpnZGlqemIKWnVPdHlpT\
44 nVOS0E2Nmd0dGxXcWZRQ2hkbnJ5MlZUbjBjblR5dU9UalByYWdOdXJMdlVwL3Nl\
45 eURhZmsxNXJ4egozcmlYZldiQnRhUUk1dnM0ekFKU2xneUg2RnpiZStoTUhlUzF\
46 mM2ppb3dJV0lRR2NNbHpGT1RpMm1xWFRybEJYCnh1WmpLZlpOcndjQVNGbk9qYV\
47 BWeFQ1ODJ4WWhtTm8wR3J2MlZEck51bDlSYkgvK3lNS2J5NEhkOFRvVThMU2kKY\
48 3Uxajh3cz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
49 server: https://192.168.0.22:16443
50 name: microk8s-cluster
51 contexts:
52 - context:
53 cluster: microk8s-cluster
54 user: admin
55 name: microk8s
56 current-context: microk8s
57 kind: Config
58 preferences: {}
59 users:
60 - name: admin
61 user:
62 token: clhkRExRem5Xd1dCdnFEVXdvRGtDRGE5b1F3WnNrZk5qeHFCOU10bHBZRT0K
63 """
64
65
66 async def AsyncMockFunc():
67 await asyncio.sleep(1)
68
69
70 class AsyncMock(MagicMock):
71 async def __call__(self, *args, **kwargs):
72 return super(AsyncMock, self).__call__(*args, **kwargs)
73
74
75 class FakeN2VC(MagicMock):
76 last_written_values = None
77
78 async def write_app_status_to_db(
79 self,
80 db_dict: dict,
81 status: N2VCDeploymentStatus,
82 detailed_status: str,
83 vca_status: str,
84 entity_type: str,
85 vca_id: str = None,
86 ):
87 """
88 Write application status to database
89
90 :param: db_dict: DB dictionary
91 :param: status: Status of the application
92 :param: detailed_status: Detailed status
93 :param: vca_status: VCA status
94 :param: entity_type: Entity type ("application", "machine, and "action")
95 :param: vca_id: Id of the VCA. If None, the default VCA will be used.
96 """
97 self.last_written_values = Dict(
98 {
99 "n2vc_status": status,
100 "message": detailed_status,
101 "vca_status": vca_status,
102 "entity": entity_type,
103 }
104 )
105
106 osm_status = N2VCConnector.osm_status
107
108
109 class FakeMachine(MagicMock):
110 entity_id = "2"
111 dns_name = "FAKE ENDPOINT"
112 model_name = "FAKE MODEL"
113 entity_type = "machine"
114 safe_data = {"instance-id": "myid"}
115
116 async def destroy(self, force):
117 pass
118
119
120 class FakeManualMachine(MagicMock):
121 entity_id = "2"
122 dns_name = "FAKE ENDPOINT"
123 model_name = "FAKE MODEL"
124 entity_type = "machine"
125 safe_data = {"instance-id": "manual:myid"}
126 series = "FAKE SERIES"
127
128 async def destroy(self, force):
129 pass
130
131
132 class FakeWatcher(AsyncMock):
133 delta_to_return = None
134
135 async def Next(self):
136 return Dict({"deltas": self.delta_to_return})
137
138
139 class FakeConnection(MagicMock):
140 endpoint = None
141 is_open = False
142
143
144 class FakeAction(MagicMock):
145 entity_id = "id"
146 status = "ready"
147
148
149 class FakeModel:
150 def __init__(self, applications: dict = {}):
151 self._applications = applications
152
153 @property
154 def applications(self):
155 return self._applications
156
157
158 class FakeUnit(MagicMock):
159 async def is_leader_from_status(self):
160 return True
161
162 async def run_action(self, action_name, **kwargs):
163 return FakeAction()
164
165 @property
166 def machine_id(self):
167 return "existing_machine_id"
168
169 name = "existing_unit"
170
171
172 class FakeApplication(AsyncMock):
173 async def set_config(self, config):
174 pass
175
176 async def add_unit(self, to):
177 pass
178
179 async def destroy_unit(self, unit_name):
180 pass
181
182 async def get_actions(self):
183 return ["existing_action"]
184
185 async def get_config(self):
186 return ["app_config"]
187
188 async def scale(self, scale):
189 pass
190
191 units = [FakeUnit(), FakeUnit()]
192
193
194 class FakeFile:
195 def __init__(self, content: str = ""):
196 self.content = content
197
198 def read(self, size: int = -1):
199 return self.content
200
201
202 class FakeFileWrapper:
203 def __init__(self, content: str = ""):
204 self.file = FakeFile(content=content)
205
206 def __enter__(self):
207 return self.file
208
209 def __exit__(self, type, value, traceback):
210 pass
211
212
213 FAKE_DELTA_MACHINE_PENDING = Dict(
214 {
215 "deltas": ["machine", "change", {}],
216 "entity": "machine",
217 "type": "change",
218 "data": {
219 "id": "2",
220 "instance-id": "juju-1b5808-2",
221 "agent-status": {"current": "pending", "message": "", "version": ""},
222 "instance-status": {"current": "running", "message": "Running"},
223 },
224 }
225 )
226 FAKE_DELTA_MACHINE_STARTED = Dict(
227 {
228 "deltas": ["machine", "change", {}],
229 "entity": "machine",
230 "type": "change",
231 "data": {
232 "id": "2",
233 "instance-id": "juju-1b5808-2",
234 "agent-status": {"current": "started", "message": "", "version": ""},
235 "instance-status": {"current": "running", "message": "Running"},
236 },
237 }
238 )
239
240 FAKE_DELTA_UNIT_PENDING = Dict(
241 {
242 "deltas": ["unit", "change", {}],
243 "entity": "unit",
244 "type": "change",
245 "data": {
246 "name": "git/0",
247 "application": "git",
248 "machine-id": "6",
249 "workload-status": {"current": "waiting", "message": ""},
250 "agent-status": {"current": "idle", "message": ""},
251 },
252 }
253 )
254
255 FAKE_DELTA_UNIT_STARTED = Dict(
256 {
257 "deltas": ["unit", "change", {}],
258 "entity": "unit",
259 "type": "change",
260 "data": {
261 "name": "git/0",
262 "application": "git",
263 "machine-id": "6",
264 "workload-status": {"current": "active", "message": ""},
265 "agent-status": {"current": "idle", "message": ""},
266 },
267 }
268 )
269
270 FAKE_DELTA_APPLICATION_MAINTENANCE = Dict(
271 {
272 "deltas": ["application", "change", {}],
273 "entity": "application",
274 "type": "change",
275 "data": {
276 "name": "git",
277 "status": {
278 "current": "maintenance",
279 "message": "installing charm software",
280 },
281 },
282 }
283 )
284
285 FAKE_DELTA_APPLICATION_ACTIVE = Dict(
286 {
287 "deltas": ["application", "change", {}],
288 "entity": "application",
289 "type": "change",
290 "data": {"name": "git", "status": {"current": "active", "message": "Ready!"}},
291 }
292 )
293
294 FAKE_DELTA_ACTION_COMPLETED = Dict(
295 {
296 "deltas": ["action", "change", {}],
297 "entity": "action",
298 "type": "change",
299 "data": {
300 "model-uuid": "af19cdd4-374a-4d9f-86b1-bfed7b1b5808",
301 "id": "1",
302 "receiver": "git/0",
303 "name": "add-repo",
304 "status": "completed",
305 "message": "",
306 },
307 }
308 )
309
310 Deltas = [
311 Dict(
312 {
313 "entity": Dict({"id": "2", "type": "machine"}),
314 "filter": Dict({"entity_id": "2", "entity_type": "machine"}),
315 "delta": FAKE_DELTA_MACHINE_PENDING,
316 "entity_status": Dict(
317 {"status": "pending", "message": "Running", "vca_status": "running"}
318 ),
319 "db": Dict(
320 {
321 "written": True,
322 "data": Dict(
323 {
324 "message": "Running",
325 "entity": "machine",
326 "vca_status": "running",
327 "n2vc_status": N2VCDeploymentStatus.PENDING,
328 }
329 ),
330 }
331 ),
332 }
333 ),
334 Dict(
335 {
336 "entity": Dict({"id": "2", "type": "machine"}),
337 "filter": Dict({"entity_id": "1", "entity_type": "machine"}),
338 "delta": FAKE_DELTA_MACHINE_PENDING,
339 "entity_status": Dict(
340 {"status": "pending", "message": "Running", "vca_status": "running"}
341 ),
342 "db": Dict({"written": False, "data": None}),
343 }
344 ),
345 Dict(
346 {
347 "entity": Dict({"id": "2", "type": "machine"}),
348 "filter": Dict({"entity_id": "2", "entity_type": "machine"}),
349 "delta": FAKE_DELTA_MACHINE_STARTED,
350 "entity_status": Dict(
351 {"status": "started", "message": "Running", "vca_status": "running"}
352 ),
353 "db": Dict(
354 {
355 "written": True,
356 "data": Dict(
357 {
358 "message": "Running",
359 "entity": "machine",
360 "vca_status": "running",
361 "n2vc_status": N2VCDeploymentStatus.COMPLETED,
362 }
363 ),
364 }
365 ),
366 }
367 ),
368 Dict(
369 {
370 "entity": Dict({"id": "2", "type": "machine"}),
371 "filter": Dict({"entity_id": "1", "entity_type": "machine"}),
372 "delta": FAKE_DELTA_MACHINE_STARTED,
373 "entity_status": Dict(
374 {"status": "started", "message": "Running", "vca_status": "running"}
375 ),
376 "db": Dict({"written": False, "data": None}),
377 }
378 ),
379 Dict(
380 {
381 "entity": Dict({"id": "git/0", "type": "unit"}),
382 "filter": Dict({"entity_id": "git", "entity_type": "application"}),
383 "delta": FAKE_DELTA_UNIT_PENDING,
384 "entity_status": Dict(
385 {"status": "waiting", "message": "", "vca_status": "waiting"}
386 ),
387 "db": Dict(
388 {
389 "written": True,
390 "data": Dict(
391 {
392 "message": "",
393 "entity": "unit",
394 "vca_status": "waiting",
395 "n2vc_status": N2VCDeploymentStatus.RUNNING,
396 }
397 ),
398 }
399 ),
400 }
401 ),
402 Dict(
403 {
404 "entity": Dict({"id": "git/0", "type": "unit"}),
405 "filter": Dict({"entity_id": "2", "entity_type": "machine"}),
406 "delta": FAKE_DELTA_UNIT_PENDING,
407 "entity_status": Dict(
408 {"status": "waiting", "message": "", "vca_status": "waiting"}
409 ),
410 "db": Dict({"written": False, "data": None}),
411 }
412 ),
413 Dict(
414 {
415 "entity": Dict({"id": "git/0", "type": "unit"}),
416 "filter": Dict({"entity_id": "git", "entity_type": "application"}),
417 "delta": FAKE_DELTA_UNIT_STARTED,
418 "entity_status": Dict(
419 {"status": "active", "message": "", "vca_status": "active"}
420 ),
421 "db": Dict(
422 {
423 "written": True,
424 "data": Dict(
425 {
426 "message": "",
427 "entity": "unit",
428 "vca_status": "active",
429 "n2vc_status": N2VCDeploymentStatus.COMPLETED,
430 }
431 ),
432 }
433 ),
434 }
435 ),
436 Dict(
437 {
438 "entity": Dict({"id": "git/0", "type": "unit"}),
439 "filter": Dict({"entity_id": "1", "entity_type": "action"}),
440 "delta": FAKE_DELTA_UNIT_STARTED,
441 "entity_status": Dict(
442 {"status": "active", "message": "", "vca_status": "active"}
443 ),
444 "db": Dict({"written": False, "data": None}),
445 }
446 ),
447 Dict(
448 {
449 "entity": Dict({"id": "git", "type": "application"}),
450 "filter": Dict({"entity_id": "git", "entity_type": "application"}),
451 "delta": FAKE_DELTA_APPLICATION_MAINTENANCE,
452 "entity_status": Dict(
453 {
454 "status": "maintenance",
455 "message": "installing charm software",
456 "vca_status": "maintenance",
457 }
458 ),
459 "db": Dict(
460 {
461 "written": True,
462 "data": Dict(
463 {
464 "message": "installing charm software",
465 "entity": "application",
466 "vca_status": "maintenance",
467 "n2vc_status": N2VCDeploymentStatus.RUNNING,
468 }
469 ),
470 }
471 ),
472 }
473 ),
474 Dict(
475 {
476 "entity": Dict({"id": "git", "type": "application"}),
477 "filter": Dict({"entity_id": "2", "entity_type": "machine"}),
478 "delta": FAKE_DELTA_APPLICATION_MAINTENANCE,
479 "entity_status": Dict(
480 {
481 "status": "maintenance",
482 "message": "installing charm software",
483 "vca_status": "maintenance",
484 }
485 ),
486 "db": Dict({"written": False, "data": None}),
487 }
488 ),
489 Dict(
490 {
491 "entity": Dict({"id": "git", "type": "application"}),
492 "filter": Dict({"entity_id": "git", "entity_type": "application"}),
493 "delta": FAKE_DELTA_APPLICATION_ACTIVE,
494 "entity_status": Dict(
495 {"status": "active", "message": "Ready!", "vca_status": "active"}
496 ),
497 "db": Dict(
498 {
499 "written": True,
500 "data": Dict(
501 {
502 "message": "Ready!",
503 "entity": "application",
504 "vca_status": "active",
505 "n2vc_status": N2VCDeploymentStatus.COMPLETED,
506 }
507 ),
508 }
509 ),
510 }
511 ),
512 Dict(
513 {
514 "entity": Dict({"id": "git", "type": "application"}),
515 "filter": Dict({"entity_id": "1", "entity_type": "action"}),
516 "delta": FAKE_DELTA_APPLICATION_ACTIVE,
517 "entity_status": Dict(
518 {"status": "active", "message": "Ready!", "vca_status": "active"}
519 ),
520 "db": Dict({"written": False, "data": None}),
521 }
522 ),
523 Dict(
524 {
525 "entity": Dict({"id": "1", "type": "action"}),
526 "filter": Dict({"entity_id": "1", "entity_type": "action"}),
527 "delta": FAKE_DELTA_ACTION_COMPLETED,
528 "entity_status": Dict(
529 {
530 "status": "completed",
531 "message": "completed",
532 "vca_status": "completed",
533 }
534 ),
535 "db": Dict(
536 {
537 "written": True,
538 "data": Dict(
539 {
540 "message": "completed",
541 "entity": "action",
542 "vca_status": "completed",
543 "n2vc_status": N2VCDeploymentStatus.COMPLETED,
544 }
545 ),
546 }
547 ),
548 }
549 ),
550 Dict(
551 {
552 "entity": Dict({"id": "git", "type": "action"}),
553 "filter": Dict({"entity_id": "1", "entity_type": "machine"}),
554 "delta": FAKE_DELTA_ACTION_COMPLETED,
555 "entity_status": Dict(
556 {
557 "status": "completed",
558 "message": "completed",
559 "vca_status": "completed",
560 }
561 ),
562 "db": Dict({"written": False, "data": None}),
563 }
564 ),
565 ]