Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docker: add registry option #754

Merged
merged 7 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,6 @@ jobs:
strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]
env:
VIRTUAL_ENV: "test"
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
15 changes: 8 additions & 7 deletions reana/reana_dev/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,13 +166,14 @@ def reana_dev(): # noqa: D301
.. code-block:: console

\b
$ reana-dev git-clean
$ reana-dev docker-build --no-cache
$ # we should now run one more test with non-cached ``latest``
$ # once it works, we can tag and push
$ reana-dev docker-build -t 0.3.0.dev20180625
$ reana-dev docker-push -t 0.3.0.dev20180625
$ # we should now publish stable helm charts for tag via chartpress
$ # Clean the environment
$ cd ~/mysrc/reana-server
$ reana-dev git-clean -c .
$ # Build the docker image
$ reana-dev docker-build --platform linux/amd64 --platform linux/arm64 -c .
$ # Tag and release the image
$ reana-dev git-tag -c .
$ reana-dev release-docker --platform linux/amd64 --platform linux/arm64 -c .

"""
pass
Expand Down
76 changes: 63 additions & 13 deletions reana/reana_dev/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

"""`reana-dev`'s Docker commands."""

import sys

Check warning on line 11 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L11

Added line #L11 was not covered by tests
import click

from reana.config import DOCKER_PREFETCH_IMAGES
Expand Down Expand Up @@ -85,6 +86,11 @@
type=click.IntRange(min=1),
help="Number of docker images to build in parallel.",
)
@click.option(

Check warning on line 89 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L89

Added line #L89 was not covered by tests
"--platform",
multiple=True,
help="Platforms for multi-arch images [default=current architecture]",
)
@docker_commands.command(name="docker-build")
@click.pass_context
def docker_build(
Expand All @@ -98,6 +104,7 @@
quiet,
exclude_components,
parallel,
platform,
): # noqa: D301
"""Build REANA component images.

Expand Down Expand Up @@ -126,6 +133,8 @@
:param output_component_versions: File where to write the built images
tags. Useful when using `--tag auto` since every REANA component
will have a different tag.
:param parallel: Number of docker images to build in parallel.
:param platform: Platforms for multi-arch images. [default=current architecture]
:type component: str
:type exclude_components: str
:type user: str
Expand All @@ -134,10 +143,18 @@
:type no_cache: bool
:type output_component_versions: File
:type quiet: bool
:type parallel: int
:type platform: list
"""
if exclude_components:
exclude_components = exclude_components.split(",")
components = select_components(component, exclude_components)

is_multi_arch = len(platform) > 1
if is_multi_arch:

Check warning on line 154 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L153-L154

Added lines #L153 - L154 were not covered by tests
# check whether podman is installed
run_command("podman version", display=False, return_output=True)

Check warning on line 156 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L156

Added line #L156 was not covered by tests

built_components_versions_tags = []

# show the component's name before each output line of `docker build` if there
Expand All @@ -147,21 +164,39 @@

commands = []
for component in components:
component_tag = tag
if is_component_dockerised(component):
cmd = "docker build"
if tag == "auto":
component_tag = get_docker_tag(component)
component_tag = get_docker_tag(component) if tag == "auto" else tag
component_version_tag = "docker.io/{0}/{1}:{2}".format(

Check warning on line 169 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L168-L169

Added lines #L168 - L169 were not covered by tests
user, component, component_tag
)
if is_multi_arch:

Check warning on line 172 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L172

Added line #L172 was not covered by tests
# remove the image with the same name, if it exists, as otherwise
# podman is not able to create the manifest
run_command(

Check warning on line 175 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L175

Added line #L175 was not covered by tests
f"podman image rm {component_version_tag} || true", component
)
# remove the manifest if it already exists, as otherwise podman will add
# the built images to the existing manifest instead of creating a new one
run_command(

Check warning on line 180 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L180

Added line #L180 was not covered by tests
f"podman manifest rm {component_version_tag} || true", component
)
cmd = "podman build"

Check warning on line 183 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L183

Added line #L183 was not covered by tests
else:
cmd = "docker build"

Check warning on line 185 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L185

Added line #L185 was not covered by tests
for arg in build_arg:
cmd += " --build-arg {0}".format(arg)
if no_cache:
cmd += " --no-cache"
if quiet or parallel > 1:
cmd += " --quiet"
component_version_tag = "docker.io/{0}/{1}:{2}".format(
user, component, component_tag
)
cmd += " -t {0} .".format(component_version_tag)
if platform:
cmd += f" --platform {','.join(platform)}"

Check warning on line 193 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L192-L193

Added lines #L192 - L193 were not covered by tests

