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.
19 from unittest
.mock
import Mock
20 from n2vc
.definitions
import Offer
, RelationEndpoint
21 from n2vc
.k8s_juju_conn
import K8sJujuConnector
, RBAC_LABEL_KEY_NAME
22 from osm_common
import fslocal
23 from .utils
import kubeconfig
, FakeModel
, FakeFileWrapper
, AsyncMock
, FakeApplication
24 from n2vc
.exceptions
import (
28 from n2vc
.vca
.connection_data
import ConnectionData
31 class K8sJujuConnTestCase(asynctest
.TestCase
):
32 @asynctest.mock
.patch("n2vc.k8s_juju_conn.Libjuju")
33 @asynctest.mock
.patch("n2vc.k8s_juju_conn.MotorStore")
34 @asynctest.mock
.patch("n2vc.k8s_juju_conn.get_connection")
35 @asynctest.mock
.patch("n2vc.vca.connection_data.base64_to_cacert")
38 mock_base64_to_cacert
=None,
39 mock_get_connection
=None,
43 self
.loop
= asyncio
.get_event_loop()
45 mock_base64_to_cacert
.return_value
= """
46 -----BEGIN CERTIFICATE-----
48 -----END CERTIFICATE-----"""
49 mock_libjuju
.return_value
= Mock()
50 mock_store
.return_value
= AsyncMock()
51 mock_vca_connection
= Mock()
52 mock_get_connection
.return_value
= mock_vca_connection
53 mock_vca_connection
.data
.return_value
= ConnectionData(
55 "endpoints": ["1.2.3.4:17070"],
61 "lxd-credentials": "credentials",
62 "k8s-cloud": "k8s_cloud",
63 "k8s-credentials": "k8s_credentials",
65 "api-proxy": "api_proxy",
68 logging
.disable(logging
.CRITICAL
)
70 self
.kdu_name
= "kdu_name"
71 self
.kdu_instance
= "{}-{}".format(self
.kdu_name
, "id")
72 self
.default_namespace
= self
.kdu_instance
74 self
.k8s_juju_conn
= K8sJujuConnector(
81 self
.k8s_juju_conn
._store
.get_vca_id
.return_value
= None
82 self
.k8s_juju_conn
.libjuju
= Mock()
85 self
.kubectl
.get_secret_data
= AsyncMock()
86 self
.kubectl
.get_secret_data
.return_value
= ("token", "cacert")
87 self
.kubectl
.get_services
.return_value
= [{}]
88 self
.k8s_juju_conn
._get
_kubectl
= Mock()
89 self
.k8s_juju_conn
._get
_kubectl
.return_value
= self
.kubectl
90 self
.k8s_juju_conn
._obtain
_namespace
_from
_db
= Mock(
91 return_value
=self
.default_namespace
95 class InitEnvTest(K8sJujuConnTestCase
):
97 super(InitEnvTest
, self
).setUp()
98 self
.k8s_juju_conn
.libjuju
.add_k8s
= AsyncMock()
100 def test_with_cluster_uuid(
103 reuse_cluster_uuid
= "uuid"
104 uuid
, created
= self
.loop
.run_until_complete(
105 self
.k8s_juju_conn
.init_env(
106 k8s_creds
=kubeconfig
, reuse_cluster_uuid
=reuse_cluster_uuid
110 self
.assertTrue(created
)
111 self
.assertEqual(uuid
, reuse_cluster_uuid
)
112 self
.kubectl
.get_default_storage_class
.assert_called_once()
113 self
.k8s_juju_conn
.libjuju
.add_k8s
.assert_called_once()
115 def test_with_no_cluster_uuid(
118 uuid
, created
= self
.loop
.run_until_complete(
119 self
.k8s_juju_conn
.init_env(k8s_creds
=kubeconfig
)
122 self
.assertTrue(created
)
123 self
.assertTrue(isinstance(uuid
, str))
124 self
.kubectl
.get_default_storage_class
.assert_called_once()
125 self
.k8s_juju_conn
.libjuju
.add_k8s
.assert_called_once()
127 def test_init_env_exception(
130 self
.k8s_juju_conn
.libjuju
.add_k8s
.side_effect
= Exception()
133 with self
.assertRaises(Exception):
134 uuid
, created
= self
.loop
.run_until_complete(
135 self
.k8s_juju_conn
.init_env(k8s_creds
=kubeconfig
)
137 self
.assertIsNone(created
)
138 self
.assertIsNone(uuid
)
139 self
.kubectl
.create_cluster_role
.assert_called_once()
140 self
.kubectl
.create_service_account
.assert_called_once()
141 self
.kubectl
.create_cluster_role_binding
.assert_called_once()
142 self
.kubectl
.get_default_storage_class
.assert_called_once()
143 self
.kubectl
.delete_cluster_role
.assert_called_once()
144 self
.kubectl
.delete_service_account
.assert_called_once()
145 self
.kubectl
.delete_cluster_role_binding
.assert_called_once()
146 self
.k8s_juju_conn
.libjuju
.add_k8s
.assert_called_once()
149 class NotImplementedTest(K8sJujuConnTestCase
):
151 super(NotImplementedTest
, self
).setUp()
153 def test_repo_add(self
):
154 with self
.assertRaises(MethodNotImplemented
):
155 self
.loop
.run_until_complete(self
.k8s_juju_conn
.repo_add("", ""))
157 def test_repo_list(self
):
158 with self
.assertRaises(MethodNotImplemented
):
159 self
.loop
.run_until_complete(self
.k8s_juju_conn
.repo_list())
161 def test_repo_remove(self
):
162 with self
.assertRaises(MethodNotImplemented
):
163 self
.loop
.run_until_complete(self
.k8s_juju_conn
.repo_remove(""))
165 def test_synchronize_repos(self
):
167 self
.loop
.run_until_complete(self
.k8s_juju_conn
.synchronize_repos("", ""))
170 def test_upgrade(self
):
171 with self
.assertRaises(MethodNotImplemented
):
172 self
.loop
.run_until_complete(self
.k8s_juju_conn
.upgrade("", ""))
174 def test_rollback(self
):
175 with self
.assertRaises(MethodNotImplemented
):
176 self
.loop
.run_until_complete(self
.k8s_juju_conn
.rollback("", ""))
178 def test_get_namespace(self
):
179 self
.assertIsNone(self
.k8s_juju_conn
.get_namespace(""))
181 def test_instances_list(self
):
182 res
= self
.loop
.run_until_complete(self
.k8s_juju_conn
.instances_list(""))
183 self
.assertEqual(res
, [])
186 class ResetTest(K8sJujuConnTestCase
):
188 super(ResetTest
, self
).setUp()
189 self
.k8s_juju_conn
.libjuju
.remove_cloud
= AsyncMock()
190 self
.k8s_juju_conn
.libjuju
.get_cloud_credentials
= AsyncMock()
192 cloud_creds
.result
= {"attrs": {RBAC_LABEL_KEY_NAME
: "asd"}}
193 self
.k8s_juju_conn
.libjuju
.get_cloud_credentials
.return_value
= [cloud_creds
]
194 self
.k8s_juju_conn
.get_credentials
= Mock()
195 self
.k8s_juju_conn
.get_credentials
.return_value
= kubeconfig
197 def test_success(self
):
198 removed
= self
.loop
.run_until_complete(self
.k8s_juju_conn
.reset("uuid"))
199 self
.assertTrue(removed
)
200 self
.k8s_juju_conn
.libjuju
.remove_cloud
.assert_called_once()
202 def test_exception(self
):
204 self
.k8s_juju_conn
.libjuju
.remove_cloud
.side_effect
= Exception()
205 with self
.assertRaises(Exception):
206 removed
= self
.loop
.run_until_complete(self
.k8s_juju_conn
.reset("uuid"))
207 self
.assertIsNone(removed
)
208 self
.k8s_juju_conn
.libjuju
.remove_cloud
.assert_called_once()
211 @asynctest.mock
.patch("os.chdir")
212 class InstallTest(K8sJujuConnTestCase
):
214 super(InstallTest
, self
).setUp()
215 self
.db_dict
= {"filter": {"_id": "id"}}
216 self
.local_bundle
= "bundle"
217 self
.cs_bundle
= "cs:bundle"
218 self
.http_bundle
= "https://example.com/bundle.yaml"
219 self
.cluster_uuid
= "cluster"
220 self
.k8s_juju_conn
.libjuju
.add_model
= AsyncMock()
221 self
.k8s_juju_conn
.libjuju
.deploy
= AsyncMock()
223 def test_success_local(self
, mock_chdir
):
224 self
.loop
.run_until_complete(
225 self
.k8s_juju_conn
.install(
230 kdu_name
=self
.kdu_name
,
231 db_dict
=self
.db_dict
,
235 self
.assertEqual(mock_chdir
.call_count
, 2)
236 self
.k8s_juju_conn
.libjuju
.add_model
.assert_called_once()
237 self
.k8s_juju_conn
.libjuju
.deploy
.assert_called_once_with(
238 "local:{}".format(self
.local_bundle
),
239 model_name
=self
.default_namespace
,
244 def test_success_cs(self
, mock_chdir
):
245 self
.loop
.run_until_complete(
246 self
.k8s_juju_conn
.install(
251 kdu_name
=self
.kdu_name
,
252 db_dict
=self
.db_dict
,
256 self
.k8s_juju_conn
.libjuju
.add_model
.assert_called_once()
257 self
.k8s_juju_conn
.libjuju
.deploy
.assert_called_once_with(
259 model_name
=self
.default_namespace
,
264 def test_success_http(self
, mock_chdir
):
265 self
.loop
.run_until_complete(
266 self
.k8s_juju_conn
.install(
271 kdu_name
=self
.kdu_name
,
272 db_dict
=self
.db_dict
,
276 self
.k8s_juju_conn
.libjuju
.add_model
.assert_called_once()
277 self
.k8s_juju_conn
.libjuju
.deploy
.assert_called_once_with(
279 model_name
=self
.default_namespace
,
284 def test_success_not_kdu_name(self
, mock_chdir
):
285 self
.loop
.run_until_complete(
286 self
.k8s_juju_conn
.install(
291 db_dict
=self
.db_dict
,
295 self
.k8s_juju_conn
.libjuju
.add_model
.assert_called_once()
296 self
.k8s_juju_conn
.libjuju
.deploy
.assert_called_once_with(
298 model_name
=self
.default_namespace
,
303 def test_missing_db_dict(self
, mock_chdir
):
305 with self
.assertRaises(K8sException
):
306 self
.loop
.run_until_complete(
307 self
.k8s_juju_conn
.install(
312 kdu_name
=self
.kdu_name
,
316 self
.assertIsNone(kdu_instance
)
317 self
.k8s_juju_conn
.libjuju
.add_model
.assert_not_called()
318 self
.k8s_juju_conn
.libjuju
.deploy
.assert_not_called()
320 @asynctest.mock
.patch("os.getcwd")
321 def test_getcwd_exception(self
, mock_getcwd
, mock_chdir
):
322 mock_getcwd
.side_effect
= FileNotFoundError()
323 self
.loop
.run_until_complete(
324 self
.k8s_juju_conn
.install(
329 kdu_name
=self
.kdu_name
,
330 db_dict
=self
.db_dict
,
334 self
.k8s_juju_conn
.libjuju
.add_model
.assert_called_once()
335 self
.k8s_juju_conn
.libjuju
.deploy
.assert_called_once_with(
337 model_name
=self
.default_namespace
,
342 def test_missing_bundle(self
, mock_chdir
):
343 with self
.assertRaises(K8sException
):
344 self
.loop
.run_until_complete(
345 self
.k8s_juju_conn
.install(
350 kdu_name
=self
.kdu_name
,
352 db_dict
=self
.db_dict
,
355 self
.k8s_juju_conn
.libjuju
.add_model
.assert_not_called()
356 self
.k8s_juju_conn
.libjuju
.deploy
.assert_not_called()
358 def test_missing_exception(self
, mock_chdir
):
359 self
.k8s_juju_conn
.libjuju
.deploy
.side_effect
= Exception()
360 with self
.assertRaises(Exception):
361 self
.loop
.run_until_complete(
362 self
.k8s_juju_conn
.install(
367 kdu_name
=self
.kdu_name
,
368 db_dict
=self
.db_dict
,
372 self
.k8s_juju_conn
.libjuju
.add_model
.assert_called_once()
373 self
.k8s_juju_conn
.libjuju
.deploy
.assert_called_once_with(
374 "local:{}".format(self
.local_bundle
),
375 model_name
=self
.default_namespace
,
381 class UninstallTest(K8sJujuConnTestCase
):
383 super(UninstallTest
, self
).setUp()
384 self
.k8s_juju_conn
.libjuju
.destroy_model
= AsyncMock()
386 def test_success(self
):
387 destroyed
= self
.loop
.run_until_complete(
388 self
.k8s_juju_conn
.uninstall("cluster_uuid", "model_name")
390 self
.assertTrue(destroyed
)
391 self
.k8s_juju_conn
.libjuju
.destroy_model
.assert_called_once()
393 def test_exception(self
):
395 self
.k8s_juju_conn
.libjuju
.destroy_model
.side_effect
= Exception()
396 with self
.assertRaises(Exception):
397 destroyed
= self
.loop
.run_until_complete(
398 self
.k8s_juju_conn
.uninstall("cluster_uuid", "model_name")
400 self
.assertIsNone(destroyed
)
401 self
.k8s_juju_conn
.libjuju
.destroy_model
.assert_called_once()
404 class ExecPrimitivesTest(K8sJujuConnTestCase
):
406 super(ExecPrimitivesTest
, self
).setUp()
407 self
.action_name
= "touch"
408 self
.application_name
= "myapp"
409 self
.k8s_juju_conn
.libjuju
.get_actions
= AsyncMock()
410 self
.k8s_juju_conn
.libjuju
.execute_action
= AsyncMock()
412 def test_success(self
):
413 params
= {"application-name": self
.application_name
}
414 self
.k8s_juju_conn
.libjuju
.get_actions
.return_value
= [self
.action_name
]
415 self
.k8s_juju_conn
.libjuju
.execute_action
.return_value
= (
420 output
= self
.loop
.run_until_complete(
421 self
.k8s_juju_conn
.exec_primitive(
422 "cluster", self
.kdu_instance
, self
.action_name
, params
=params
426 self
.assertEqual(output
, "success")
427 self
.k8s_juju_conn
._obtain
_namespace
_from
_db
.assert_called_once_with(
428 kdu_instance
=self
.kdu_instance
430 self
.k8s_juju_conn
.libjuju
.get_actions
.assert_called_once_with(
431 application_name
=self
.application_name
, model_name
=self
.default_namespace
433 self
.k8s_juju_conn
.libjuju
.execute_action
.assert_called_once_with(
434 application_name
=self
.application_name
,
435 model_name
=self
.default_namespace
,
436 action_name
=self
.action_name
,
440 def test_exception(self
):
441 params
= {"application-name": self
.application_name
}
442 self
.k8s_juju_conn
.libjuju
.get_actions
.return_value
= [self
.action_name
]
443 self
.k8s_juju_conn
.libjuju
.execute_action
.side_effect
= Exception()
446 with self
.assertRaises(Exception):
447 output
= self
.loop
.run_until_complete(
448 self
.k8s_juju_conn
.exec_primitive(
449 "cluster", self
.kdu_instance
, self
.action_name
, params
=params
453 self
.assertIsNone(output
)
454 self
.k8s_juju_conn
._obtain
_namespace
_from
_db
.assert_called_once_with(
455 kdu_instance
=self
.kdu_instance
457 self
.k8s_juju_conn
.libjuju
.get_actions
.assert_called_once_with(
458 application_name
=self
.application_name
, model_name
=self
.default_namespace
460 self
.k8s_juju_conn
.libjuju
.execute_action
.assert_called_once_with(
461 application_name
=self
.application_name
,
462 model_name
=self
.default_namespace
,
463 action_name
=self
.action_name
,
467 def test_missing_application_name_in_params(self
):
471 with self
.assertRaises(K8sException
):
472 output
= self
.loop
.run_until_complete(
473 self
.k8s_juju_conn
.exec_primitive(
474 "cluster", self
.kdu_instance
, self
.action_name
, params
=params
478 self
.assertIsNone(output
)
479 self
.k8s_juju_conn
.libjuju
.get_actions
.assert_not_called()
480 self
.k8s_juju_conn
.libjuju
.execute_action
.assert_not_called()
482 def test_missing_params(self
):
484 with self
.assertRaises(K8sException
):
485 output
= self
.loop
.run_until_complete(
486 self
.k8s_juju_conn
.exec_primitive(
487 "cluster", self
.kdu_instance
, self
.action_name
491 self
.assertIsNone(output
)
492 self
.k8s_juju_conn
.libjuju
.get_actions
.assert_not_called()
493 self
.k8s_juju_conn
.libjuju
.execute_action
.assert_not_called()
495 def test_missing_action(self
):
497 params
= {"application-name": self
.application_name
}
498 self
.k8s_juju_conn
.libjuju
.get_actions
.return_value
= [self
.action_name
]
499 self
.k8s_juju_conn
.libjuju
.execute_action
.return_value
= (
503 with self
.assertRaises(K8sException
):
504 output
= self
.loop
.run_until_complete(
505 self
.k8s_juju_conn
.exec_primitive(
506 "cluster", self
.kdu_instance
, "non-existing-action", params
=params
510 self
.assertIsNone(output
)
511 self
.k8s_juju_conn
._obtain
_namespace
_from
_db
.assert_called_once_with(
512 kdu_instance
=self
.kdu_instance
514 self
.k8s_juju_conn
.libjuju
.get_actions
.assert_called_once_with(
515 application_name
=self
.application_name
, model_name
=self
.default_namespace
517 self
.k8s_juju_conn
.libjuju
.execute_action
.assert_not_called()
519 def test_missing_not_completed(self
):
521 params
= {"application-name": self
.application_name
}
522 self
.k8s_juju_conn
.libjuju
.get_actions
.return_value
= [self
.action_name
]
523 self
.k8s_juju_conn
.libjuju
.execute_action
.return_value
= (None, "failed")
524 with self
.assertRaises(K8sException
):
525 output
= self
.loop
.run_until_complete(
526 self
.k8s_juju_conn
.exec_primitive(
527 "cluster", self
.kdu_instance
, self
.action_name
, params
=params
531 self
.assertIsNone(output
)
532 self
.k8s_juju_conn
._obtain
_namespace
_from
_db
.assert_called_once_with(
533 kdu_instance
=self
.kdu_instance
535 self
.k8s_juju_conn
.libjuju
.get_actions
.assert_called_once_with(
536 application_name
=self
.application_name
, model_name
=self
.default_namespace
538 self
.k8s_juju_conn
.libjuju
.execute_action
.assert_called_once_with(
539 application_name
=self
.application_name
,
540 model_name
=self
.default_namespace
,
541 action_name
=self
.action_name
,
546 class InspectKduTest(K8sJujuConnTestCase
):
548 super(InspectKduTest
, self
).setUp()
550 @asynctest.mock
.patch("builtins.open")
551 @asynctest.mock
.patch("os.path.exists")
552 def test_existing_file(self
, mock_exists
, mock_open
):
553 mock_exists
.return_value
= True
555 'description': 'test bundle',
556 'bundle': 'kubernetes',
557 'applications': {'app':{ }, 'app2': { }}
559 mock_open
.return_value
= FakeFileWrapper(content
=content
)
560 kdu
= self
.loop
.run_until_complete(self
.k8s_juju_conn
.inspect_kdu("model"))
561 self
.assertEqual(kdu
, {"app": {}, "app2": {}})
562 mock_exists
.assert_called_once()
563 mock_open
.assert_called_once()
565 @asynctest.mock
.patch("builtins.open")
566 @asynctest.mock
.patch("os.path.exists")
567 def test_not_existing_file(self
, mock_exists
, mock_open
):
569 mock_exists
.return_value
= False
570 with self
.assertRaises(K8sException
):
571 kdu
= self
.loop
.run_until_complete(self
.k8s_juju_conn
.inspect_kdu("model"))
572 self
.assertEqual(kdu
, None)
573 mock_exists
.assert_called_once_with("model")
574 mock_open
.assert_not_called()
577 class HelpKduTest(K8sJujuConnTestCase
):
579 super(HelpKduTest
, self
).setUp()
581 @asynctest.mock
.patch("builtins.open")
582 @asynctest.mock
.patch("os.listdir")
583 def test_existing_file(self
, mock_listdir
, mock_open
):
584 content
= "Readme file content"
585 mock_open
.return_value
= FakeFileWrapper(content
=content
)
586 for file in ["README.md", "README.txt", "README"]:
587 mock_listdir
.return_value
= [file]
588 help = self
.loop
.run_until_complete(
589 self
.k8s_juju_conn
.help_kdu("kdu_instance")
591 self
.assertEqual(help, content
)
593 self
.assertEqual(mock_listdir
.call_count
, 3)
594 self
.assertEqual(mock_open
.call_count
, 3)
596 @asynctest.mock
.patch("builtins.open")
597 @asynctest.mock
.patch("os.listdir")
598 def test_not_existing_file(self
, mock_listdir
, mock_open
):
599 for file in ["src/charm.py", "tox.ini", "requirements.txt"]:
600 mock_listdir
.return_value
= [file]
601 help = self
.loop
.run_until_complete(
602 self
.k8s_juju_conn
.help_kdu("kdu_instance")
604 self
.assertEqual(help, None)
606 self
.assertEqual(mock_listdir
.call_count
, 3)
607 self
.assertEqual(mock_open
.call_count
, 0)
610 class StatusKduTest(K8sJujuConnTestCase
):
612 super(StatusKduTest
, self
).setUp()
613 self
.k8s_juju_conn
.libjuju
.get_model_status
= AsyncMock()
615 def test_success(self
):
616 applications
= {"app": {"status": {"status": "active"}}}
617 model
= FakeModel(applications
=applications
)
618 self
.k8s_juju_conn
.libjuju
.get_model_status
.return_value
= model
619 status
= self
.loop
.run_until_complete(
620 self
.k8s_juju_conn
.status_kdu("cluster", "kdu_instance")
622 self
.assertEqual(status
, {"app": {"status": "active"}})
623 self
.k8s_juju_conn
.libjuju
.get_model_status
.assert_called_once()
625 def test_exception(self
):
626 self
.k8s_juju_conn
.libjuju
.get_model_status
.side_effect
= Exception()
628 with self
.assertRaises(Exception):
629 status
= self
.loop
.run_until_complete(
630 self
.k8s_juju_conn
.status_kdu("cluster", "kdu_instance")
632 self
.assertIsNone(status
)
633 self
.k8s_juju_conn
.libjuju
.get_model_status
.assert_called_once()
636 class GetServicesTest(K8sJujuConnTestCase
):
638 super(GetServicesTest
, self
).setUp()
640 @asynctest.mock
.patch("n2vc.k8s_juju_conn.K8sJujuConnector.get_credentials")
641 def test_success(self
, mock_get_credentials
):
642 mock_get_credentials
.return_value
= kubeconfig
643 self
.loop
.run_until_complete(self
.k8s_juju_conn
.get_services("", "", ""))
644 mock_get_credentials
.assert_called_once()
645 self
.kubectl
.get_services
.assert_called_once()
648 class GetServiceTest(K8sJujuConnTestCase
):
650 super(GetServiceTest
, self
).setUp()
652 @asynctest.mock
.patch("n2vc.k8s_juju_conn.K8sJujuConnector.get_credentials")
653 def test_success(self
, mock_get_credentials
):
654 mock_get_credentials
.return_value
= kubeconfig
655 self
.loop
.run_until_complete(self
.k8s_juju_conn
.get_service("", "", ""))
656 mock_get_credentials
.assert_called_once()
657 self
.kubectl
.get_services
.assert_called_once()
660 class GetCredentialsTest(K8sJujuConnTestCase
):
662 super(GetCredentialsTest
, self
).setUp()
664 @asynctest.mock
.patch("yaml.safe_dump")
665 def test_success(self
, mock_safe_dump
):
666 self
.k8s_juju_conn
.db
.get_one
.return_value
= {
668 "credentials": "credentials",
669 "schema_version": "2",
671 self
.k8s_juju_conn
.get_credentials("cluster_uuid")
672 self
.k8s_juju_conn
.db
.get_one
.assert_called_once()
673 self
.k8s_juju_conn
.db
.encrypt_decrypt_fields
.assert_called_once()
674 mock_safe_dump
.assert_called_once()
677 class UpdateVcaStatusTest(K8sJujuConnTestCase
):
679 super(UpdateVcaStatusTest
, self
).setUp()
680 self
.vcaStatus
= {"model": {"applications": {"app": {"actions": {}}}}}
681 self
.k8s_juju_conn
.libjuju
.get_executed_actions
= AsyncMock()
682 self
.k8s_juju_conn
.libjuju
.get_actions
= AsyncMock()
683 self
.k8s_juju_conn
.libjuju
.get_application_configs
= AsyncMock()
685 def test_success(self
):
686 self
.loop
.run_until_complete(
687 self
.k8s_juju_conn
.update_vca_status(self
.vcaStatus
, self
.kdu_instance
)
689 self
.k8s_juju_conn
.libjuju
.get_executed_actions
.assert_called_once()
690 self
.k8s_juju_conn
.libjuju
.get_application_configs
.assert_called_once()
692 def test_exception(self
):
693 self
.k8s_juju_conn
.libjuju
.get_model
.return_value
= None
694 self
.k8s_juju_conn
.libjuju
.get_executed_actions
.side_effect
= Exception()
695 with self
.assertRaises(Exception):
696 self
.loop
.run_until_complete(
697 self
.k8s_juju_conn
.update_vca_status(self
.vcaStatus
, self
.kdu_instance
)
699 self
.k8s_juju_conn
.libjuju
.get_executed_actions
.assert_not_called()
700 self
.k8s_juju_conn
.libjuju
.get_application_configs
.assert_not_called_once()
703 class ScaleTest(K8sJujuConnTestCase
):
705 super(ScaleTest
, self
).setUp()
706 self
.application_name
= "app"
707 self
.kdu_name
= "kdu-instance"
709 self
.k8s_juju_conn
.libjuju
.scale_application
= AsyncMock()
711 def test_success(self
):
712 self
.loop
.run_until_complete(
713 self
.k8s_juju_conn
.scale(self
.kdu_name
, self
._scale
, self
.application_name
)
715 self
.k8s_juju_conn
.libjuju
.scale_application
.assert_called_once()
717 def test_exception(self
):
718 self
.k8s_juju_conn
.libjuju
.scale_application
.side_effect
= Exception()
719 with self
.assertRaises(Exception):
720 self
.loop
.run_until_complete(
721 self
.k8s_juju_conn
.scale(
722 self
.kdu_name
, self
._scale
, self
.application_name
725 self
.k8s_juju_conn
.libjuju
.scale_application
.assert_called_once()
728 class GetScaleCount(K8sJujuConnTestCase
):
730 super(GetScaleCount
, self
).setUp()
731 self
.k8s_juju_conn
.libjuju
.get_model_status
= AsyncMock()
733 def test_success(self
):
734 applications
= {"app": FakeApplication()}
735 model
= FakeModel(applications
=applications
)
736 self
.k8s_juju_conn
.libjuju
.get_model_status
.return_value
= model
737 status
= self
.loop
.run_until_complete(
738 self
.k8s_juju_conn
.get_scale_count("app", "kdu_instance")
740 self
.assertEqual(status
, 2)
741 self
.k8s_juju_conn
.libjuju
.get_model_status
.assert_called_once()
743 def test_exception(self
):
744 self
.k8s_juju_conn
.libjuju
.get_model_status
.side_effect
= Exception()
746 with self
.assertRaises(Exception):
747 status
= self
.loop
.run_until_complete(
748 self
.k8s_juju_conn
.status_kdu("app", "kdu_instance")
750 self
.assertIsNone(status
)
751 self
.k8s_juju_conn
.libjuju
.get_model_status
.assert_called_once()
754 class AddRelationTest(K8sJujuConnTestCase
):
756 super(AddRelationTest
, self
).setUp()
757 self
.k8s_juju_conn
.libjuju
.add_relation
= AsyncMock()
758 self
.k8s_juju_conn
.libjuju
.offer
= AsyncMock()
759 self
.k8s_juju_conn
.libjuju
.get_controller
= AsyncMock()
760 self
.k8s_juju_conn
.libjuju
.consume
= AsyncMock()
762 def test_standard_relation(self
):
763 relation_endpoint_1
= RelationEndpoint("model-1.app1.0", None, "endpoint")
764 relation_endpoint_2
= RelationEndpoint("model-1.app2.1", None, "endpoint")
765 self
.loop
.run_until_complete(
766 self
.k8s_juju_conn
.add_relation(relation_endpoint_1
, relation_endpoint_2
)
768 self
.k8s_juju_conn
.libjuju
.add_relation
.assert_called_once_with(
769 model_name
="model-1", endpoint_1
="app1:endpoint", endpoint_2
="app2:endpoint"
771 self
.k8s_juju_conn
.libjuju
.offer
.assert_not_called()
772 self
.k8s_juju_conn
.libjuju
.consume
.assert_not_called()
774 def test_cmr_relation_same_controller(self
):
775 relation_endpoint_1
= RelationEndpoint("model-1.app1.0", None, "endpoint")
776 relation_endpoint_2
= RelationEndpoint("model-2.app2.1", None, "endpoint")
777 offer
= Offer("admin/model-1.app1")
778 self
.k8s_juju_conn
.libjuju
.offer
.return_value
= offer
779 self
.k8s_juju_conn
.libjuju
.consume
.return_value
= "saas"
780 self
.loop
.run_until_complete(
781 self
.k8s_juju_conn
.add_relation(relation_endpoint_1
, relation_endpoint_2
)
783 self
.k8s_juju_conn
.libjuju
.offer
.assert_called_once_with(relation_endpoint_1
)
784 self
.k8s_juju_conn
.libjuju
.consume
.assert_called_once()
785 self
.k8s_juju_conn
.libjuju
.add_relation
.assert_called_once_with(
786 "model-2", "app2:endpoint", "saas"
789 def test_relation_exception(self
):
790 relation_endpoint_1
= RelationEndpoint("model-1.app1.0", None, "endpoint")
791 relation_endpoint_2
= RelationEndpoint("model-2.app2.1", None, "endpoint")
792 self
.k8s_juju_conn
.libjuju
.offer
.side_effect
= Exception()
793 with self
.assertRaises(Exception):
794 self
.loop
.run_until_complete(
795 self
.k8s_juju_conn
.add_relation(
796 relation_endpoint_1
, relation_endpoint_2