Merge ~mthaddon/charm-k8s-ingress/+git/charm-k8s-ingress:hostname-over-relation into charm-k8s-ingress:master

Proposed by Tom Haddon
Status: Merged
Approved by: Jon Seager
Approved revision: f11595ecfdd3f4209e1f914e55ed80ff116ea50f
Merged at revision: ca4cc16e34018af2f1782e2b974483ba59be68da
Proposed branch: ~mthaddon/charm-k8s-ingress/+git/charm-k8s-ingress:hostname-over-relation
Merge into: charm-k8s-ingress:master
Diff against target: 181 lines (+84/-17)
2 files modified
src/charm.py (+40/-16)
tests/unit/test_charm.py (+44/-1)
Reviewer Review Type Date Requested Status
🤖 prod-jenkaas-is (community) continuous-integration Approve
ingress-charmers Pending
Review via email: mp+400310@code.launchpad.net

Commit message

If service-hostname is passed via the relation, use it. Also allow other properties to be passed via the relation.

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
🤖 prod-jenkaas-is (prod-jenkaas-is) wrote :

A CI job is currently in progress. A follow up comment will be added when it completes.

Revision history for this message
🤖 prod-jenkaas-is (prod-jenkaas-is) wrote :

PASSED: Continuous integration, rev:f1731b33b23bc9f1ef64a398f8324870c5bce4f2
https://jenkins.canonical.com/is/job/lp-charm-k8s-ingress-ci/13/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/is/job/lp-charm-test/43/
    None: https://jenkins.canonical.com/is/job/lp-update-mp/57088/

Click here to trigger a rebuild:
https://jenkins.canonical.com/is/job/lp-charm-k8s-ingress-ci/13//rebuild

review: Approve (continuous-integration)
Revision history for this message
🤖 prod-jenkaas-is (prod-jenkaas-is) wrote :

A CI job is currently in progress. A follow up comment will be added when it completes.

Revision history for this message
🤖 prod-jenkaas-is (prod-jenkaas-is) wrote :

PASSED: Continuous integration, rev:f11595ecfdd3f4209e1f914e55ed80ff116ea50f
https://jenkins.canonical.com/is/job/lp-charm-k8s-ingress-ci/14/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/is/job/lp-charm-test/44/
    None: https://jenkins.canonical.com/is/job/lp-update-mp/57138/

Click here to trigger a rebuild:
https://jenkins.canonical.com/is/job/lp-charm-k8s-ingress-ci/14//rebuild

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