if is_multi_arch:
cmd += f" --manifest {component_version_tag} ."

Check warning on line 196 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L195-L196

Added lines #L195 - L196 were not covered by tests
else:
cmd += " -t {0} .".format(component_version_tag)

Check warning on line 198 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L198

Added line #L198 was not covered by tests

commands.append((_run_command, (cmd, component)))
built_components_versions_tags.append(component_version_tag)
else:
Expand Down Expand Up @@ -257,12 +292,19 @@
default=["CLUSTER"],
help="Which components? [name|CLUSTER]",
)
@click.option(

Check warning on line 295 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L295

Added line #L295 was not covered by tests
"--registry",
"-r",
default="docker.io",
help="Registry to use in the image tag [default=docker.io]",
)
@click.option("--image-name", help="Does the local image have a custom name?")

Check warning on line 301 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L301

Added line #L301 was not covered by tests
@docker_commands.command(name="docker-push")
def docker_push(user, tag, component): # noqa: D301
"""Push REANA component images to DockerHub.
def docker_push(user, tag, component, registry, image_name): # noqa: D301

Check warning on line 303 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L303

Added line #L303 was not covered by tests
"""Push REANA component images to a Docker image registry.

\b
:param components: The option ``component`` can be repeated. The value may
:param component: The option ``component`` can be repeated. The value may
consist of:
* (1) standard component name such as
'reana-workflow-controller';
Expand All @@ -280,18 +322,26 @@
:param user: DockerHub organisation or user name. [default=reanahub]
:param tag: Docker image tag to push. Default 'latest'. Use 'auto' to
push git-tag-based value such as '0.7.0-alpha.3'.
:param tag: Docker tag to use. [default=latest]
:param registry: Registry to use in the image tag. [default=docker.io]
:param image_name: Custom name of the local Docker image.
:type component: str
:type user: str
:type tag: str
:type registry: str
:type image_name: str
"""
components = select_components(component)

if image_name and len(components) > 1:
click.secho("Cannot use custom image name with multiple components.", fg="red")
sys.exit(1)

Check warning on line 337 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L335-L337

Added lines #L335 - L337 were not covered by tests

for component in components:
component_tag = tag
if is_component_dockerised(component):
if tag == "auto":
component_tag = get_docker_tag(component)
cmd = "docker push {0}/{1}:{2}".format(user, component, component_tag)
cmd = f"docker push {registry}/{user}/{image_name or component}:{component_tag}"

Check warning on line 344 in reana/reana_dev/docker.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/docker.py#L344

Added line #L344 was not covered by tests
run_command(cmd, component)
else:
msg = "Ignoring this component that does not contain" " a Dockerfile."
Expand Down
95 changes: 87 additions & 8 deletions reana/reana_dev/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

"""`reana-dev`'s release commands."""

import json

Check warning on line 11 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L11

Added line #L11 was not covered by tests
import os
import sys
import tempfile
Expand Down Expand Up @@ -84,10 +85,24 @@
)
@click.option("--user", "-u", default="reanahub", help="DockerHub user name [reanahub]")
@click.option("--image-name", help="Should the component have a custom image name?")
@click.option(

Check warning on line 88 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L88

Added line #L88 was not covered by tests
"--registry",
"-r",
default="docker.io",
help="Registry to use in the image tag [default=docker.io]",
)
@click.option(

Check warning on line 94 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L94

Added line #L94 was not covered by tests
"--platform",
multiple=True,
help="Platforms for multi-arch images [default=current architecture]",
)
@click.option("--tags-only", is_flag=True, help="Only print the Docker image tags")

Check warning on line 99 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L99

Added line #L99 was not covered by tests
@release_commands.command(name="release-docker")
@click.pass_context
def release_docker(ctx, component, user, image_name): # noqa: D301
"""Release a component on Docker Hub.
def release_docker(

Check warning on line 102 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L102

Added line #L102 was not covered by tests
ctx, component, user, image_name, registry, platform, tags_only
): # noqa: D301
"""Release a component on a Docker image registry.

