Use enum to standardise `phase`

pull/1185/head
Simon Li 2022-10-03 22:49:22 +01:00
rodzic 0345a86143
commit 1735925116
5 zmienionych plików z 55 dodań i 25 usunięć

Wyświetl plik

@ -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)

Wyświetl plik

@ -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

Wyświetl plik

@ -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 = (

Wyświetl plik

@ -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))

Wyświetl plik

@ -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.