From 0ebb9d755d2be90732059ed4b7bdac3493c76c4d Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 13 Dec 2023 14:14:31 +0100 Subject: [PATCH] feat: implement support for image pull secret for build pod This new KubernetesBuildExecutor specific option allows to set a list of image pull secret so that the build pod can also access private registries to retrieve the image it uses. --- binderhub/build.py | 17 ++++++++++++++++ binderhub/tests/test_build.py | 38 +++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/binderhub/build.py b/binderhub/build.py index 0cbf82762..5e46f7b58 100644 --- a/binderhub/build.py +++ b/binderhub/build.py @@ -297,6 +297,10 @@ def _default_namespace(self): def _default_builder_info(self): return {"build_image": self.build_image} + image_pull_secrets = List( + [], help="Pull secrets for the builder image", config=True + ) + docker_host = Unicode( "/var/run/docker.sock", allow_none=True, @@ -455,6 +459,18 @@ def get_builder_volumes(self): return volumes, volume_mounts + def get_image_pull_secrets(self): + """ + Get the list of image pull secrets to be used for the builder image + """ + + image_pull_secrets = [] + + for secret in self.image_pull_secrets: + image_pull_secrets.append(client.V1LocalObjectReference(name=secret)) + + return image_pull_secrets + def submit(self): """ Submit a build pod to create the image for the repository. @@ -526,6 +542,7 @@ def submit(self): volumes=volumes, restart_policy="Never", affinity=self.get_affinity(), + image_pull_secrets=self.get_image_pull_secrets(), ), ) diff --git a/binderhub/tests/test_build.py b/binderhub/tests/test_build.py index 8dfdd3721..3f9fca503 100644 --- a/binderhub/tests/test_build.py +++ b/binderhub/tests/test_build.py @@ -417,6 +417,44 @@ class EnvBuild(KubernetesBuildExecutor): assert env == extra_environments +def test_build_image_pull_secrets(): + build_pull_secrets = ["build-image-secret", "build-image-secret-2"] + + mock_k8s_api = _list_image_builder_pods_mock() + + class PullBuild(KubernetesBuildExecutor): + q = mock.MagicMock() + api = mock_k8s_api + name = "test_build" + repo_url = "repo" + ref = "ref" + image_name = "name" + namespace = "build_namespace" + push_secret = "" + build_image = "image" + image_pull_secrets = build_pull_secrets + memory_limit = 0 + docker_host = "http://mydockerregistry.local" + node_selector = {} + + build = PullBuild() + + with mock.patch.object(build.stop_event, "is_set", return_value=True): + build.submit() + + call_args_list = mock_k8s_api.create_namespaced_pod.call_args_list + assert len(call_args_list) == 1 + + args = call_args_list[0][0] + pod = args[1] + + assert len(pod.spec.containers) == 1 + + pull_secrets = [secret.name for secret in pod.spec.image_pull_secrets] + + assert pull_secrets == build_pull_secrets + + async def test_local_repo2docker_build(): q = Queue() repo_url = "https://github.com/binderhub-ci-repos/cached-minimal-dockerfile"