\b
:param components: The option ``component`` can be repeated. The value may
Expand All @@ -105,21 +120,85 @@
to include several runable REANA demo examples;
* (7) special value 'ALL' that will expand to include
all REANA repositories.
:param user: Organisation or user name. [default=reanahub]
:param image_name: Custom name of the local Docker image.
:param registry: Registry to use in the image tag. [default=docker.io]
:param platform: Platforms for multi-arch images. [default=current architecture]
:param tags_only: Only print the Docker image tags.
:type component: str
:type user: str
:type image_name: str
:type registry: str
:type platform: list
:type tags_only: bool
"""
components = select_components(component)

if image_name and len(components) > 1:
click.secho("Cannot use custom image name with multiple components.", fg="red")
sys.exit(1)

Check warning on line 139 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L137-L139

Added lines #L137 - L139 were not covered by tests
Comment on lines +137 to +139
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: maybe we could add this check also in the docker_push function? It could be helpful when calling it directly from the docker-push command.


is_multi_arch = len(platform) > 1
if is_multi_arch and not tags_only:

Check warning on line 142 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L141-L142

Added lines #L141 - L142 were not covered by tests
# check whether podman is installed
run_command("podman version", display=False, return_output=True)

Check warning on line 144 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L144

Added line #L144 was not covered by tests
# platforms are in the format OS/ARCH[/VARIANT], we are only interested in ARCH
expected_arch = sorted([p.split("/")[1] for p in platform])

Check warning on line 146 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L146

Added line #L146 was not covered by tests

cannot_release_on_dockerhub = []
for component_ in components:
if not is_component_dockerised(component_):
cannot_release_on_dockerhub.append(component_)
is_component_releasable(component_, exit_code=True, display=True)
full_image_name = f"{user}/{image_name or component_}"
# source_image_name is the name used by docker-build
source_image_name = f"docker.io/{user}/{component_}"
target_image_name = f"{registry}/{user}/{image_name or component_}"

Check warning on line 155 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L154-L155

Added lines #L154 - L155 were not covered by tests
docker_tag = get_docker_tag(component_)
run_command(
f"docker tag {full_image_name}:latest {full_image_name}:{docker_tag}",
component_,
)
ctx.invoke(docker_push, component=[component_], tag=docker_tag, user=user)

if tags_only:
click.echo(f"{target_image_name}:{docker_tag}")
continue

Check warning on line 160 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L158-L160

Added lines #L158 - L160 were not covered by tests

if is_multi_arch:
manifest = json.loads(

Check warning on line 163 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L162-L163

Added lines #L162 - L163 were not covered by tests
run_command(
f"podman manifest inspect {source_image_name}:latest",
component=component_,
return_output=True,
)
)
manifest_arch = sorted(

Check warning on line 170 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L170

Added line #L170 was not covered by tests
[m["platform"]["architecture"] for m in manifest["manifests"]]
)
if manifest_arch != expected_arch:
display_message(

Check warning on line 174 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L173-L174

Added lines #L173 - L174 were not covered by tests
f"Expected multi-arch image {source_image_name} with {expected_arch} variants, "
f"found {manifest_arch}.",
component=component_,
)
sys.exit(1)
run_command(

Check warning on line 180 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L179-L180

Added lines #L179 - L180 were not covered by tests
f"podman tag {source_image_name}:latest {target_image_name}:{docker_tag}",
component_,
)
run_command(

Check warning on line 184 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L184

Added line #L184 was not covered by tests
f"podman manifest push --all {target_image_name}:{docker_tag} "
f"docker://{target_image_name}:{docker_tag}",
component_,
)
else:
run_command(

Check warning on line 190 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L190

Added line #L190 was not covered by tests
f"docker tag {source_image_name}:latest {target_image_name}:{docker_tag}",
component_,
)
ctx.invoke(

Check warning on line 194 in reana/reana_dev/release.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/release.py#L194

Added line #L194 was not covered by tests
docker_push,
component=[component_],
registry=registry,
user=user,
image_name=image_name,
tag=docker_tag,
)

if cannot_release_on_dockerhub:
click.secho(
Expand Down
14 changes: 1 addition & 13 deletions reana/reana_dev/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@
REPO_LIST_DEMO_RUNNABLE,
)

INSTANCE_NAME = os.path.basename(os.environ["VIRTUAL_ENV"])


def shorten_component_name(component):
"""Return canonical short version of the component name.
Expand Down Expand Up @@ -438,16 +436,6 @@
click.secho("{0}".format(msg), bold=True)


def get_prefixed_component_name(component):
"""Get prefixed component name.

:param component: String representing the component name.

:return: Prefixed name.
"""
return "-".join([INSTANCE_NAME, component])


def fetch_latest_pypi_version(package):
"""Fetch latest released version of a package."""
import requests
Expand Down Expand Up @@ -912,7 +900,7 @@
:type component: str
"""
cmd = "git describe --tags --abbrev=0"
return run_command(cmd, component, return_output=True, display=True)
return run_command(cmd, component, return_output=True, display=False)

Check warning on line 903 in reana/reana_dev/utils.py

View check run for this annotation

Codecov / codecov/patch

reana/reana_dev/utils.py#L903

Added line #L903 was not covered by tests


def validate_mode_option(ctx, param, value):
Expand Down