From 93966becedf5f19022ab203b7a5aa40c21b21754 Mon Sep 17 00:00:00 2001 From: Marcel Clausen Date: Fri, 8 May 2026 14:21:31 +0200 Subject: [PATCH 1/2] disable preview mode on prod --- app/helpers/wmts.py | 4 ++- tests/unit_tests/test_get_tile.py | 43 +++++++++++++++++-------------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/app/helpers/wmts.py b/app/helpers/wmts.py index dc15297..c24fdc0 100644 --- a/app/helpers/wmts.py +++ b/app/helpers/wmts.py @@ -53,7 +53,9 @@ def prepare_wmts_cached_response(s3_resp): def validate_wmts_mode(): mode = request.args.get('mode', settings.DEFAULT_MODE) - supported_modes = ('default', 'preview') + supported_modes = ('default',) if settings.APP_STAGING == 'prod' else ( + 'default', 'preview' + ) if mode not in supported_modes: msg = 'Unsupported mode: %s. Only "%s" are supported.' logger.error(msg, mode, ", ".join(supported_modes)) diff --git a/tests/unit_tests/test_get_tile.py b/tests/unit_tests/test_get_tile.py index a59f972..c6985e8 100644 --- a/tests/unit_tests/test_get_tile.py +++ b/tests/unit_tests/test_get_tile.py @@ -261,10 +261,11 @@ def test_wmts_out_of_bounds(self, mock_get_s3_file): def test_wmts_4326_unsupported_zoom(self, mock_get_s3_file): mock_get_s3_file.return_value = self.mock_get_s3_file_conn_nok - resp = self.app.get( - '1.0.0/inline_points/default/current/4326/18/273577/63352.png' - '?mode=preview' - ) + with patch.object(settings, 'APP_STAGING', 'test'): + resp = self.app.get( + '1.0.0/inline_points/default/current/4326/18/273577/63352.png' + '?mode=preview' + ) self.assertEqual(resp.status_code, 400) self.assertCacheControl(resp) @@ -296,10 +297,11 @@ def test_wmts_png_preview_gutter(self, mock_wms, mock_get_s3_file): mock_get_s3_file.return_value = self.mock_get_s3_file_conn_ok self.get_wms_request_mock(mock_wms) - resp = self.app.get( - '/1.0.0/inline_points/' + - 'default/current/21781/20/76/44.png?mode=preview' - ) + with patch.object(settings, 'APP_STAGING', 'test'): + resp = self.app.get( + '/1.0.0/inline_points/' + + 'default/current/21781/20/76/44.png?mode=preview' + ) self.assertEqual(resp.status_code, 200) self.assertEqual( resp.headers['Cache-Control'], @@ -477,10 +479,11 @@ def handle_2nd_level_cache_wrapper(*args, **kwargs): 'app.helpers.wmts.handle_2nd_level_cache', wraps=handle_2nd_level_cache_wrapper ) as mock_handle_2nd_level_cache: - resp = self.app.get( - '/1.0.0/inline_points/default/current/21781/20/76/44.png' - '?mode=preview' - ) + with patch.object(settings, 'APP_STAGING', 'test'): + resp = self.app.get( + '/1.0.0/inline_points/default/current/21781/20/76/44.png' + '?mode=preview' + ) self.assertEqual(resp.status_code, 200) mock_handle_2nd_level_cache.assert_called() self.assertEqual( @@ -507,9 +510,10 @@ def test_wmts_cadastral_wms_proxy_from_s3_cache_preview( ): mock_get_s3_file.return_value = self.mock_get_s3_file_conn_ok - resp = self.app.get( - '1.0.0/inline_points/default/current/2056/17/4/7.png?mode=preview' - ) + with patch.object(settings, 'APP_STAGING', 'test'): + resp = self.app.get( + '1.0.0/inline_points/default/current/2056/17/4/7.png?mode=preview' + ) self.assertEqual(resp.status_code, 200) self.assert2ndCacheHeader(resp, False) @@ -584,9 +588,10 @@ def test_wmts_bad_content_type(self, mock_get_s3_file, mocker): headers={'Content-Type': 'text/xml; charset=UTF-8'} ) - resp = self.app.get( - '/1.0.0/inline_points/' + - 'default/current/21781/20/76/44.png?mode=preview' - ) + with patch.object(settings, 'APP_STAGING', 'test'): + resp = self.app.get( + '/1.0.0/inline_points/' + + 'default/current/21781/20/76/44.png?mode=preview' + ) self.assertEqual(resp.status_code, 501) self.assertEqual(resp.headers['Cache-Control'], 'public, max-age=5') From eba0d0fcb1e10bdacdc78d32b16ba2515bd466ff Mon Sep 17 00:00:00 2001 From: Marcel Clausen Date: Wed, 17 Jun 2026 09:40:39 +0200 Subject: [PATCH 2/2] PB-2315: fix readiness check The WMS backend now returns the MapServer message wrapped in HTML, causing the exact-string equality check to fail and WMTS pods to remain unready. Replace the equality check against `wms_ok_string` with a substring search for the marker without trailing newline, and decode with `errors='replace'` to avoid failures on unexpected bytes. Add unit tests for the ready (mocked happy path) and missing-marker (503) cases. --- app/routes.py | 10 ++++++---- tests/unit_tests/test_checker.py | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/app/routes.py b/app/routes.py index e90b0df..52f6173 100644 --- a/app/routes.py +++ b/app/routes.py @@ -71,17 +71,19 @@ def liveness(): @app.route('/checker/ready', methods=['GET']) def readiness(): - wms_ok_string = 'No query information to decode. ' + \ - 'QUERY_STRING is set, but empty.\n' + wms_ok_marker = ( + 'No query information to decode. QUERY_STRING is set, but empty.' + ) content = get_wms_backend_readiness() - if content.decode('ascii') != wms_ok_string: + content_str = content.decode('ascii', errors='replace') + if wms_ok_marker not in content_str: logger.error( 'Incomprehensible WMS backend %s answer: %s. ' 'WMS is probably not ready yet.', settings.WMS_BACKEND_READY, - content.decode('ascii') + content_str ) abort(503, 'Incomprehensible answer. WMS is probably not ready yet.') return make_response(jsonify({'success': True, 'message': 'OK'})) diff --git a/tests/unit_tests/test_checker.py b/tests/unit_tests/test_checker.py index 9782ca2..c56acb2 100644 --- a/tests/unit_tests/test_checker.py +++ b/tests/unit_tests/test_checker.py @@ -39,3 +39,20 @@ def test_backend_checker_down(self, mock_get_backend): resp = self.app.get('/checker/ready') mock_get_backend.assert_called_once() self.assertEqual(resp.status_code, 502) + + @patch('app.routes.get_wms_backend_readiness') + def test_backend_checker_ready(self, mock_readiness): + mock_readiness.return_value = ( + b'No query information to decode. QUERY_STRING is set, but empty.' + ) + resp = self.app.get('/checker/ready') + self.assertEqual(resp.status_code, 200) + self.assertEqual(resp.json, {'success': True, 'message': 'OK'}) + + @patch('app.routes.get_wms_backend_readiness') + def test_backend_checker_missing_marker(self, mock_readiness): + mock_readiness.return_value = ( + b'Apache is up but MapServer is not.' + ) + resp = self.app.get('/checker/ready') + self.assertEqual(resp.status_code, 503)