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
23 # Learn more at: https://juju.is/docs/sdk
27 This [library](https://juju.is/docs/sdk/libraries) implements both sides of the
28 `nbi` [interface](https://juju.is/docs/sdk/relations).
30 The *provider* side of this interface is implemented by the
31 [osm-nbi Charmed Operator](https://charmhub.io/osm-nbi).
33 Any Charmed Operator that *requires* NBI for providing its
34 service should implement the *requirer* side of this interface.
36 In a nutshell using this library to implement a Charmed Operator *requiring*
40 $ charmcraft fetch-lib charms.osm_nbi.v0.nbi
55 from charms.osm_nbi.v0.nbi import NbiRequires
56 from ops.charm import CharmBase
59 class MyCharm(CharmBase):
61 def __init__(self, *args):
62 super().__init__(*args)
63 self.nbi = NbiRequires(self)
64 self.framework.observe(
65 self.on["nbi"].relation_changed,
66 self._on_nbi_relation_changed,
68 self.framework.observe(
69 self.on["nbi"].relation_broken,
70 self._on_nbi_relation_broken,
72 self.framework.observe(
73 self.on["nbi"].relation_broken,
77 def _on_nbi_relation_broken(self, event):
78 # Get NBI host and port
79 host: str = self.nbi.host
80 port: int = self.nbi.port
84 def _on_nbi_broken(self, event):
87 self.unit.status = BlockedStatus("need nbi relation")
91 [here](https://osm.etsi.org/bugzilla/enter_bug.cgi), selecting the `devops` module!
93 from typing
import Optional
95 from ops
.charm
import CharmBase
, CharmEvents
96 from ops
.framework
import EventBase
, EventSource
, Object
97 from ops
.model
import Relation
100 # The unique Charmhub library identifier, never change it
101 LIBID
= "8c888f7c869949409e12c16d78ec068b"
103 # Increment this major API version when introducing breaking changes
106 # Increment this PATCH version before using `charmcraft publish-lib` or reset
107 # to 0 if you are raising the major API version
110 NBI_HOST_APP_KEY
= "host"
111 NBI_PORT_APP_KEY
= "port"
114 class NbiRequires(Object
): # pragma: no cover
115 """Requires-side of the Nbi relation."""
117 def __init__(self
, charm
: CharmBase
, endpoint_name
: str = "nbi") -> None:
118 super().__init
__(charm
, endpoint_name
)
120 self
._endpoint
_name
= endpoint_name
123 def host(self
) -> str:
124 """Get nbi hostname."""
125 relation
: Relation
= self
.model
.get_relation(self
._endpoint
_name
)
127 relation
.data
[relation
.app
].get(NBI_HOST_APP_KEY
)
128 if relation
and relation
.app
133 def port(self
) -> int:
134 """Get nbi port number."""
135 relation
: Relation
= self
.model
.get_relation(self
._endpoint
_name
)
137 int(relation
.data
[relation
.app
].get(NBI_PORT_APP_KEY
))
138 if relation
and relation
.app
143 class NbiProvides(Object
):
144 """Provides-side of the Nbi relation."""
146 def __init__(self
, charm
: CharmBase
, endpoint_name
: str = "nbi") -> None:
147 super().__init
__(charm
, endpoint_name
)
148 self
._endpoint
_name
= endpoint_name
150 def set_host_info(self
, host
: str, port
: int, relation
: Optional
[Relation
] = None) -> None:
151 """Set Nbi host and port.
153 This function writes in the application data of the relation, therefore,
154 only the unit leader can call it.
157 host (str): Nbi hostname or IP address.
158 port (int): Nbi port.
159 relation (Optional[Relation]): Relation to update.
160 If not specified, all relations will be updated.
163 Exception: if a non-leader unit calls this function.
165 if not self
.model
.unit
.is_leader():
166 raise Exception("only the leader set host information.")
169 self
._update
_relation
_data
(host
, port
, relation
)
172 for relation
in self
.model
.relations
[self
._endpoint
_name
]:
173 self
._update
_relation
_data
(host
, port
, relation
)
175 def _update_relation_data(self
, host
: str, port
: int, relation
: Relation
) -> None:
176 """Update data in relation if needed."""
177 relation
.data
[self
.model
.app
][NBI_HOST_APP_KEY
] = host
178 relation
.data
[self
.model
.app
][NBI_PORT_APP_KEY
] = str(port
)