Merge ~cjwatson/launchpad-layers:interface-apache-vhost-config into launchpad-layers:main

Proposed by Colin Watson
Status: Merged
Merged at revision: 8b7d25a29b8297d491abe6a0c6b69f34e39dddba
Proposed branch: ~cjwatson/launchpad-layers:interface-apache-vhost-config
Merge into: launchpad-layers:main
Diff against target: 68 lines (+56/-0)
2 files modified
apache-vhost-config/interface.yaml (+3/-0)
apache-vhost-config/provides.py (+53/-0)
Reviewer Review Type Date Requested Status
Ines Almeida Approve
Review via email: mp+447537@code.launchpad.net

Commit message

Add interface to publish Apache virtual host configuration

Description of the change

This implements the interface described under "Using the vhost-config relation" in https://git.launchpad.net/apache2-charm/tree/README.md. It will allow us to put the desired Apache frontend configuration in the corresponding service charm and then just add some relations to make everything work. I have a functioning prototype of this for the librarian.

To post a comment you must log in.
Revision history for this message
Ines Almeida (ines-almeida) wrote :

I'm fairly new to these interfaces, so can you explain me why this interface doesn't need a `requires.py` side? Does the apache charm just access the published data directly?

Regardless, this looks good to me. I like the `dataclass` use, will keep that in mind if I need to build new interfaces that pass data on

review: Approve
Revision history for this message
Colin Watson (cjwatson) wrote :

Yeah, the only charm on the requires side of the interface at the moment is the Apache charm, which is a bare charm (pre-reactive), and just does this sort of thing directly:

```
    relation_data = relations_of_type("vhost-config")
    ...
    for unit_data in relation_data:
        if "vhosts" in unit_data:
            ...
```

There's no specific reason that the requires side couldn't be implemented here, but I didn't see much point in writing that out here when nothing would be using it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/apache-vhost-config/interface.yaml b/apache-vhost-config/interface.yaml
2new file mode 100644
3index 0000000..0394b31
4--- /dev/null
5+++ b/apache-vhost-config/interface.yaml
6@@ -0,0 +1,3 @@
7+name: apache-vhost-config
8+summary: Apache virtual host configuration interface
9+version: 1
10diff --git a/apache-vhost-config/provides.py b/apache-vhost-config/provides.py
11new file mode 100644
12index 0000000..7bd4a3e
13--- /dev/null
14+++ b/apache-vhost-config/provides.py
15@@ -0,0 +1,53 @@
16+# Copyright 2023 Canonical Ltd. This software is licensed under the
17+# GNU Affero General Public License version 3 (see the file LICENSE).
18+
19+import base64
20+from dataclasses import dataclass
21+from typing import Dict, Iterable
22+
23+from charmhelpers.core import hookenv
24+from charms.reactive import Endpoint, clear_flag, set_flag, when
25+
26+
27+@dataclass
28+class Vhost:
29+ port: int
30+ template: str
31+
32+ def to_publish(self) -> Dict[str, str]:
33+ return {
34+ "port": self.port,
35+ "template": base64.b64encode(self.template.encode()).decode(),
36+ }
37+
38+
39+class ApacheVhostConfigProvides(Endpoint):
40+ @when("endpoint.{endpoint_name}.joined")
41+ def handle_joined_unit(self):
42+ set_flag(self.expand_name("{endpoint_name}.available"))
43+
44+ @when("endpoint.{endpoint_name}.changed")
45+ def handle_changed_unit(self):
46+ set_flag(self.expand_name("{endpoint_name}.available"))
47+ clear_flag(self.expand_name("changed"))
48+
49+ @when("endpoint.{endpoint_name}.departed")
50+ def handle_departed_unit(self):
51+ clear_flag(self.expand_name("{endpoint_name}.available"))
52+ self.all_departed_units.clear()
53+ clear_flag(self.expand_name("departed"))
54+
55+ def make_vhost(self, port: int, template: str):
56+ """Prepare a vhost entry for use by `publish_vhosts`."""
57+ return Vhost(port=port, template=template)
58+
59+ def publish_vhosts(self, vhosts: Iterable[Vhost]):
60+ """Publish virtual host configurations for use by the Apache charm.
61+
62+ :param vhosts: An iterable of objects returned by `make_vhost`.
63+ """
64+ hookenv.log("Publishing Apache virtual host configurations")
65+ for relation in self.relations:
66+ relation.to_publish.update(
67+ {"vhosts": [vhost.to_publish() for vhost in vhosts]}
68+ )

Subscribers

People subscribed via source and target branches