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