Merge ~davigar15/charm-k8s-ingress:master into charm-k8s-ingress:master

Proposed by David
Status: Merged
Approved by: Tom Haddon
Approved revision: 9d4f6d6862c3dc7b13011744d216bd551b0953fa
Merged at revision: 3322e29004b466b33e8ed912cb62f321ea8f79e1
Proposed branch: ~davigar15/charm-k8s-ingress:master
Merge into: charm-k8s-ingress:master
Diff against target: 147 lines (+78/-0)
3 files modified
lib/charms/nginx_ingress_integrator/v0/ingress.py (+14/-0)
src/charm.py (+52/-0)
tests/unit/test_charm.py (+12/-0)
Reviewer Review Type Date Requested Status
Tom Haddon Needs Fixing
Review via email: mp+412351@code.launchpad.net

Commit message

Fix bug #1939698: remove k8s resources on relation-departed

Description of the change

This change fixes the deletion of the k8s resources when the relation is departed. It will delete both the service and the ingress resources that the charm creates.

To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Tom Haddon (mthaddon) wrote :

Some comments inline

review: Needs Fixing
Revision history for this message
Tom Haddon (mthaddon) wrote :

One very minor lint fix needed.

Revision history for this message
Tom Haddon (mthaddon) wrote :

LGTM, thx

Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision 3322e29004b466b33e8ed912cb62f321ea8f79e1

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/charms/nginx_ingress_integrator/v0/ingress.py b/lib/charms/nginx_ingress_integrator/v0/ingress.py
2index d10839c..1871e20 100644
3--- a/lib/charms/nginx_ingress_integrator/v0/ingress.py
4+++ b/lib/charms/nginx_ingress_integrator/v0/ingress.py
5@@ -94,10 +94,15 @@ class IngressAvailableEvent(EventBase):
6 pass
7
8
9+class IngressBrokenEvent(EventBase):
10+ pass
11+
12+
13 class IngressCharmEvents(CharmEvents):
14 """Custom charm events."""
15
16 ingress_available = EventSource(IngressAvailableEvent)
17+ ingress_broken = EventSource(IngressBrokenEvent)
18
19
20 class IngressRequires(Object):
21@@ -173,6 +178,7 @@ class IngressProvides(Object):
22 # Observe the relation-changed hook event and bind
23 # self.on_relation_changed() to handle the event.
24 self.framework.observe(charm.on["ingress"].relation_changed, self._on_relation_changed)
25+ self.framework.observe(charm.on["ingress"].relation_broken, self._on_relation_broken)
26 self.charm = charm
27
28 def _on_relation_changed(self, event):
29@@ -209,3 +215,11 @@ class IngressProvides(Object):
30 # Create an event that our charm can use to decide it's okay to
31 # configure the ingress.
32 self.charm.on.ingress_available.emit()
33+
34+ def _on_relation_broken(self, _):
35+ """Handle a relation-broken event in the ingress relation."""
36+ if not self.model.unit.is_leader():
37+ return
38+
39+ # Create an event that our charm can use to remove the ingress resource.
40+ self.charm.on.ingress_broken.emit()
41diff --git a/src/charm.py b/src/charm.py
42index 421df63..38a5255 100755
43--- a/src/charm.py
44+++ b/src/charm.py
45@@ -45,6 +45,7 @@ class NginxIngressCharm(CharmBase):
46 self.ingress = IngressProvides(self)
47 # When the 'ingress' is ready to configure, do so.
48 self.framework.observe(self.on.ingress_available, self._on_config_changed)
49+ self.framework.observe(self.on.ingress_broken, self._on_ingress_broken)
50
51 def _describe_ingresses_action(self, event):
52 """Handle the 'describe-ingresses' action."""
53@@ -315,6 +316,22 @@ class NginxIngressCharm(CharmBase):
54 self._service_name,
55 )
56
57+ def _remove_service(self):
58+ """Remove the created service in kubernetes."""
59+ self.k8s_auth()
60+ api = _core_v1_api()
61+ services = api.list_namespaced_service(namespace=self._namespace)
62+ if self._k8s_service_name in [x.metadata.name for x in services.items]:
63+ api.delete_namespaced_service(
64+ name=self._k8s_service_name,
65+ namespace=self._namespace,
66+ )
67+ logger.info(
68+ "Service deleted in namespace %s with name %s",
69+ self._namespace,
70+ self._service_name,
71+ )
72+
73 def _look_up_and_set_ingress_class(self, api, body):
74 """Set the configured ingress class, otherwise the cluster's default ingress class."""
75 ingress_class = self.config['ingress-class']
76@@ -373,6 +390,19 @@ class NginxIngressCharm(CharmBase):
77 self._ingress_name,
78 )
79
80+ def _remove_ingress(self):
81+ """Remove ingress resource."""
82+ self.k8s_auth()
83+ api = _networking_v1_api()
84+ ingresses = api.list_namespaced_ingress(namespace=self._namespace)
85+ if self._ingress_name in [x.metadata.name for x in ingresses.items]:
86+ api.delete_namespaced_ingress(self._ingress_name, self._namespace)
87+ logger.info(
88+ "Ingress deleted in namespace %s with name %s",
89+ self._namespace,
90+ self._ingress_name,
91+ )
92+
93 def _on_config_changed(self, _):
94 """Handle the config changed event."""
95 msg = ""
96@@ -403,6 +433,28 @@ class NginxIngressCharm(CharmBase):
97 raise
98 self.unit.status = ActiveStatus(msg)
99
100+ def _on_ingress_broken(self, _):
101+ """Handle the ingress broken event."""
102+ if self.unit.is_leader() and self._ingress_name:
103+ try:
104+ self._remove_ingress()
105+ self._remove_service()
106+ except kubernetes.client.exceptions.ApiException as e:
107+ if e.status == 403:
108+ logger.error(
109+ "Insufficient permissions to delete the k8s ingress resource, "
110+ "will request `juju trust` to be run"
111+ )
112+ self.unit.status = BlockedStatus(
113+ "Insufficient permissions, try: `juju trust {} --scope=cluster`".format(
114+ self.app.name
115+ )
116+ )
117+ return
118+ else:
119+ raise
120+ self.unit.status = ActiveStatus()
121+
122
123 if __name__ == "__main__": # pragma: no cover
124 main(NginxIngressCharm)
125diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py
126index c3e52c2..936eddc 100644
127--- a/tests/unit/test_charm.py
128+++ b/tests/unit/test_charm.py
129@@ -385,6 +385,18 @@ class TestCharm(unittest.TestCase):
130 self.assertEqual(self.harness.charm._service_name, "gunicorn")
131 self.assertEqual(self.harness.charm._service_port, 80)
132
133+ @patch('charm.NginxIngressCharm._remove_ingress')
134+ @patch('charm.NginxIngressCharm._remove_service')
135+ def test_on_ingress_relation_broken(self, _remove_service, _remove_ingress):
136+ """Test relation-broken."""
137+ # Call the test test_on_ingress_relation_changed first
138+ # to make sure the relation is created and therefore can be removed.
139+ self.test_on_ingress_relation_changed()
140+ relation = self.harness.charm.model.get_relation("ingress")
141+ self.harness.charm.on.ingress_relation_broken.emit(relation)
142+ self.assertEqual(_remove_ingress.call_count, 1)
143+ self.assertEqual(_remove_service.call_count, 1)
144+
145 def test_get_k8s_ingress(self):
146 """Test getting our definition of a k8s ingress."""
147 self.harness.disable_hooks()

Subscribers

People subscribed via source and target branches

to all changes: