Skip to content

Commit 242e40b

Browse files
committed
Resolve conflicts with main
2 parents 11d3157 + 79c6ef0 commit 242e40b

File tree

7 files changed

+108
-177
lines changed

7 files changed

+108
-177
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ repos:
4242

4343
# Autoformat: markdown, yaml
4444
- repo: https://github.com/pre-commit/mirrors-prettier
45-
rev: v3.0.0-alpha.4
45+
rev: v3.0.0-alpha.6
4646
hooks:
4747
- id: prettier
4848

jupyterhub_traefik_proxy/consul.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,6 @@ def _start_traefik(self):
118118
self.traefik_env.setdefault("CONSUL_HTTP_TOKEN", self.consul_password)
119119
super()._start_traefik()
120120

121-
def _stop_traefik(self):
122-
super()._stop_traefik()
123-
124121
async def persist_dynamic_config(self):
125122
data = self.flatten_dict_for_kv(
126123
self.dynamic_config, prefix=self.kv_traefik_prefix
@@ -307,6 +304,3 @@ async def _kv_get_jupyterhub_prefixed_entries(self):
307304
)
308305

309306
return routes["Results"]
310-
311-
async def stop(self):
312-
await super().stop()

jupyterhub_traefik_proxy/etcd.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ def _default_client(self):
137137
)
138138
return etcd3.client(**kwargs)
139139

140-
def _clean_resources(self):
141-
super()._clean_resources()
140+
def _cleanup(self):
141+
super()._cleanup()
142142
self.etcd.close()
143143

144144
@run_on_executor

jupyterhub_traefik_proxy/fileprovider.py

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,14 @@ def _load_dynamic_config(self):
6666
except FileNotFoundError:
6767
dynamic_config = {}
6868

69-
if not dynamic_config:
70-
dynamic_config = {
71-
"http": {"services": {}, "routers": {}},
72-
"jupyter": {"routers": {}},
73-
}
69+
# fill in default keys
70+
# use setdefault to ensure these are always fully defined
71+
# and never _partially_ defined
72+
http = dynamic_config.setdefault("http", {})
73+
http.setdefault("services", {})
74+
http.setdefault("routers", {})
75+
jupyter = dynamic_config.setdefault("jupyter", {})
76+
jupyter.setdefault("routers", {})
7477
return dynamic_config
7578

7679
def persist_dynamic_config(self):
@@ -90,14 +93,15 @@ async def _setup_traefik_static_config(self):
9093
}
9194
await super()._setup_traefik_static_config()
9295

93-
def _clean_resources(self):
96+
def _cleanup(self):
97+
"""Cleanup dynamic config file as well"""
98+
super()._cleanup()
9499
try:
95-
if self.should_start:
96-
os.remove(self.static_config_file)
97100
os.remove(self.dynamic_config_file)
98-
except:
99-
self.log.error("Failed to remove traefik's configuration files")
100-
raise
101+
except Exception as e:
102+
self.log.error(
103+
f"Failed to remove traefik configuration file {self.dynamic_config_file}: {e}"
104+
)
101105

102106
def _get_route_unsafe(self, traefik_routespec):
103107
service_alias = traefik_utils.generate_alias(traefik_routespec, "service")
@@ -117,32 +121,10 @@ def _get_route_unsafe(self, traefik_routespec):
117121
result["data"] = jupyter_routers["data"]
118122

119123
if result["data"] is None and result["target"] is None:
120-
self.log.info(f"No route for {routespec} found!")
124+
self.log.warning(f"No route for {routespec} found!")
121125
result = None
122126
return result
123127

124-
async def start(self):
125-
"""Start the proxy.
126-
127-
Will be called during startup if should_start is True.
128-
129-
**Subclasses must define this method**
130-
if the proxy is to be started by the Hub
131-
"""
132-
await super().start()
133-
await self._wait_for_static_config()
134-
135-
async def stop(self):
136-
"""Stop the proxy.
137-
138-
Will be called during teardown if should_start is True.
139-
140-
**Subclasses must define this method**
141-
if the proxy is to be started by the Hub
142-
"""
143-
await super().stop()
144-
self._clean_resources()
145-
146128
async def add_route(self, routespec, target, data):
147129
"""Add a route to the proxy.
148130

jupyterhub_traefik_proxy/kv_proxy.py

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
import asyncio
2222
import json
23-
import os
2423
from collections.abc import MutableMapping
2524
from functools import wraps
2625

@@ -205,14 +204,6 @@ async def _kv_get_jupyterhub_prefixed_entries(self):
205204

206205
raise NotImplementedError()
207206

208-
def _clean_resources(self):
209-
try:
210-
if self.should_start:
211-
os.remove(self.static_config_file)
212-
except:
213-
self.log.error("Failed to remove traefik's configuration files")
214-
raise
215-
216207
async def _setup_traefik_static_config(self):
217208
self._define_kv_specific_static_config()
218209
await super()._setup_traefik_static_config()
@@ -221,20 +212,6 @@ async def _setup_traefik_dynamic_config(self):
221212
await super()._setup_traefik_dynamic_config()
222213
await self.persist_dynamic_config()
223214

224-
async def start(self):
225-
"""Start the proxy.
226-
Will be called during startup if should_start is True.
227-
"""
228-
await super().start()
229-
await self._wait_for_static_config()
230-
231-
async def stop(self):
232-
"""Stop the proxy.
233-
Will be called during teardown if should_start is True.
234-
"""
235-
await super().stop()
236-
self._clean_resources()
237-
238215
async def add_route(self, routespec, target, data):
239216
"""Add a route to the proxy.
240217
@@ -275,10 +252,10 @@ async def add_route(self, routespec, target, data):
275252
)
276253

