2 # Copyright 2022 Canonical Ltd.
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
16 # For those usages not covered by the Apache License, Version 2.0 please
17 # contact: legal@canonical.com
19 # To get in touch with the maintainers, please contact:
20 # osm-charmers@lists.launchpad.net
27 class BaseRelationClient(ops
.framework
.Object
):
28 """Requires side of a Kafka Endpoint"""
32 charm
: ops
.charm
.CharmBase
,
34 mandatory_fields
: list = [],
36 super().__init
__(charm
, relation_name
)
37 self
.relation_name
= relation_name
38 self
.mandatory_fields
= mandatory_fields
39 self
._update
_relation
()
41 def get_data_from_unit(self
, key
: str):
43 # This update relation doesn't seem to be needed, but I added it because apparently
44 # the data is empty in the unit tests.
45 # In reality, the constructor is called in every hook.
46 # In the unit tests when doing an update_relation_data, apparently it is not called.
47 self
._update
_relation
()
49 for unit
in self
.relation
.units
:
50 data
= self
.relation
.data
[unit
].get(key
)
54 def get_data_from_app(self
, key
: str):
55 if not self
.relation
or self
.relation
.app
not in self
.relation
.data
:
56 # This update relation doesn't seem to be needed, but I added it because apparently
57 # the data is empty in the unit tests.
58 # In reality, the constructor is called in every hook.
59 # In the unit tests when doing an update_relation_data, apparently it is not called.
60 self
._update
_relation
()
61 if self
.relation
and self
.relation
.app
in self
.relation
.data
:
62 data
= self
.relation
.data
[self
.relation
.app
].get(key
)
66 def is_missing_data_in_unit(self
):
67 return not all([self
.get_data_from_unit(field
) for field
in self
.mandatory_fields
])
69 def is_missing_data_in_app(self
):
70 return not all([self
.get_data_from_app(field
) for field
in self
.mandatory_fields
])
72 def _update_relation(self
):
73 self
.relation
= self
.framework
.model
.get_relation(self
.relation_name
)
76 class KeystoneClient(BaseRelationClient
):
77 """Requires side of a Keystone Endpoint"""
83 "project_domain_name",
87 "keystone_db_password",
94 def __init__(self
, charm
: ops
.charm
.CharmBase
, relation_name
: str):
95 super().__init
__(charm
, relation_name
, self
.mandatory_fields
)
99 return self
.get_data_from_app("host")
103 return self
.get_data_from_app("port")
106 def user_domain_name(self
):
107 return self
.get_data_from_app("user_domain_name")
110 def project_domain_name(self
):
111 return self
.get_data_from_app("project_domain_name")
115 return self
.get_data_from_app("username")
119 return self
.get_data_from_app("password")
123 return self
.get_data_from_app("service")
126 def keystone_db_password(self
):
127 return self
.get_data_from_app("keystone_db_password")
131 return self
.get_data_from_app("region_id")
134 def admin_username(self
):
135 return self
.get_data_from_app("admin_username")
138 def admin_password(self
):
139 return self
.get_data_from_app("admin_password")
142 def admin_project_name(self
):
143 return self
.get_data_from_app("admin_project_name")
146 class MongoClient(BaseRelationClient
):
147 """Requires side of a Mongo Endpoint"""
149 mandatory_fields_mapping
= {
150 "reactive": ["connection_string"],
151 "ops": ["replica_set_uri", "replica_set_name"],
154 def __init__(self
, charm
: ops
.charm
.CharmBase
, relation_name
: str):
155 super().__init
__(charm
, relation_name
, mandatory_fields
=[])
158 def connection_string(self
):
160 replica_set_uri
= self
.get_data_from_unit("replica_set_uri")
161 replica_set_name
= self
.get_data_from_unit("replica_set_name")
162 return f
"{replica_set_uri}?replicaSet={replica_set_name}"
164 return self
.get_data_from_unit("connection_string")
167 return not self
.is_missing_data_in_unit_ops()
169 def is_missing_data_in_unit(self
):
170 return self
.is_missing_data_in_unit_ops() and self
.is_missing_data_in_unit_reactive()
172 def is_missing_data_in_unit_ops(self
):
174 [self
.get_data_from_unit(field
) for field
in self
.mandatory_fields_mapping
["ops"]]
177 def is_missing_data_in_unit_reactive(self
):
179 [self
.get_data_from_unit(field
) for field
in self
.mandatory_fields_mapping
["reactive"]]
183 class PrometheusClient(BaseRelationClient
):
184 """Requires side of a Prometheus Endpoint"""
186 mandatory_fields
= ["hostname", "port"]
188 def __init__(self
, charm
: ops
.charm
.CharmBase
, relation_name
: str):
189 super().__init
__(charm
, relation_name
, self
.mandatory_fields
)
193 return self
.get_data_from_app("hostname")
197 return self
.get_data_from_app("port")
201 return self
.get_data_from_app("user")
205 return self
.get_data_from_app("password")