1 # Copyright 2020 Canonical Ltd.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 from n2vc
.utils
import Dict
, N2VCDeploymentStatus
18 from n2vc
.n2vc_conn
import N2VCConnector
19 from unittest
.mock
import MagicMock
22 kubeconfig
= """apiVersion: v1
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
53 cluster: microk8s-cluster
56 current-context: microk8s
62 token: clhkRExRem5Xd1dCdnFEVXdvRGtDRGE5b1F3WnNrZk5qeHFCOU10bHBZRT0K
66 async def AsyncMockFunc():
67 await asyncio
.sleep(1)
70 class AsyncMock(MagicMock
):
71 async def __call__(self
, *args
, **kwargs
):
72 return super(AsyncMock
, self
).__call
__(*args
, **kwargs
)
75 class FakeN2VC(MagicMock
):
76 last_written_values
= None
78 async def write_app_status_to_db(
81 status
: N2VCDeploymentStatus
,
88 Write application status to database
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.
97 self
.last_written_values
= Dict(
99 "n2vc_status": status
,
100 "message": detailed_status
,
101 "vca_status": vca_status
,
102 "entity": entity_type
,
106 osm_status
= N2VCConnector
.osm_status
109 class FakeMachine(MagicMock
):
111 dns_name
= "FAKE ENDPOINT"
112 model_name
= "FAKE MODEL"
113 entity_type
= "machine"
114 safe_data
= {"instance-id": "myid"}
116 async def destroy(self
, force
):
120 class FakeManualMachine(MagicMock
):
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"
128 async def destroy(self
, force
):
132 class FakeWatcher(AsyncMock
):
133 delta_to_return
= None
135 async def Next(self
):
136 return Dict({"deltas": self
.delta_to_return
})
139 class FakeConnection(MagicMock
):
144 class FakeAction(MagicMock
):
150 def __init__(self
, applications
: dict = {}):
151 self
._applications
= applications
154 def applications(self
):
155 return self
._applications
158 class FakeUnit(MagicMock
):
159 async def is_leader_from_status(self
):
162 async def run_action(self
, action_name
, **kwargs
):
166 def machine_id(self
):
167 return "existing_machine_id"
169 name
= "existing_unit"
172 class FakeApplication(AsyncMock
):
173 async def set_config(self
, config
):
176 async def add_unit(self
, to
):
179 async def destroy_unit(self
, unit_name
):
182 async def get_actions(self
):
183 return ["existing_action"]
185 async def get_config(self
):
186 return ["app_config"]
188 async def scale(self
, scale
):
191 units
= [FakeUnit(), FakeUnit()]
195 def __init__(self
, content
: str = ""):
196 self
.content
= content
198 def read(self
, size
: int = -1):
202 class FakeFileWrapper
:
203 def __init__(self
, content
: str = ""):
204 self
.file = FakeFile(content
=content
)
209 def __exit__(self
, type, value
, traceback
):
213 FAKE_DELTA_MACHINE_PENDING
= Dict(
215 "deltas": ["machine", "change", {}],
220 "instance-id": "juju-1b5808-2",
221 "agent-status": {"current": "pending", "message": "", "version": ""},
222 "instance-status": {"current": "running", "message": "Running"},
226 FAKE_DELTA_MACHINE_STARTED
= Dict(
228 "deltas": ["machine", "change", {}],
233 "instance-id": "juju-1b5808-2",
234 "agent-status": {"current": "started", "message": "", "version": ""},
235 "instance-status": {"current": "running", "message": "Running"},
240 FAKE_DELTA_UNIT_PENDING
= Dict(
242 "deltas": ["unit", "change", {}],
247 "application": "git",
249 "workload-status": {"current": "waiting", "message": ""},
250 "agent-status": {"current": "idle", "message": ""},
255 FAKE_DELTA_UNIT_STARTED
= Dict(
257 "deltas": ["unit", "change", {}],
262 "application": "git",
264 "workload-status": {"current": "active", "message": ""},
265 "agent-status": {"current": "idle", "message": ""},
270 FAKE_DELTA_APPLICATION_MAINTENANCE
= Dict(
272 "deltas": ["application", "change", {}],
273 "entity": "application",
278 "current": "maintenance",
279 "message": "installing charm software",
285 FAKE_DELTA_APPLICATION_ACTIVE
= Dict(
287 "deltas": ["application", "change", {}],
288 "entity": "application",
290 "data": {"name": "git", "status": {"current": "active", "message": "Ready!"}},
294 FAKE_DELTA_ACTION_COMPLETED
= Dict(
296 "deltas": ["action", "change", {}],
300 "model-uuid": "af19cdd4-374a-4d9f-86b1-bfed7b1b5808",
304 "status": "completed",
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"}
324 "message": "Running",
326 "vca_status": "running",
327 "n2vc_status": N2VCDeploymentStatus
.PENDING
,
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"}
342 "db": Dict({"written": False, "data": None}),
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"}
358 "message": "Running",
360 "vca_status": "running",
361 "n2vc_status": N2VCDeploymentStatus
.COMPLETED
,
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"}
376 "db": Dict({"written": False, "data": None}),
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"}
394 "vca_status": "waiting",
395 "n2vc_status": N2VCDeploymentStatus
.RUNNING
,
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"}
410 "db": Dict({"written": False, "data": None}),
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"}
428 "vca_status": "active",
429 "n2vc_status": N2VCDeploymentStatus
.COMPLETED
,
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"}
444 "db": Dict({"written": False, "data": None}),
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(
454 "status": "maintenance",
455 "message": "installing charm software",
456 "vca_status": "maintenance",
464 "message": "installing charm software",
465 "entity": "application",
466 "vca_status": "maintenance",
467 "n2vc_status": N2VCDeploymentStatus
.RUNNING
,
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(
481 "status": "maintenance",
482 "message": "installing charm software",
483 "vca_status": "maintenance",
486 "db": Dict({"written": False, "data": None}),
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"}
503 "entity": "application",
504 "vca_status": "active",
505 "n2vc_status": N2VCDeploymentStatus
.COMPLETED
,
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"}
520 "db": Dict({"written": False, "data": None}),
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(
530 "status": "completed",
531 "message": "completed",
532 "vca_status": "completed",
540 "message": "completed",
542 "vca_status": "completed",
543 "n2vc_status": N2VCDeploymentStatus
.COMPLETED
,
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(
557 "status": "completed",
558 "message": "completed",
559 "vca_status": "completed",
562 "db": Dict({"written": False, "data": None}),