277254
if status:
278-
self.log.info(
255+
self.log.debug(
279256
"Added service %s with the alias %s.", target, route_keys.service_alias
280257
)
281-
self.log.info(
258+
self.log.debug(
282259
"Added router %s for service %s with the following routing rule %s.",
283260
route_keys.router_alias,
284261
route_keys.service_alias,
@@ -309,7 +286,7 @@ async def delete_route(self, routespec):
309286
jupyterhub_routespec, route_keys
310287
)
311288
if status:
312-
self.log.info("Routespec %s was deleted.", routespec)
289+
self.log.debug("Routespec %s was deleted.", routespec)
313290
else:
314291
self.log.error(
315292
"Couldn't delete route %s. Response: %s", routespec, response

jupyterhub_traefik_proxy/proxy.py

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ async def _check_for_traefik_service(self, routespec, kind):
288288
return True
289289

290290
async def _wait_for_route(self, routespec):
291-
self.log.info(f"Waiting for {routespec} to register with traefik")
291+
self.log.debug("Waiting for %s to register with traefik", routespec)
292292

293293
async def _check_traefik_dynamic_conf_ready():
294294
"""Check if traefik loaded its dynamic configuration yet"""
@@ -326,17 +326,26 @@ async def _wait_for_static_config(self):
326326
async def _check_traefik_static_conf_ready():
327327
"""Check if traefik loaded its static configuration yet"""
328328
try:
329-
resp = await self._traefik_api_request("/api/overview")
330-
except Exception:
331-
self.log.exception("Error checking for traefik static configuration")
332-
return False
333-
334-
if resp.code != 200:
335-
self.log.error(
336-
"Unexpected response code %s checking for traefik static configuration",
337-
resp.code,
329+
await self._traefik_api_request("/api/overview")
330+
except ConnectionRefusedError:
331+
self.log.debug(
332+
f"Connection Refused waiting for traefik at {self.traefik_api_url}. It's probably starting up..."
338333
)
339334
return False
335+
except HTTPClientError as e:
336+
if e.code == 599:
337+
self.log.debug(
338+
f"Connection error waiting for traefik at {self.traefik_api_url}. It's probably starting up..."
339+
)
340+
return False
341+
if e.code == 404:
342+
self.log.debug(
343+
f"traefik api at {e.response.request.url} overview not ready yet"
344+
)
345+
return False
346+
# unexpected
347+
self.log.error(f"Error checking for traefik static configuration {e}")
348+
return False
340349

341350
return True
342351

@@ -347,7 +356,7 @@ async def _check_traefik_static_conf_ready():
347356
)
348357

349358
def _stop_traefik(self):
350-
self.log.info("Cleaning up proxy[%i]...", self.traefik_process.pid)
359+
self.log.info("Cleaning up traefik proxy [pid=%i]...", self.traefik_process.pid)
351360
self.traefik_process.terminate()
352361
try:
353362
self.traefik_process.communicate(timeout=10)
@@ -363,6 +372,7 @@ def _start_traefik(self):
363372
"Configuration mode not supported \n.\
364373
The proxy can only be configured through fileprovider, etcd and consul"
365374
)
375+
366376
env = os.environ.copy()
367377
env.update(self.traefik_env)
368378
try:
@@ -419,7 +429,7 @@ async def _setup_traefik_static_config(self):
419429
raise
420430

421431
async def _setup_traefik_dynamic_config(self):
422-
self.log.info("Setting up traefik's dynamic config...")
432+
self.log.debug("Setting up traefik's dynamic config...")
423433
self._generate_htpassword()
424434
api_url = urlparse(self.traefik_api_url)
425435
api_path = api_url.path if api_url.path else '/api'
@@ -478,6 +488,7 @@ async def start(self):
478488
await self._setup_traefik_static_config()
479489
await self._setup_traefik_dynamic_config()
480490
self._start_traefik()
491+
await self._wait_for_static_config()
481492

482493
async def stop(self):
483494
"""Stop the proxy.
@@ -488,6 +499,20 @@ async def stop(self):
488499
if the proxy is to be started by the Hub
489500
"""
490501
self._stop_traefik()
502+
self._cleanup()
503+
504+
def _cleanup(self):
505+
"""Cleanup after stop
506+
507+
Extend if there's more to cleanup than the static config file
508+
"""
509+
if self.should_start:
510+
try:
511+
os.remove(self.static_config_file)
512+
except Exception as e:
513+
self.log.error(
514+
f"Failed to remove traefik config file {self.static_config_file}: {e}"
515+
)
491516

492517
async def add_route(self, routespec, target, data):
493518
"""Add a route to the proxy.

0 commit comments

Comments
 (0)