Skip to content

Commit a8d5049

Browse files
committed
Support dynamic push credentials obtained from registry
1 parent 6f03245 commit a8d5049

File tree

3 files changed

+46
-12
lines changed

3 files changed

+46
-12
lines changed

binderhub/build.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,18 @@ class BuildExecutor(LoggingConfigurable):
9191
config=True,
9292
)
9393

94+
push_secret_content = Unicode(
95+
"",
96+
help=(
97+
"Content of an implementation dependent secret for pushing image to a registry. "
98+
"For example, if push tokens are temporary this can be used to pass the token "
99+
"as an environment variable CONTAINER_ENGINE_REGISTRY_CREDENTIALS to "
100+
"repo2docker."
101+
"If provided this will be used instead of push_secret."
102+
),
103+
config=True,
104+
)
105+
94106
memory_limit = ByteSpecification(
95107
0,
96108
help="Memory limit for the build process in bytes (optional suffixes K M G T).",
@@ -394,7 +406,23 @@ def submit(self):
394406
)
395407
]
396408

397-
if self.push_secret:
409+
env = [
410+
client.V1EnvVar(name=key, value=value)
411+
for key, value in self.extra_envs.items()
412+
]
413+
if self.git_credentials:
414+
env.append(
415+
client.V1EnvVar(name="GIT_CREDENTIAL_ENV", value=self.git_credentials)
416+
)
417+
418+
if self.push_secret_content:
419+
env.append(
420+
client.V1EnvVar(
421+
name="CONTAINER_ENGINE_REGISTRY_CREDENTIALS",
422+
value=self.push_secret_content,
423+
)
424+
)
425+
elif self.push_secret:
398426
volume_mounts.append(
399427
client.V1VolumeMount(mount_path="/root/.docker", name="docker-config")
400428
)
@@ -405,15 +433,6 @@ def submit(self):
405433
)
406434
)
407435

408-
env = [
409-
client.V1EnvVar(name=key, value=value)
410-
for key, value in self.extra_envs.items()
411-
]
412-
if self.git_credentials:
413-
env.append(
414-
client.V1EnvVar(name="GIT_CREDENTIAL_ENV", value=self.git_credentials)
415-
)
416-
417436
self.pod = client.V1Pod(
418437
metadata=client.V1ObjectMeta(
419438
name=self.name,

binderhub/builder.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,11 +381,12 @@ async def get(self, provider_prefix, _unescaped_spec):
381381
.lower()
382382
)
383383

384+
image_without_tag, image_tag = _get_image_basename_and_tag(image_name)
384385
if self.settings["use_registry"]:
385386
for _ in range(3):
386387
try:
387388
image_manifest = await self.registry.get_image_manifest(
388-
*_get_image_basename_and_tag(image_name)
389+
image_without_tag, image_tag
389390
)
390391
image_found = bool(image_manifest)
391392
break
@@ -457,7 +458,13 @@ async def get(self, provider_prefix, _unescaped_spec):
457458
image_name=image_name,
458459
git_credentials=provider.git_credentials,
459460
)
460-
if not self.settings["use_registry"]:
461+
if self.settings["use_registry"]:
462+
push_token = await self.registry.get_credentials(
463+
image_without_tag, image_tag
464+
)
465+
if push_token:
466+
build.push_secret_content = json.dumps(push_token)
467+
else:
461468
build.push_secret = ""
462469

463470
self.build = build

binderhub/registry.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,14 @@ async def get_image_manifest(self, image, tag):
329329
raise
330330
return json.loads(resp.body.decode("utf-8"))
331331

332+
async def get_credentials(self, image, tag):
333+
"""
334+
If a dynamic token is required for pushing an image to the registry
335+
return a dictionary of login credentials, otherwise return None
336+
(caller should get credentials from some other source)
337+
"""
338+
return None
339+
332340

333341
class FakeRegistry(DockerRegistry):
334342
"""

0 commit comments

Comments
 (0)