Coverage for n2vc/vca/connection.py: 100%

47 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-05-07 06:04 +0000

1# Copyright 2021 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 

15import typing 

16 

17from n2vc.config import EnvironConfig, ModelConfig 

18from n2vc.store import Store 

19from n2vc.vca.cloud import Cloud 

20from n2vc.vca.connection_data import ConnectionData 

21 

22 

23class Connection: 

24 def __init__(self, store: Store, vca_id: str = None): 

25 """ 

26 Contructor 

27 

28 :param: store: Store object. Used to communicate wuth the DB 

29 :param: vca_id: Id of the VCA. If none specified, the default VCA will be used. 

30 """ 

31 self._data = None 

32 self.default = vca_id is None 

33 self._vca_id = vca_id 

34 self._store = store 

35 

36 async def load(self): 

37 """Load VCA connection data""" 

38 await self._load_vca_connection_data() 

39 

40 @property 

41 def is_default(self): 

42 return self._vca_id is None 

43 

44 @property 

45 def data(self) -> ConnectionData: 

46 return self._data 

47 

48 async def _load_vca_connection_data(self) -> typing.NoReturn: 

49 """ 

50 Load VCA connection data 

51 

52 If self._vca_id is None, it will get the VCA data from the Environment variables, 

53 and the default VCA will be used. If it is not None, then it means that it will 

54 load the credentials from the database (A non-default VCA will be used). 

55 """ 

56 if self._vca_id: 

57 self._data = await self._store.get_vca_connection_data(self._vca_id) 

58 else: 

59 envs = EnvironConfig() 

60 # Get endpoints from the DB and ENV. Check if update in the database is needed or not. 

61 db_endpoints = await self._store.get_vca_endpoints() 

62 env_endpoints = ( 

63 envs["endpoints"].split(",") 

64 if "endpoints" in envs 

65 else ["{}:{}".format(envs["host"], envs.get("port", 17070))] 

66 ) 

67 

68 db_update_needed = not all(e in db_endpoints for e in env_endpoints) 

69 

70 endpoints = env_endpoints if db_update_needed else db_endpoints 

71 config = { 

72 "endpoints": endpoints, 

73 "user": envs["user"], 

74 "secret": envs["secret"], 

75 "cacert": envs["cacert"], 

76 "pubkey": envs.get("pubkey"), 

77 "lxd-cloud": envs.get("cloud"), 

78 "lxd-credentials": envs.get("credentials", envs.get("cloud")), 

79 "k8s-cloud": envs.get("k8s_cloud"), 

80 "k8s-credentials": envs.get("k8s_credentials", envs.get("k8s_cloud")), 

81 "model-config": ModelConfig(envs), 

82 "api-proxy": envs.get("api_proxy", None), 

83 } 

84 self._data = ConnectionData(**config) 

85 if db_update_needed: 

86 await self.update_endpoints(endpoints) 

87 

88 @property 

89 def endpoints(self): 

90 return self._data.endpoints 

91 

92 async def update_endpoints(self, endpoints: typing.List[str]): 

93 await self._store.update_vca_endpoints(endpoints, self._vca_id) 

94 self._data.endpoints = endpoints 

95 

96 @property 

97 def lxd_cloud(self) -> Cloud: 

98 return Cloud(self.data.lxd_cloud, self.data.lxd_credentials) 

99 

100 @property 

101 def k8s_cloud(self) -> Cloud: 

102 return Cloud(self.data.k8s_cloud, self.data.k8s_credentials) 

103 

104 

105async def get_connection(store: Store, vca_id: str = None) -> Connection: 

106 """ 

107 Get Connection 

108 

109 Method to get a Connection object with the VCA information loaded 

110 """ 

111 connection = Connection(store, vca_id=vca_id) 

112 await connection.load() 

113 return connection