Skip to content

Commit e27f63f

Browse files
authored
Merge pull request #1521 from manics/build-traitlets-2
Breaking: Default to traitlets based Build class
2 parents 7a558f0 + 13015f8 commit e27f63f

File tree

11 files changed

+163
-191
lines changed

11 files changed

+163
-191
lines changed

CHANGES.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,28 @@ If you were previously disabling the image cleaner replace:
3333

3434
- `imageCleaner.host.enabled: false` ➡️ `imageCleaner.enabled: false`
3535

36+
### `binderhub.build.Build` class replaced by `binderhub.build.KubernetesBuildExecutor`
37+
38+
The `binderhub.build.Build` class is replaced by the Traitlets based `binderhub.build.KubernetesBuildExecutor` class
39+
[#1518](https://github.com/jupyterhub/binderhub/pull/1518),
40+
[#1521](https://github.com/jupyterhub/binderhub/pull/1521).
41+
42+
The following build configuration properties should be set using Traitlets in the BinderHub configuration:
43+
44+
- `c.BinderHub.appendix` ➡️ `c.BuildExecutor.appendix`
45+
- `c.BinderHub.sticky_builds` ➡️ `c.KubernetesBuildExecutor.sticky_builds`
46+
- `c.BinderHub.log_tail_lines` ➡️ `c.KubernetesBuildExecutor.log_tail_lines`
47+
- `c.BinderHub.push_secret` ➡️ `c.BuildExecutor.push_secret`
48+
- `c.BinderHub.build_memory_request` ➡️ `c.KubernetesBuildExecutor.memory_request`
49+
- `c.BinderHub.build_memory_limit` ➡️ `c.BuildExecutor.memory_limit`
50+
- `c.BinderHub.build_docker_host` ➡️ `c.KubernetesBuildExecutor.docker_host`
51+
- `c.BinderHub.build_namespace` ➡️ `c.KubernetesBuildExecutor.namespace`
52+
- `c.BinderHub.build_image` ➡️ `c.KubernetesBuildExecutor.build_image`
53+
- `c.BinderHub.build_node_selector` ➡️ `c.KubernetesBuildExecutor.node_selector`
54+
55+
If you have subclassed `binderhub.build.Build` you must update your subclass (including `__init__()` if defined) to inherit from `binderhub.build.KubernetesBuildExecutor`.
56+
The behaviour of the class is otherwise unchanged.
57+
3658
# 0.2.0
3759

3860
# master@{2019-07-01}...master@{2019-10-01}

binderhub/app.py

Lines changed: 69 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import os
99
import re
1010
import secrets
11+
import warnings
1112
from binascii import a2b_hex
1213
from concurrent.futures import ThreadPoolExecutor
1314
from glob import glob
@@ -41,7 +42,7 @@
4142
from traitlets.config import Application
4243

4344
from .base import AboutHandler, Custom404, VersionHandler
44-
from .build import Build, BuildExecutor, KubernetesBuildExecutor
45+
from .build import BuildExecutor, KubernetesBuildExecutor, KubernetesCleaner
4546
from .builder import BuildHandler
4647
from .config import ConfigHandler
4748
from .events import EventLog
@@ -229,6 +230,8 @@ def _valid_badge_base_url(self, proposal):
229230

230231
appendix = Unicode(
231232
help="""
233+
DEPRECATED: Use c.BuildExecutor.appendix
234+
232235
Appendix to pass to repo2docker
233236
234237
A multi-line string of Docker directives to run.
@@ -248,6 +251,8 @@ def _valid_badge_base_url(self, proposal):
248251
sticky_builds = Bool(
249252
False,
250253
help="""
254+
DEPRECATED: Use c.KubernetesBuildExecutor.sticky_builds
255+
251256
Attempt to assign builds for the same repository to the same node.
252257
253258
In order to speed up re-builds of a repository all its builds will
@@ -270,7 +275,7 @@ def _valid_badge_base_url(self, proposal):
270275
)
271276

272277
build_class = Type(
273-
Build,
278+
KubernetesBuildExecutor,
274279
klass=BuildExecutor,
275280
help="""
276281
The class used to build repo2docker images.
@@ -280,6 +285,15 @@ def _valid_badge_base_url(self, proposal):
280285
config=True,
281286
)
282287

288+
build_cleaner_class = Type(
289+
KubernetesCleaner,
290+
allow_none=True,
291+
help="""
292+
The class used to cleanup builders.
293+
""",
294+
config=True,
295+
)
296+
283297
registry_class = Type(
284298
DockerRegistry,
285299
help="""
@@ -369,6 +383,8 @@ def _pod_quota_deprecated(self, change):
369383
log_tail_lines = Integer(
370384
100,
371385
help="""
386+
DEPRECATED: Use c.KubernetesBuildExecutor.log_tail_lines
387+
372388
Limit number of log lines to show when connecting to an already running build.
373389
""",
374390
config=True,
@@ -378,6 +394,8 @@ def _pod_quota_deprecated(self, change):
378394
"binder-build-docker-config",
379395
allow_none=True,
380396
help="""
397+
DEPRECATED: Use c.BuildExecutor.push_secret
398+
381399
A kubernetes secret object that provides credentials for pushing built images.
382400
""",
383401
config=True,
@@ -401,6 +419,8 @@ def _pod_quota_deprecated(self, change):
401419
build_memory_request = ByteSpecification(
402420
0,
403421
help="""
422+
DEPRECATED: Use c.KubernetesBuildExecutor.memory_request
423+
404424
Amount of memory to request when scheduling a build
405425
406426
0 reserves no memory.
@@ -416,6 +436,8 @@ def _pod_quota_deprecated(self, change):
416436
build_memory_limit = ByteSpecification(
417437
0,
418438
help="""
439+
DEPRECATED: Use c.BuildExecutor.memory_limit
440+
419441
Max amount of memory allocated for each image build process.
420442
421443
0 sets no limit.
@@ -440,6 +462,8 @@ def _pod_quota_deprecated(self, change):
440462
"/var/run/docker.sock",
441463
config=True,
442464
help="""
465+
DEPRECATED: Use c.KubernetesBuildExecutor.docker_host
466+
443467
The docker URL repo2docker should use to build the images.
444468
445469
Currently, only paths are supported, and they are expected to be available on
@@ -518,6 +542,8 @@ def _add_slash(self, proposal):
518542

519543
build_namespace = Unicode(
520544
help="""
545+
DEPRECATED: Use c.KubernetesBuildExecutor.namespace
546+
521547
Kubernetes namespace to spawn build pods in.
522548
523549
Note that the push_secret must refer to a secret in this namespace.
@@ -532,6 +558,8 @@ def _default_build_namespace(self):
532558
build_image = Unicode(
533559
"quay.io/jupyterhub/repo2docker:2022.10.0",
534560
help="""
561+
DEPRECATED: Use c.KubernetesBuildExecutor.build_image
562+
535563
The repo2docker image to be used for doing builds
536564
""",
537565
config=True,
@@ -541,6 +569,8 @@ def _default_build_namespace(self):
541569
{},
542570
config=True,
543571
help="""
572+
DEPRECATED: Use c.KubernetesBuildExecutor.node_selector
573+
544574
Select the node where build pod runs on.
545575
""",
546576
)
@@ -737,6 +767,27 @@ def _template_path_default(self):
737767
help="Origin to use when emitting events. Defaults to hostname of request when empty",
738768
)
739769

770+
_build_config_deprecated_map = {
771+
"appendix": ("BuildExecutor", "appendix"),
772+
"push_secret": ("BuildExecutor", "push_secret"),
773+
"build_memory_limit": ("BuildExecutor", "memory_limit"),
774+
"sticky_builds": ("KubernetesBuildExecutor", "sticky_builds"),
775+
"log_tail_lines": ("KubernetesBuildExecutor", "log_tail_lines"),
776+
"build_memory_request": ("KubernetesBuildExecutor", "memory_request"),
777+
"build_docker_host": ("KubernetesBuildExecutor", "docker_host"),
778+
"build_namespace": ("KubernetesBuildExecutor", "namespace"),
779+
"build_image": ("KubernetesBuildExecutor", "build_image"),
780+
"build_node_selector": ("KubernetesBuildExecutor", "node_selector"),
781+
}
782+
783+
@observe(*_build_config_deprecated_map)
784+
def _build_config_deprecated(self, change):
785+
dest_cls, dest_name = self._build_config_deprecated_map[change.name]
786+
self.log.warning(
787+
"BinderHub.%s is deprecated, use %s.%s", change.name, dest_cls, dest_name
788+
)
789+
self.config[dest_cls][dest_name] = change.new
790+
740791
@staticmethod
741792
def add_url_prefix(prefix, handlers):
742793
"""add a url prefix to handlers"""
@@ -830,25 +881,22 @@ def initialize(self, *args, **kwargs):
830881

831882
launch_quota = self.launch_quota_class(parent=self, executor=self.executor)
832883

884+
# Construct a Builder so that we can extract parameters such as the
885+
# configuration or the version string to pass to /version and /health handlers
886+
example_builder = self.build_class(parent=self)
833887
self.tornado_settings.update(
834888
{
835889
"log_function": log_request,
836-
"push_secret": self.push_secret,
837890
"image_prefix": self.image_prefix,
838891
"debug": self.debug,
839892
"launcher": self.launcher,
840-
"appendix": self.appendix,
841893
"ban_networks": self.ban_networks,
842894
"ban_networks_min_prefix_len": self.ban_networks_min_prefix_len,
843-
"build_namespace": self.build_namespace,
844-
"build_image": self.build_image,
845-
"build_node_selector": self.build_node_selector,
846895
"build_pool": self.build_pool,
847896
"build_token_check_origin": self.build_token_check_origin,
848897
"build_token_secret": self.build_token_secret,
849898
"build_token_expires_seconds": self.build_token_expires_seconds,
850-
"sticky_builds": self.sticky_builds,
851-
"log_tail_lines": self.log_tail_lines,
899+
"example_builder": example_builder,
852900
"pod_quota": self.pod_quota,
853901
"per_repo_quota": self.per_repo_quota,
854902
"per_repo_quota_higher": self.per_repo_quota_higher,
@@ -866,9 +914,6 @@ def initialize(self, *args, **kwargs):
866914
"banner_message": self.banner_message,
867915
"extra_footer_scripts": self.extra_footer_scripts,
868916
"jinja2_env": jinja_env,
869-
"build_memory_limit": self.build_memory_limit,
870-
"build_memory_request": self.build_memory_request,
871-
"build_docker_host": self.build_docker_host,
872917
"build_docker_config": self.build_docker_config,
873918
"base_url": self.base_url,
874919
"badge_base_url": self.badge_base_url,
@@ -969,25 +1014,21 @@ def stop(self):
9691014
self.build_pool.shutdown()
9701015

9711016
async def watch_build_pods(self):
972-
"""Watch build pods
1017+
warnings.warn(
1018+
"watch_build_pods() is deprecated, use watch_builders()", DeprecationWarning
1019+
)
1020+
await self.watch_builders()
9731021

974-
Every build_cleanup_interval:
975-
- delete stopped build pods
976-
- delete running build pods older than build_max_age
1022+
async def watch_builders(self):
1023+
"""
1024+
Watch builders, run a cleanup function every build_cleanup_interval
9771025
"""
978-
while True:
1026+
while self.build_cleaner_class:
1027+
cleaner = self.build_cleaner_class()
9791028
try:
980-
await asyncio.wrap_future(
981-
self.executor.submit(
982-
lambda: Build.cleanup_builds(
983-
self.kube_client,
984-
self.build_namespace,
985-
self.build_max_age,
986-
)
987-
)
988-
)
1029+
await asyncio.wrap_future(self.executor.submit(cleaner.cleanup))
9891030
except Exception:
990-
app_log.exception("Failed to cleanup build pods")
1031+
app_log.exception("Failed to cleanup builders")
9911032
await asyncio.sleep(self.build_cleanup_interval)
9921033

9931034
def start(self, run_loop=True):
@@ -998,7 +1039,7 @@ def start(self, run_loop=True):
9981039
)
9991040
self.http_server.listen(self.port)
10001041
if self.builder_required:
1001-
asyncio.ensure_future(self.watch_build_pods())
1042+
asyncio.ensure_future(self.watch_builders())
10021043
if run_loop:
10031044
tornado.ioloop.IOLoop.current().start()
10041045

binderhub/base.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,11 @@ class VersionHandler(BaseHandler):
244244

245245
async def get(self):
246246
self.set_header("Content-type", "application/json")
247-
self.write(
248-
json.dumps(
249-
{
250-
"builder": self.settings["build_image"],
251-
"binderhub": binder_version,
252-
}
253-
)
254-
)
247+
r = {
248+
"builder_info": self.settings["example_builder"].builder_info,
249+
"binderhub": binder_version,
250+
}
251+
# Backwards compatibility
252+
if "build_image" in r["builder_info"]:
253+
r["builder"] = r["builder_info"]["build_image"]
254+
self.write(json.dumps(r))

0 commit comments

Comments
 (0)