Merge ~adam-collard/maas:http-service-reload-traceback into maas:master

Proposed by Adam Collard
Status: Merged
Approved by: Adam Collard
Approved revision: 11b6d281103e7895b5f28e13ed597b954c4448ef
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~adam-collard/maas:http-service-reload-traceback
Merge into: maas:master
Diff against target: 193 lines (+45/-19)
2 files modified
src/maasserver/regiondservices/http.py (+10/-2)
src/maasserver/regiondservices/tests/test_http.py (+35/-17)
Reviewer Review Type Date Requested Status
Stamatis Katsaounis Approve
MAAS Lander Approve
Review via email: mp+458913@code.launchpad.net

Commit message

fix(regiondservices.http): still stopService if not listening

drive by refactor tests to only get cert in tests that use it.

get_sample_cert_with_cacerts is cached so no change in behaviour for
tests that need a cert. Tests that don't no longer have to pay the
one-time cost.

Description of the change

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b http-service-reload-traceback lp:~adam-collard/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 11b6d281103e7895b5f28e13ed597b954c4448ef

review: Approve
Revision history for this message
Stamatis Katsaounis (skatsaounis) wrote :

LGTM. This is also found in this system-tests run: http://maas-integration-ci.internal:8080/job/maas-system-tests-snap/1678/

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/regiondservices/http.py b/src/maasserver/regiondservices/http.py
2index c061193..e8dd55c 100644
3--- a/src/maasserver/regiondservices/http.py
4+++ b/src/maasserver/regiondservices/http.py
5@@ -3,6 +3,7 @@
6
7 """HTTP proxy service for the region controller."""
8
9+from contextlib import suppress
10 from dataclasses import dataclass
11 import os
12 from pathlib import Path
13@@ -12,7 +13,10 @@ from twisted.application.service import Service
14 from twisted.internet.defer import inlineCallbacks
15
16 from maasserver.certificates import get_maas_certificate
17-from maasserver.listener import PostgresListenerService
18+from maasserver.listener import (
19+ PostgresListenerService,
20+ PostgresListenerUnregistrationError,
21+)
22 from maasserver.models.config import Config
23 from maasserver.regiondservices import certificate_expiration_check
24 from maasserver.service_monitor import service_monitor
25@@ -56,7 +60,11 @@ class RegionHTTPService(Service):
26
27 def stopService(self):
28 if self.listener is not None:
29- self.listener.unregister("sys_reverse_proxy", self._consume_event)
30+ with suppress(PostgresListenerUnregistrationError):
31+ self.listener.unregister(
32+ "sys_reverse_proxy", self._consume_event
33+ )
34+
35 return super().stopService()
36
37 @staticmethod
38diff --git a/src/maasserver/regiondservices/tests/test_http.py b/src/maasserver/regiondservices/tests/test_http.py
39index 04ce1ce..d9b5669 100644
40--- a/src/maasserver/regiondservices/tests/test_http.py
41+++ b/src/maasserver/regiondservices/tests/test_http.py
42@@ -8,7 +8,7 @@ from unittest.mock import Mock
43 from fixtures import EnvironmentVariable
44 from twisted.internet.defer import inlineCallbacks
45
46-from maasserver.listener import notify
47+from maasserver.listener import notify, PostgresListenerUnregistrationError
48 from maasserver.models import Config
49 from maasserver.regiondservices import certificate_expiration_check, http
50 from maasserver.secrets import SecretManager
51@@ -27,19 +27,17 @@ wait_for_reactor = wait_for()
52 class TestRegionHTTPService(
53 TransactionalHelpersMixin, MAASTransactionServerTestCase
54 ):
55- def setUp(self):
56- super().setUp()
57- self.cert = get_sample_cert_with_cacerts()
58-
59 def create_tls_config(self):
60+ cert = get_sample_cert_with_cacerts()
61+
62 def _create_config_in_db():
63 Config.objects.set_config("tls_port", 5443)
64 SecretManager().set_composite_secret(
65 "tls",
66 {
67- "key": self.cert.private_key_pem(),
68- "cert": self.cert.certificate_pem(),
69- "cacert": self.cert.ca_certificates_pem(),
70+ "key": cert.private_key_pem(),
71+ "cert": cert.certificate_pem(),
72+ "cacert": cert.ca_certificates_pem(),
73 },
74 )
75 # manually send a notification to emulate what TLS config does
76@@ -86,6 +84,7 @@ class TestRegionHTTPService(
77 mock_cert_check.assert_called_once_with()
78
79 def test_configure_not_snap(self):
80+ cert = get_sample_cert_with_cacerts()
81 # MAASDataFixture updates `MAAS_DATA` in the environment to point to this new location.
82 data_path = os.getenv("MAAS_DATA")
83 boot_resources_dir = f"{data_path}/boot-resources"
84@@ -101,7 +100,7 @@ class TestRegionHTTPService(
85 mock_create_cert_files = self.patch(service, "_create_cert_files")
86 mock_create_cert_files.return_value = ("key_path", "cert_path")
87
88- service._configure(http._Configuration(self.cert, port=5443))
89+ service._configure(http._Configuration(cert, port=5443))
90
91 nginx_config = nginx_conf.read_text()
92
93@@ -118,6 +117,7 @@ class TestRegionHTTPService(
94 self.assertIn(f"root {boot_resources_dir};", nginx_config)
95
96 def test_configure_in_snap(self):
97+ cert = get_sample_cert_with_cacerts()
98 self.patch(
99 os,
100 "environ",
101@@ -141,7 +141,7 @@ class TestRegionHTTPService(
102 mock_create_cert_files = self.patch(service, "_create_cert_files")
103 mock_create_cert_files.return_value = ("key_path", "cert_path")
104
105- service._configure(http._Configuration(cert=self.cert, port=5443))
106+ service._configure(http._Configuration(cert=cert, port=5443))
107
108 nginx_config = nginx_conf.read_text()
109 worker_ids = WorkersService.get_worker_ids()
110@@ -159,6 +159,7 @@ class TestRegionHTTPService(
111 self.assertIn(f"root {boot_resources_dir};", nginx_config)
112
113 def test_configure_https_also_has_http_server(self):
114+ cert = get_sample_cert_with_cacerts()
115 tempdir = self.make_dir()
116 nginx_conf = Path(tempdir) / "regiond.nginx.conf"
117 service = http.RegionHTTPService()
118@@ -169,7 +170,7 @@ class TestRegionHTTPService(
119 mock_create_cert_files = self.patch(service, "_create_cert_files")
120 mock_create_cert_files.return_value = ("key_path", "cert_path")
121
122- service._configure(http._Configuration(cert=self.cert, port=5443))
123+ service._configure(http._Configuration(cert=cert, port=5443))
124
125 nginx_config = nginx_conf.read_text()
126 self.assertIn("listen 5443 ssl http2;", nginx_config)
127@@ -177,20 +178,21 @@ class TestRegionHTTPService(
128 self.assertIn("location /MAAS/api/2.0/machines {", nginx_config)
129
130 def test_create_cert_files_writes_full_chain(self):
131+ cert = get_sample_cert_with_cacerts()
132 tempdir = Path(self.make_dir())
133 certs_dir = tempdir / "certs"
134 certs_dir.mkdir()
135 self.patch(http, "get_http_config_dir").return_value = tempdir
136
137 service = http.RegionHTTPService()
138- service._create_cert_files(self.cert)
139+ service._create_cert_files(cert)
140 self.assertEqual(
141 (certs_dir / "regiond-proxy.pem").read_text(),
142- self.cert.fullchain_pem(),
143+ cert.fullchain_pem(),
144 )
145 self.assertEqual(
146 (certs_dir / "regiond-proxy-key.pem").read_text(),
147- self.cert.private_key_pem(),
148+ cert.private_key_pem(),
149 )
150
151 @wait_for_reactor
152@@ -213,6 +215,21 @@ class TestRegionHTTPService(
153
154 @wait_for_reactor
155 @inlineCallbacks
156+ def test_unregisters_listener_without_registering(self):
157+ listener = Mock()
158+ listener.unregister.side_effect = PostgresListenerUnregistrationError(
159+ "Channel foo not found"
160+ )
161+ mock_super_stop = self.patch_autospec(http.Service, "stopService")
162+ service = http.RegionHTTPService(postgresListener=listener)
163+ yield service.stopService()
164+ listener.unregister.assert_called_once_with(
165+ "sys_reverse_proxy", service._consume_event
166+ )
167+ mock_super_stop.assert_called_once_with(service)
168+
169+ @wait_for_reactor
170+ @inlineCallbacks
171 def test_handler_is_called_on_config_change(self):
172 listener = self.make_listener_without_delay()
173 capture = []
174@@ -232,6 +249,7 @@ class TestRegionHTTPService(
175 @wait_for_reactor
176 @inlineCallbacks
177 def test_data_is_consistent_when_notified(self):
178+ cert = get_sample_cert_with_cacerts()
179 listener = self.make_listener_without_delay()
180 capture = []
181
182@@ -257,8 +275,8 @@ class TestRegionHTTPService(
183 self.assertEqual(
184 tls_secrets,
185 {
186- "key": self.cert.private_key_pem(),
187- "cert": self.cert.certificate_pem(),
188- "cacert": self.cert.ca_certificates_pem(),
189+ "key": cert.private_key_pem(),
190+ "cert": cert.certificate_pem(),
191+ "cacert": cert.ca_certificates_pem(),
192 },
193 )

Subscribers

People subscribed via source and target branches