Fix bug 1715
[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
134 delta_to_return = None
135
136 async def Next(self):
137 return Dict({"deltas": self.delta_to_return})
138
139
140 class FakeConnection(MagicMock):
141 endpoint = None
142 is_open = False
143
144
145 class FakeAction(MagicMock):
146 entity_id = "id"
147 status = "ready"
148
149
150 class FakeModel:
151 def __init__(self, applications: dict = {}):
152 self._applications = applications
153
154 @property
155 def applications(self):
156 return self._applications
157
158
159 class FakeUnit(MagicMock):
160 async def is_leader_from_status(self):
161 return True
162
163 async def run_action(self, action_name, **kwargs):
164 return FakeAction()
165
166 @property
167 def machine_id(self):
168 return "existing_machine_id"
169
170 name = "existing_unit"
171
172
173 class FakeApplication(AsyncMock):
174 async def set_config(self, config):
175 pass
176
177 async def add_unit(self, to):
178 pass
179
180 async def destroy_unit(self, unit_name):
181 pass
182
183 async def get_actions(self):
184 return ["existing_action"]
185
186 async def get_config(self):
187 return ["app_config"]
188
189 async def scale(self, scale):
190 pass
191
192 units = [FakeUnit(), FakeUnit()]
193
194
195 class FakeFile:
196 def __init__(self, content: str = ""):
197 self.content = content
198
199 def read(self, size: int = -1):
200 return self.content
201
202
203 class FakeFileWrapper:
204 def __init__(self, content: str = ""):
205 self.file = FakeFile(content=content)
206
207 def __enter__(self):
208 return self.file
209
210 def __exit__(self, type, value, traceback):
211 pass
212
213
214 FAKE_DELTA_MACHINE_PENDING = Dict(
215 {
216 "deltas": ["machine", "change", {}],
217 "entity": "machine",
218 "type": "change",
219 "data": {
220 "id": "2",
221 "instance-id": "juju-1b5808-2",
222 "agent-status": {"current": "pending", "message": "", "version": ""},
223 "instance-status": {"current": "running", "message": "Running"},
224 },
225 }
226 )
227 FAKE_DELTA_MACHINE_STARTED = Dict(
228 {
229 "deltas": ["machine", "change", {}],
230 "entity": "machine",
231 "type": "change",
232 "data": {
233 "id": "2",
234 "instance-id": "juju-1b5808-2",
235 "agent-status": {"current": "started", "message": "", "version": ""},
236 "instance-status": {"current": "running", "message": "Running"},
237 },
238 }
239 )
240
241 FAKE_DELTA_UNIT_PENDING = Dict(
242 {
243 "deltas": ["unit", "change", {}],
244 "entity": "unit",
245 "type": "change",
246 "data": {
247 "name": "git/0",
248 "application": "git",
249 "machine-id": "6",
250 "workload-status": {"current": "waiting", "message": ""},
251 "agent-status": {"current": "idle", "message": ""},
252 },
253 }
254 )
255
256 FAKE_DELTA_UNIT_STARTED = Dict(
257 {
258 "deltas": ["unit", "change", {}],
259 "entity": "unit",
260 "type": "change",
261 "data": {
262 "name": "git/0",
263 "application": "git",
264 "machine-id": "6",
265 "workload-status": {"current": "active", "message": ""},
266 "agent-status": {"current": "idle", "message": ""},
267 },
268 }
269 )
270
271 FAKE_DELTA_APPLICATION_MAINTENANCE = Dict(
272 {
273 "deltas": ["application", "change", {}],
274 "entity": "application",
275 "type": "change",
276 "data": {
277 "name": "git",
278 "status": {
279 "current": "maintenance",
280 "message": "installing charm software",
281 },
282 },
283 }
284 )
285
286 FAKE_DELTA_APPLICATION_ACTIVE = Dict(
287 {
288 "deltas": ["application", "change", {}],
289 "entity": "application",
290 "type": "change",
291 "data": {"name": "git", "status": {"current": "active", "message": "Ready!"}},
292 }
293 )
294
295 FAKE_DELTA_ACTION_COMPLETED = Dict(
296 {
297 "deltas": ["action", "change", {}],
298 "entity": "action",
299 "type": "change",
300 "data": {
301 "model-uuid": "af19cdd4-374a-4d9f-86b1-bfed7b1b5808",
302 "id": "1",
303 "receiver": "git/0",
304 "name": "add-repo",
305 "status": "completed",
306 "message": "",
307 },
308 }
309 )
310
311 Deltas = [
312 Dict(
313 {
314 "entity": Dict({"id": "2", "type": "machine"}),
315 "filter": Dict({"entity_id": "2", "entity_type": "machine"}),
316 "delta": FAKE_DELTA_MACHINE_PENDING,
317 "entity_status": Dict(
318 {"status": "pending", "message": "Running", "vca_status": "running"}
319 ),
320 "db": Dict(
321 {
322 "written": True,
323 "data": Dict(
324 {
325 "message": "Running",
326 "entity": "machine",
327 "vca_status": "running",
328 "n2vc_status": N2VCDeploymentStatus.PENDING,
329 }
330 ),
331 }
332 ),
333 }
334 ),
335 Dict(
336 {
337 "entity": Dict({"id": "2", "type": "machine"}),
338 "filter": Dict({"entity_id": "1", "entity_type": "machine"}),
339 "delta": FAKE_DELTA_MACHINE_PENDING,
340 "entity_status": Dict(
341 {"status": "pending", "message": "Running", "vca_status": "running"}
342 ),
343 "db": Dict({"written": False, "data": None}),
344 }
345 ),
346 Dict(
347 {
348 "entity": Dict({"id": "2", "type": "machine"}),
349 "filter": Dict({"entity_id": "2", "entity_type": "machine"}),
350 "delta": FAKE_DELTA_MACHINE_STARTED,
351 "entity_status": Dict(
352 {"status": "started", "message": "Running", "vca_status": "running"}
353 ),
354 "db": Dict(
355 {
356 "written": True,
357 "data": Dict(
358 {
359 "message": "Running",
360 "entity": "machine",
361 "vca_status": "running",
362 "n2vc_status": N2VCDeploymentStatus.COMPLETED,
363 }
364 ),
365 }
366 ),
367 }
368 ),
369 Dict(
370 {
371 "entity": Dict({"id": "2", "type": "machine"}),
372 "filter": Dict({"entity_id": "1", "entity_type": "machine"}),
373 "delta": FAKE_DELTA_MACHINE_STARTED,
374 "entity_status": Dict(
375 {"status": "started", "message": "Running", "vca_status": "running"}
376 ),
377 "db": Dict({"written": False, "data": None}),
378 }
379 ),
380 Dict(
381 {
382 "entity": Dict({"id": "git/0", "type": "unit"}),
383 "filter": Dict({"entity_id": "git", "entity_type": "application"}),
384 "delta": FAKE_DELTA_UNIT_PENDING,
385 "entity_status": Dict(
386 {"status": "waiting", "message": "", "vca_status": "waiting"}
387 ),
388 "db": Dict(
389 {
390 "written": True,
391 "data": Dict(
392 {
393 "message": "",
394 "entity": "unit",
395 "vca_status": "waiting",
396 "n2vc_status": N2VCDeploymentStatus.RUNNING,
397 }
398 ),
399 }
400 ),
401 }
402 ),
403 Dict(
404 {
405 "entity": Dict({"id": "git/0", "type": "unit"}),
406 "filter": Dict({"entity_id": "2", "entity_type": "machine"}),
407 "delta": FAKE_DELTA_UNIT_PENDING,
408 "entity_status": Dict(
409 {"status": "waiting", "message": "", "vca_status": "waiting"}
410 ),
411 "db": Dict({"written": False, "data": None}),
412 }
413 ),
414 Dict(
415 {
416 "entity": Dict({"id": "git/0", "type": "unit"}),
417 "filter": Dict({"entity_id": "git", "entity_type": "application"}),
418 "delta": FAKE_DELTA_UNIT_STARTED,
419 "entity_status": Dict(
420 {"status": "active", "message": "", "vca_status": "active"}
421 ),
422 "db": Dict(
423 {
424 "written": True,
425 "data": Dict(
426 {
427 "message": "",
428 "entity": "unit",
429 "vca_status": "active",
430 "n2vc_status": N2VCDeploymentStatus.COMPLETED,
431 }
432 ),
433 }
434 ),
435 }
436 ),
437 Dict(
438 {
439 "entity": Dict({"id": "git/0", "type": "unit"}),
440 "filter": Dict({"entity_id": "1", "entity_type": "action"}),
441 "delta": FAKE_DELTA_UNIT_STARTED,
442 "entity_status": Dict(
443 {"status": "active", "message": "", "vca_status": "active"}
444 ),
445 "db": Dict({"written": False, "data": None}),
446 }
447 ),
448 Dict(
449 {
450 "entity": Dict({"id": "git", "type": "application"}),
451 "filter": Dict({"entity_id": "git", "entity_type": "application"}),
452 "delta": FAKE_DELTA_APPLICATION_MAINTENANCE,
453 "entity_status": Dict(
454 {
455 "status": "maintenance",
456 "message": "installing charm software",
457 "vca_status": "maintenance",
458 }
459 ),
460 "db": Dict(
461 {
462 "written": True,
463 "data": Dict(
464 {
465 "message": "installing charm software",
466 "entity": "application",
467 "vca_status": "maintenance",
468 "n2vc_status": N2VCDeploymentStatus.RUNNING,
469 }
470 ),
471 }
472 ),
473 }
474 ),
475 Dict(
476 {
477 "entity": Dict({"id": "git", "type": "application"}),
478 "filter": Dict({"entity_id": "2", "entity_type": "machine"}),
479 "delta": FAKE_DELTA_APPLICATION_MAINTENANCE,
480 "entity_status": Dict(
481 {
482 "status": "maintenance",
483 "message": "installing charm software",
484 "vca_status": "maintenance",
485 }
486 ),
487 "db": Dict({"written": False, "data": None}),
488 }
489 ),
490 Dict(
491 {
492 "entity": Dict({"id": "git", "type": "application"}),
493 "filter": Dict({"entity_id": "git", "entity_type": "application"}),
494 "delta": FAKE_DELTA_APPLICATION_ACTIVE,
495 "entity_status": Dict(
496 {"status": "active", "message": "Ready!", "vca_status": "active"}
497 ),
498 "db": Dict(
499 {
500 "written": True,
501 "data": Dict(
502 {
503 "message": "Ready!",
504 "entity": "application",
505 "vca_status": "active",
506 "n2vc_status": N2VCDeploymentStatus.COMPLETED,
507 }
508 ),
509 }
510 ),
511 }
512 ),
513 Dict(
514 {
515 "entity": Dict({"id": "git", "type": "application"}),
516 "filter": Dict({"entity_id": "1", "entity_type": "action"}),
517 "delta": FAKE_DELTA_APPLICATION_ACTIVE,
518 "entity_status": Dict(
519 {"status": "active", "message": "Ready!", "vca_status": "active"}
520 ),
521 "db": Dict({"written": False, "data": None}),
522 }
523 ),
524 Dict(
525 {
526 "entity": Dict({"id": "1", "type": "action"}),
527 "filter": Dict({"entity_id": "1", "entity_type": "action"}),
528 "delta": FAKE_DELTA_ACTION_COMPLETED,
529 "entity_status": Dict(
530 {
531 "status": "completed",
532 "message": "completed",
533 "vca_status": "completed",
534 }
535 ),
536 "db": Dict(
537 {
538 "written": True,
539 "data": Dict(
540 {
541 "message": "completed",
542 "entity": "action",
543 "vca_status": "completed",
544 "n2vc_status": N2VCDeploymentStatus.COMPLETED,
545 }
546 ),
547 }
548 ),
549 }
550 ),
551 Dict(
552 {
553 "entity": Dict({"id": "git", "type": "action"}),
554 "filter": Dict({"entity_id": "1", "entity_type": "machine"}),
555 "delta": FAKE_DELTA_ACTION_COMPLETED,
556 "entity_status": Dict(
557 {
558 "status": "completed",
559 "message": "completed",
560 "vca_status": "completed",
561 }
562 ),
563 "db": Dict({"written": False, "data": None}),
564 }
565 ),
566 ]