Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

abort Hub when reflector ultimately fails #86

Merged
merged 1 commit into from Oct 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 10 additions & 5 deletions kubespawner/reflector.py
Expand Up @@ -2,9 +2,9 @@
import threading

from traitlets.config import SingletonConfigurable
from traitlets import Dict, Unicode
from traitlets import Any, Dict, Unicode
from kubernetes import client, config, watch

from tornado.ioloop import IOLoop

class PodReflector(SingletonConfigurable):
"""
Expand Down Expand Up @@ -38,6 +38,8 @@ class PodReflector(SingletonConfigurable):
"""
)

on_failure = Any(help="""Function to be called when the reflector gives up.""")

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Load kubernetes config here, since this is a Singleton and
Expand Down Expand Up @@ -108,12 +110,15 @@ def _watch_and_update(self):
else:
# This is an atomic operation on the dictionary!
self.pods[pod.metadata.name] = pod
except:
except Exception:
cur_delay = cur_delay * 2
if cur_delay > 30:
self.log.exception("Watching pods never recovered, giving up")
if self.on_failure:
self.on_failure()
return
self.log.exception("Error when watching pods, retrying in %ss", cur_delay)
time.sleep(cur_delay)
if cur_delay > 30:
raise
continue
finally:
w.stop()
Expand Down
9 changes: 8 additions & 1 deletion kubespawner/spawner.py
Expand Up @@ -16,6 +16,7 @@


from tornado import gen
from tornado.ioloop import IOLoop
from tornado.concurrent import run_on_executor
from traitlets.config import SingletonConfigurable
from traitlets import Type, Unicode, List, Integer, Union, Dict, Bool, Any
Expand Down Expand Up @@ -50,9 +51,15 @@ def __init__(self, *args, **kwargs):
# other attributes
self.executor = SingletonExecutor.instance(max_workers=self.k8s_api_threadpool_workers)

main_loop = IOLoop.current()
def on_reflector_failure():
self.log.critical("Pod reflector failed, halting Hub.")
main_loop.stop()

# This will start watching in __init__, so it'll start the first
# time any spawner object is created. Not ideal but works!
self.pod_reflector = PodReflector.instance(parent=self, namespace=self.namespace)
self.pod_reflector = PodReflector.instance(parent=self, namespace=self.namespace,
on_failure=on_reflector_failure)

self.api = client.CoreV1Api()

Expand Down