kopia lustrzana https://github.com/jupyterhub/repo2docker
Use enum to standardise `phase`
rodzic
0345a86143
commit
1735925116
|
@ -5,7 +5,11 @@ import logging
|
||||||
from .app import Repo2Docker
|
from .app import Repo2Docker
|
||||||
from .engine import BuildError, ImageLoadError
|
from .engine import BuildError, ImageLoadError
|
||||||
from . import __version__
|
from . import __version__
|
||||||
from .utils import validate_and_generate_port_mapping, is_valid_docker_image_name
|
from .utils import (
|
||||||
|
validate_and_generate_port_mapping,
|
||||||
|
is_valid_docker_image_name,
|
||||||
|
R2dState,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def validate_image_name(image_name):
|
def validate_image_name(image_name):
|
||||||
|
@ -302,7 +306,7 @@ def make_r2d(argv=None):
|
||||||
r2d.log.error(
|
r2d.log.error(
|
||||||
'Cannot mount "{}" in editable mode '
|
'Cannot mount "{}" in editable mode '
|
||||||
"as it is not a directory".format(args.repo),
|
"as it is not a directory".format(args.repo),
|
||||||
extra=dict(phase="failed"),
|
extra=dict(phase=R2dState.FAILED),
|
||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ from .buildpacks import (
|
||||||
)
|
)
|
||||||
from . import contentproviders
|
from . import contentproviders
|
||||||
from .engine import BuildError, ContainerEngineException, ImageLoadError
|
from .engine import BuildError, ContainerEngineException, ImageLoadError
|
||||||
from .utils import ByteSpecification, chdir
|
from .utils import ByteSpecification, chdir, R2dState
|
||||||
|
|
||||||
|
|
||||||
class Repo2Docker(Application):
|
class Repo2Docker(Application):
|
||||||
|
@ -465,7 +465,7 @@ class Repo2Docker(Application):
|
||||||
for log_line in picked_content_provider.fetch(
|
for log_line in picked_content_provider.fetch(
|
||||||
spec, checkout_path, yield_output=self.json_logs
|
spec, checkout_path, yield_output=self.json_logs
|
||||||
):
|
):
|
||||||
self.log.info(log_line, extra=dict(phase="fetching"))
|
self.log.info(log_line, extra=dict(phase=R2dState.FETCHING))
|
||||||
|
|
||||||
if not self.output_image_spec:
|
if not self.output_image_spec:
|
||||||
image_spec = "r2d" + self.repo
|
image_spec = "r2d" + self.repo
|
||||||
|
@ -491,7 +491,7 @@ class Repo2Docker(Application):
|
||||||
"Error during build: %s",
|
"Error during build: %s",
|
||||||
evalue,
|
evalue,
|
||||||
exc_info=(etype, evalue, traceback),
|
exc_info=(etype, evalue, traceback),
|
||||||
extra=dict(phase="failed"),
|
extra=dict(phase=R2dState.FAILED),
|
||||||
)
|
)
|
||||||
|
|
||||||
def initialize(self, *args, **kwargs):
|
def initialize(self, *args, **kwargs):
|
||||||
|
@ -532,7 +532,7 @@ class Repo2Docker(Application):
|
||||||
last_emit_time = time.time()
|
last_emit_time = time.time()
|
||||||
for chunk in client.push(self.output_image_spec):
|
for chunk in client.push(self.output_image_spec):
|
||||||
if client.string_output:
|
if client.string_output:
|
||||||
self.log.info(chunk, extra=dict(phase="pushing"))
|
self.log.info(chunk, extra=dict(phase=R2dState.PUSHING))
|
||||||
continue
|
continue
|
||||||
# else this is Docker output
|
# else this is Docker output
|
||||||
|
|
||||||
|
@ -546,7 +546,7 @@ class Repo2Docker(Application):
|
||||||
self.log.warning("Not a JSON progress line: %r", line)
|
self.log.warning("Not a JSON progress line: %r", line)
|
||||||
continue
|
continue
|
||||||
if "error" in progress:
|
if "error" in progress:
|
||||||
self.log.error(progress["error"], extra=dict(phase="failed"))
|
self.log.error(progress["error"], extra=dict(phase=R2dState.FAILED))
|
||||||
raise ImageLoadError(progress["error"])
|
raise ImageLoadError(progress["error"])
|
||||||
if "id" not in progress:
|
if "id" not in progress:
|
||||||
continue
|
continue
|
||||||
|
@ -561,13 +561,15 @@ class Repo2Docker(Application):
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"Pushing image\n",
|
"Pushing image\n",
|
||||||
extra=dict(
|
extra=dict(
|
||||||
progress=progress_layers, layers=layers, phase="pushing"
|
progress=progress_layers,
|
||||||
|
layers=layers,
|
||||||
|
phase=R2dState.PUSHING,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
last_emit_time = time.time()
|
last_emit_time = time.time()
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"Successfully pushed {}".format(self.output_image_spec),
|
"Successfully pushed {}".format(self.output_image_spec),
|
||||||
extra=dict(phase="pushing"),
|
extra=dict(phase=R2dState.PUSHING),
|
||||||
)
|
)
|
||||||
|
|
||||||
def run_image(self):
|
def run_image(self):
|
||||||
|
@ -659,24 +661,27 @@ class Repo2Docker(Application):
|
||||||
for line in container.logs(stream=True, timestamps=True):
|
for line in container.logs(stream=True, timestamps=True):
|
||||||
line = line.decode("utf-8")
|
line = line.decode("utf-8")
|
||||||
last_timestamp, line = line.split(" ", maxsplit=1)
|
last_timestamp, line = line.split(" ", maxsplit=1)
|
||||||
self.log.info(line, extra=dict(phase="running"))
|
self.log.info(line, extra=dict(phase=R2dState.RUNNING))
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
container.reload()
|
container.reload()
|
||||||
if container.status == "running":
|
if container.status == "running":
|
||||||
self.log.info("Stopping container...\n", extra=dict(phase="running"))
|
self.log.info(
|
||||||
|
"Stopping container...\n", extra=dict(phase=R2dState.RUNNING)
|
||||||
|
)
|
||||||
container.kill()
|
container.kill()
|
||||||
exit_code = container.exitcode
|
exit_code = container.exitcode
|
||||||
|
|
||||||
container.wait()
|
container.wait()
|
||||||
|
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"Container finished running.\n".upper(), extra=dict(phase="running")
|
"Container finished running.\n".upper(),
|
||||||
|
extra=dict(phase=R2dState.RUNNING),
|
||||||
)
|
)
|
||||||
# are there more logs? Let's send them back too
|
# are there more logs? Let's send them back too
|
||||||
late_logs = container.logs(since=last_timestamp).decode("utf-8")
|
late_logs = container.logs(since=last_timestamp).decode("utf-8")
|
||||||
for line in late_logs.split("\n"):
|
for line in late_logs.split("\n"):
|
||||||
self.log.debug(line + "\n", extra=dict(phase="running"))
|
self.log.debug(line + "\n", extra=dict(phase=R2dState.RUNNING))
|
||||||
|
|
||||||
container.remove()
|
container.remove()
|
||||||
if exit_code:
|
if exit_code:
|
||||||
|
@ -751,7 +756,7 @@ class Repo2Docker(Application):
|
||||||
self.log.error(
|
self.log.error(
|
||||||
"Subdirectory %s does not exist",
|
"Subdirectory %s does not exist",
|
||||||
self.subdir,
|
self.subdir,
|
||||||
extra=dict(phase="failure"),
|
extra=dict(phase=R2dState.FAILED),
|
||||||
)
|
)
|
||||||
raise FileNotFoundError("Could not find {}".format(checkout_path))
|
raise FileNotFoundError("Could not find {}".format(checkout_path))
|
||||||
|
|
||||||
|
@ -786,7 +791,7 @@ class Repo2Docker(Application):
|
||||||
else:
|
else:
|
||||||
self.log.debug(
|
self.log.debug(
|
||||||
picked_buildpack.render(build_args),
|
picked_buildpack.render(build_args),
|
||||||
extra=dict(phase="building"),
|
extra=dict(phase=R2dState.BUILDING),
|
||||||
)
|
)
|
||||||
if self.user_id == 0:
|
if self.user_id == 0:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -796,7 +801,7 @@ class Repo2Docker(Application):
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"Using %s builder\n",
|
"Using %s builder\n",
|
||||||
bp.__class__.__name__,
|
bp.__class__.__name__,
|
||||||
extra=dict(phase="building"),
|
extra=dict(phase=R2dState.BUILDING),
|
||||||
)
|
)
|
||||||
|
|
||||||
for l in picked_buildpack.build(
|
for l in picked_buildpack.build(
|
||||||
|
@ -808,19 +813,24 @@ class Repo2Docker(Application):
|
||||||
self.extra_build_kwargs,
|
self.extra_build_kwargs,
|
||||||
):
|
):
|
||||||
if docker_client.string_output:
|
if docker_client.string_output:
|
||||||
self.log.info(l, extra=dict(phase="building"))
|
self.log.info(l, extra=dict(phase=R2dState.BUILDING))
|
||||||
# else this is Docker output
|
# else this is Docker output
|
||||||
elif "stream" in l:
|
elif "stream" in l:
|
||||||
self.log.info(l["stream"], extra=dict(phase="building"))
|
self.log.info(
|
||||||
|
l["stream"], extra=dict(phase=R2dState.BUILDING)
|
||||||
|
)
|
||||||
elif "error" in l:
|
elif "error" in l:
|
||||||
self.log.info(l["error"], extra=dict(phase="failure"))
|
self.log.info(l["error"], extra=dict(phase=R2dState.FAILED))
|
||||||
raise BuildError(l["error"])
|
raise BuildError(l["error"])
|
||||||
elif "status" in l:
|
elif "status" in l:
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"Fetching base image...\r", extra=dict(phase="building")
|
"Fetching base image...\r",
|
||||||
|
extra=dict(phase=R2dState.BUILDING),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.log.info(json.dumps(l), extra=dict(phase="building"))
|
self.log.info(
|
||||||
|
json.dumps(l), extra=dict(phase=R2dState.BUILDING)
|
||||||
|
)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# Cleanup checkout if necessary
|
# Cleanup checkout if necessary
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from .base import ContentProvider, ContentProviderException
|
from .base import ContentProvider, ContentProviderException
|
||||||
from ..utils import execute_cmd, check_ref
|
from ..utils import execute_cmd, check_ref, R2dState
|
||||||
|
|
||||||
|
|
||||||
class Git(ContentProvider):
|
class Git(ContentProvider):
|
||||||
|
@ -44,7 +44,7 @@ class Git(ContentProvider):
|
||||||
hash = check_ref(ref, output_dir)
|
hash = check_ref(ref, output_dir)
|
||||||
if hash is None:
|
if hash is None:
|
||||||
self.log.error(
|
self.log.error(
|
||||||
"Failed to check out ref %s", ref, extra=dict(phase="failed")
|
"Failed to check out ref %s", ref, extra=dict(phase=R2dState.FAILED)
|
||||||
)
|
)
|
||||||
if ref == "master":
|
if ref == "master":
|
||||||
msg = (
|
msg = (
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from .base import ContentProvider, ContentProviderException
|
from .base import ContentProvider, ContentProviderException
|
||||||
from ..utils import execute_cmd
|
from ..utils import execute_cmd, R2dState
|
||||||
|
|
||||||
args_enabling_topic = ["--config", "extensions.topic="]
|
args_enabling_topic = ["--config", "extensions.topic="]
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ class Mercurial(ContentProvider):
|
||||||
yield line
|
yield line
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
self.log.error(
|
self.log.error(
|
||||||
"Failed to update to ref %s", ref, extra=dict(phase="failed")
|
"Failed to update to ref %s", ref, extra=dict(phase=R2dState.FAILED)
|
||||||
)
|
)
|
||||||
raise ValueError("Failed to update to ref {}".format(ref))
|
raise ValueError("Failed to update to ref {}".format(ref))
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
from enum import Enum
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -10,6 +11,21 @@ from shutil import copystat, copy2
|
||||||
from traitlets import Integer, TraitError
|
from traitlets import Integer, TraitError
|
||||||
|
|
||||||
|
|
||||||
|
class R2dState(Enum):
|
||||||
|
"""
|
||||||
|
The current state of repo2docker
|
||||||
|
"""
|
||||||
|
|
||||||
|
FETCHING = "fetching"
|
||||||
|
BUILDING = "building"
|
||||||
|
PUSHING = "pushing"
|
||||||
|
RUNNING = "running"
|
||||||
|
FAILED = "failed"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
|
||||||
def execute_cmd(cmd, capture=False, **kwargs):
|
def execute_cmd(cmd, capture=False, **kwargs):
|
||||||
"""
|
"""
|
||||||
Call given command, yielding output line by line if capture=True.
|
Call given command, yielding output line by line if capture=True.
|
||||||
|
|
Ładowanie…
Reference in New Issue