Change successfully merged at revision ca4cc16e34018af2f1782e2b974483ba59be68da

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/charm.py b/src/charm.py
2index a206ba7..146ddc7 100755
3--- a/src/charm.py
4+++ b/src/charm.py
5@@ -103,6 +103,14 @@ class CharmK8SIngressCharm(CharmBase):
6 self._on_config_changed(event)
7
8 @property
9+ def _k8s_service_name(self):
10+ """Return a service name for the use creating a k8s service."""
11+ # Avoid collision with service name created by Juju. Currently
12+ # Juju creates a K8s service listening on port 65535/TCP so we
13+ # need to create a separate one.
14+ return "{}-service".format(self._service_name)
15+
16+ @property
17 def _ingress_name(self):
18 """Return an ingress name for use creating a k8s ingress."""
19 # Follow the same naming convention as Juju.
20@@ -111,6 +119,12 @@ class CharmK8SIngressCharm(CharmBase):
21 )
22
23 @property
24+ def _max_body_size(self):
25+ """Return the max-body-size to use for k8s ingress."""
26+ max_body_size = self._stored.ingress_relation_data.get("max-body-size") or self.config["max-body-size"]
27+ return "{}m".format(max_body_size)
28+
29+ @property
30 def _namespace(self):
31 """Return the namespace to operate on."""
32 return (
33@@ -120,12 +134,9 @@ class CharmK8SIngressCharm(CharmBase):
34 )
35
36 @property
37- def _k8s_service_name(self):
38- """Return a service name for the use creating a k8s service."""
39- # Avoid collision with service name created by Juju. Currently
40- # Juju creates a K8s service listening on port 65535/TCP so we
41- # need to create a separate one.
42- return "{}-service".format(self._service_name)
43+ def _service_hostname(self):
44+ """Return the hostname for the service we're connecting to."""
45+ return self._stored.ingress_relation_data.get("service-hostname") or self.config["service-hostname"]
46
47 @property
48 def _service_name(self):
49@@ -139,6 +150,22 @@ class CharmK8SIngressCharm(CharmBase):
50 return int(self._stored.ingress_relation_data.get("service-port"))
51 return self.config["service-port"]
52
53+ @property
54+ def _session_cookie_max_age(self):
55+ """Return the session-cookie-max-age to use for k8s ingress."""
56+ session_cookie_max_age = (
57+ self._stored.ingress_relation_data.get("session-cookie-max-age") or self.config["session-cookie-max-age"]
58+ )
59+ if session_cookie_max_age:
60+ return str(session_cookie_max_age)
61+ # Don't return "0" which would evaluate to True.
62+ return ""
63+
64+ @property
65+ def _tls_secret_name(self):
66+ """Return the tls-secret-name to use for k8s ingress (if any)."""
67+ return self._stored.ingress_relation_data.get("tls-secret-name") or self.config["tls-secret-name"]
68+
69 def k8s_auth(self):
70 """Authenticate to kubernetes."""
71 if self._authed:
72@@ -179,7 +206,7 @@ class CharmK8SIngressCharm(CharmBase):
73 spec = kubernetes.client.NetworkingV1beta1IngressSpec(
74 rules=[
75 kubernetes.client.NetworkingV1beta1IngressRule(
76- host=self.config["service-hostname"],
77+ host=self._service_hostname,
78 http=kubernetes.client.NetworkingV1beta1HTTPIngressRuleValue(
79 paths=[
80 kubernetes.client.NetworkingV1beta1HTTPIngressPath(
81@@ -196,24 +223,21 @@ class CharmK8SIngressCharm(CharmBase):
82 )
83 annotations = {
84 "nginx.ingress.kubernetes.io/rewrite-target": "/",
85- "nginx.ingress.kubernetes.io/proxy-body-size": "{}m".format(self.config["max-body-size"]),
86+ "nginx.ingress.kubernetes.io/proxy-body-size": self._max_body_size,
87 }
88- if self.config["session-cookie-max-age"]:
89+ if self._session_cookie_max_age:
90 annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
91 annotations["nginx.ingress.kubernetes.io/affinity-mode"] = "balanced"
92 annotations["nginx.ingress.kubernetes.io/session-cookie-change-on-failure"] = "true"
93- annotations["nginx.ingress.kubernetes.io/session-cookie-max-age"] = "{}".format(
94- self.config["session-cookie-max-age"]
95- )
96+ annotations["nginx.ingress.kubernetes.io/session-cookie-max-age"] = self._session_cookie_max_age
97 annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "{}_AFFINITY".format(
98 self._service_name.upper()
99 )
100 annotations["nginx.ingress.kubernetes.io/session-cookie-samesite"] = "Lax"
101- tls_secret_name = self.config["tls-secret-name"]
102- if tls_secret_name:
103+ if self._tls_secret_name:
104 spec.tls = kubernetes.client.NetworkingV1beta1IngressTLS(
105- hosts=[self.config["service-hostname"]],
106- secret_name=tls_secret_name,
107+ hosts=[self._service_hostname],
108+ secret_name=self._tls_secret_name,
109 )
110 else:
111 annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = "false"
112diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py
113index 3efb784..1496048 100644
114--- a/tests/unit/test_charm.py
115+++ b/tests/unit/test_charm.py
116@@ -58,6 +58,16 @@ class TestCharm(unittest.TestCase):
117 # Confirm status is as expected.
118 self.assertEqual(self.harness.charm.unit.status, ActiveStatus())
119
120+ def test_max_body_size(self):
121+ """Test for the max-body-size property."""
122+ # First set via config.
123+ self.harness.update_config({"max-body-size": 80})
124+ self.assertEqual(self.harness.charm._max_body_size, "80m")
125+ # Now set via the StoredState. This will be set to a string, as all
126+ # relation data must be a string.
127+ self.harness.charm._stored.ingress_relation_data["max-body-size"] = "88"
128+ self.assertEqual(self.harness.charm._max_body_size, "88m")
129+
130 def test_namespace(self):
131 """Test for the namespace property."""
132 # If charm config and _stored is empty, use model name.
133@@ -81,6 +91,39 @@ class TestCharm(unittest.TestCase):
134 self.harness.charm._stored.ingress_relation_data["service-port"] = "88"
135 self.assertEqual(self.harness.charm._service_port, 88)
136
137+ def test_service_hostname(self):
138+ """Test the service-hostname property."""
139+ # First set via config.
140+ self.harness.update_config({"service-hostname": "foo.internal"})
141+ self.assertEqual(self.harness.charm._service_hostname, "foo.internal")
142+ # Now set via the StoredState. This will be set to a string, as all
143+ # relation data must be a string.
144+ self.harness.charm._stored.ingress_relation_data["service-hostname"] = "foo-bar.internal"
145+ self.assertEqual(self.harness.charm._service_hostname, "foo-bar.internal")
146+
147+ def test_session_cookie_max_age(self):
148+ """Test the session-cookie-max-age property."""
149+ # First set via config.
150+ self.harness.update_config({"session-cookie-max-age": 3600})
151+ self.assertEqual(self.harness.charm._session_cookie_max_age, "3600")
152+ # Confirm if we set this to 0 we get a False value, e.g. it doesn't
153+ # return a string of "0" which would be evaluated to True.
154+ self.harness.update_config({"session-cookie-max-age": 0})
155+ self.assertFalse(self.harness.charm._session_cookie_max_age)
156+ # Now set via the StoredState. This will be set to a string, as all
157+ # relation data must be a string.
158+ self.harness.charm._stored.ingress_relation_data["session-cookie-max-age"] = "3688"
159+ self.assertEqual(self.harness.charm._session_cookie_max_age, "3688")
160+
161+ def test_tls_secret_name(self):
162+ """Test the tls-secret-name property."""
163+ self.harness.update_config({"tls-secret-name": "gunicorn-tls"})
164+ self.assertEqual(self.harness.charm._tls_secret_name, "gunicorn-tls")
165+ # Now set via the StoredState. This will be set to a string, as all
166+ # relation data must be a string.
167+ self.harness.charm._stored.ingress_relation_data["tls-secret-name"] = "gunicorn-tls-new"
168+ self.assertEqual(self.harness.charm._tls_secret_name, "gunicorn-tls-new")
169+
170 @patch('charm.CharmK8SIngressCharm._on_config_changed')
171 def test_on_ingress_relation_changed(self, _on_config_changed):
172 """Test ingress relation changed handler."""
173@@ -139,7 +182,7 @@ class TestCharm(unittest.TestCase):
174 def test_get_k8s_ingress(self):
175 """Test getting our definition of a k8s ingress."""
176 self.harness.disable_hooks()
177- self.harness.update_config({"service-name": "gunicorn", "service-port": 80, "service-hostname": "foo.internal"})
178+ self.harness.update_config({"service-hostname": "foo.internal", "service-name": "gunicorn", "service-port": 80})
179 expected = kubernetes.client.NetworkingV1beta1Ingress(
180 api_version="networking.k8s.io/v1beta1",
181 kind="Ingress",

Subscribers

People subscribed via source and target branches

to all changes: