|
4 | 4 | import subprocess
|
5 | 5 | import warnings
|
6 | 6 | from io import StringIO
|
| 7 | +from pathlib import Path |
7 | 8 | from pwd import getpwnam
|
8 | 9 |
|
9 | 10 | from django.apps import AppConfig
|
@@ -88,10 +89,9 @@ def version_check(app_configs, **kwargs):
|
88 | 89 | def static_check(app_configs, **kwargs):
|
89 | 90 | errors = []
|
90 | 91 | output = StringIO()
|
91 |
| - version = get_version_json() |
92 | 92 |
|
93 | 93 | # We only run this check in production images.
|
94 |
| - if version.get('target') != 'production': |
| 94 | + if settings.TARGET != 'production': |
95 | 95 | return []
|
96 | 96 |
|
97 | 97 | try:
|
@@ -188,54 +188,88 @@ def db_charset_check(app_configs, **kwargs):
|
188 | 188 | @register(CustomTags.custom_setup)
|
189 | 189 | def nginx_check(app_configs, **kwargs):
|
190 | 190 | errors = []
|
191 |
| - version = get_version_json() |
192 | 191 |
|
193 |
| - if version.get('target') == 'production': |
| 192 | + # We only run this check in local environments |
| 193 | + # Becuase that is the only environment where the local |
| 194 | + # nginx server is routing requests. |
| 195 | + if settings.ENV != 'local': |
194 | 196 | return []
|
195 | 197 |
|
196 |
| - configs = [ |
197 |
| - (settings.MEDIA_ROOT, 'http://nginx/user-media'), |
198 |
| - (settings.STATIC_FILES_PATH, 'http://nginx/static'), |
199 |
| - (settings.STATIC_ROOT, 'http://nginx/static'), |
| 198 | + is_production = settings.TARGET == 'production' |
| 199 | + |
| 200 | + nginx_routing_configs = [ |
| 201 | + { |
| 202 | + 'document_root': settings.MEDIA_ROOT, |
| 203 | + 'url_prefix': 'user-media', |
| 204 | + # MEDIA_ROOT is available over nginx in all local environments. |
| 205 | + 'served_by': 'nginx', |
| 206 | + }, |
| 207 | + { |
| 208 | + 'document_root': settings.STATIC_ROOT, |
| 209 | + 'url_prefix': 'static', |
| 210 | + # STATIC_ROOT is only available over nginx in production images |
| 211 | + # where we expect collectstatic to have copied files to it. |
| 212 | + 'served_by': 'nginx' if is_production else None, |
| 213 | + }, |
| 214 | + { |
| 215 | + 'document_root': settings.STATIC_FILES_PATH, |
| 216 | + 'url_prefix': 'static', |
| 217 | + # STATIC_FILES_PATH is available via olympia static server |
| 218 | + # in non production images. |
| 219 | + 'served_by': None if is_production else 'olympia', |
| 220 | + }, |
200 | 221 | ]
|
201 | 222 |
|
202 |
| - files_to_remove = [] |
203 |
| - |
204 |
| - for dir, base_url in configs: |
205 |
| - file_path = os.path.join(dir, 'test.txt') |
206 |
| - file_url = f'{base_url}/test.txt' |
207 |
| - |
208 |
| - if not os.path.exists(dir): |
209 |
| - errors.append(Error(f'{dir} does not exist', id='setup.E007')) |
210 |
| - |
211 |
| - try: |
212 |
| - with open(file_path, 'w') as f: |
213 |
| - f.write(dir) |
214 |
| - |
215 |
| - files_to_remove.append(file_path) |
216 |
| - response = requests.get(file_url) |
| 223 | + def process_request(config, path): |
| 224 | + url = f'http://nginx/{config["url_prefix"]}/{path}' |
| 225 | + response = requests.get(url) |
217 | 226 |
|
218 |
| - expected_config = ( |
219 |
| - (response.status_code, 200), |
220 |
| - (response.text, dir), |
221 |
| - (response.headers.get('X-Served-By'), 'nginx'), |
222 |
| - ) |
| 227 | + expected_served_by = config['served_by'] |
| 228 | + document_root = config['document_root'] |
223 | 229 |
|
224 |
| - if any(item[0] != item[1] for item in expected_config): |
225 |
| - message = f'Failed to access {file_url}. {expected_config}' |
226 |
| - errors.append(Error(message, id='setup.E008')) |
| 230 | + expected_status_code = 404 if expected_served_by is None else 200 |
227 | 231 |
|
228 |
| - except Exception as e: |
| 232 | + if response.status_code != expected_status_code: |
229 | 233 | errors.append(
|
230 | 234 | Error(
|
231 |
| - f'Unknown error accessing {file_path} via {file_url}: {e}', |
232 |
| - id='setup.E010', |
| 235 | + ( |
| 236 | + f'Expected {url} serving file from {document_root} ' |
| 237 | + f'to respond with code {expected_status_code}, ' |
| 238 | + f'received {response.status_code}' |
| 239 | + ), |
| 240 | + id='setup.E007', |
233 | 241 | )
|
234 | 242 | )
|
| 243 | + elif expected_served_by is not None: |
| 244 | + actual_served_by = response.headers.get('X-Served-By') |
| 245 | + if actual_served_by != expected_served_by: |
| 246 | + errors.append( |
| 247 | + Error( |
| 248 | + ( |
| 249 | + f'Expected {url} serving file from {document_root} ' |
| 250 | + f'to be served by {expected_served_by}, ' |
| 251 | + f'received {actual_served_by}' |
| 252 | + ), |
| 253 | + id='setup.E007', |
| 254 | + ) |
| 255 | + ) |
| 256 | + |
| 257 | + for config in nginx_routing_configs: |
| 258 | + document_root = config['document_root'] |
| 259 | + file_name = 'test.txt' |
| 260 | + file_path = Path(document_root) / file_name |
235 | 261 |
|
236 |
| - # Always remove the files we created. |
237 |
| - for file_path in files_to_remove: |
238 |
| - os.remove(file_path) |
| 262 | + try: |
| 263 | + # First expect the request to fail while the path does not exist |
| 264 | + process_request(config, file_name) |
| 265 | + # Then create the file and expect the request to succeed |
| 266 | + with open(file_path, 'w') as f: |
| 267 | + f.write('test') |
| 268 | + process_request(config, file_name) |
| 269 | + except FileNotFoundError: |
| 270 | + errors.append(Error(f'{document_root} does not exist', id='setup.E007')) |
| 271 | + finally: |
| 272 | + file_path.unlink(missing_ok=True) |
239 | 273 |
|
240 | 274 | return errors
|
241 | 275 |
|
|
0 commit comments