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

Add inject dockerfile support for multiplatform images and test for mp image reuse in other steps. #66

Merged
merged 1 commit into from
Aug 31, 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
27 changes: 27 additions & 0 deletions buildrunner/docker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import os
import ssl
import tempfile
from typing import Tuple
import urllib.parse
import docker

Expand Down Expand Up @@ -105,3 +107,28 @@ def force_remove_container(docker_client, container):
force=True,
v=True,
)


def get_dockerfile(dockerfile: str, temp_dir: str = None) -> Tuple[str, bool]:
"""
Check if the dockerfile exists, if not create a temporary file and write the dockerfile to it.
:param dockerfile: the dockerfile
:param temp_dir: the temporary directory
:return: the dockerfile and a boolean indicating if the dockerfile was created
"""
cleanup_dockerfile = False
curr_dockerfile = None

if dockerfile:
if os.path.exists(dockerfile):
curr_dockerfile = dockerfile
else:
# pylint: disable=consider-using-with
df_file = tempfile.NamedTemporaryFile(delete=False, dir=temp_dir)
try:
df_file.write(dockerfile.encode('utf-8'))
cleanup_dockerfile = True
curr_dockerfile = df_file.name
finally:
df_file.close()
return curr_dockerfile, cleanup_dockerfile
16 changes: 3 additions & 13 deletions buildrunner/docker/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import docker
import docker.errors

from buildrunner.docker import new_client, force_remove_container
from buildrunner.docker import get_dockerfile, new_client, force_remove_container


class DockerBuilder: # pylint: disable=too-many-instance-attributes
Expand All @@ -39,18 +39,8 @@ def __init__(
self.temp_dir = temp_dir
self.dockerfile = None
self.cleanup_dockerfile = False
if dockerfile:
if os.path.exists(dockerfile):
self.dockerfile = dockerfile
else:
# pylint: disable=consider-using-with
df_file = tempfile.NamedTemporaryFile(delete=False, dir=self.temp_dir)
try:
df_file.write(dockerfile.encode('utf-8'))
self.cleanup_dockerfile = True
self.dockerfile = df_file.name
finally:
df_file.close()

self.dockerfile, self.cleanup_dockerfile = get_dockerfile(dockerfile, self.temp_dir)

self.docker_client = new_client(
dockerd_url=dockerd_url,
Expand Down
14 changes: 11 additions & 3 deletions buildrunner/docker/multiplatform_image_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import python_on_whales
from python_on_whales import docker

from buildrunner.docker import get_dockerfile

LOGGER = logging.getLogger(__name__)


Expand Down Expand Up @@ -308,7 +310,9 @@ def build_multiple_images(self,
build_args = {}
build_args['DOCKER_REGISTRY'] = docker_registry

LOGGER.debug(f"Building {name}:{tags} for platforms {platforms} from {file}")
dockerfile, cleanup_dockerfile = get_dockerfile(file)

LOGGER.debug(f"Building {name}:{tags} for platforms {platforms} from {dockerfile}")

if self._use_local_registry and not self._local_registry_is_running:
# Starts local registry container to do ephemeral image storage
Expand All @@ -335,7 +339,7 @@ def build_multiple_images(self,
platform,
push,
path,
file,
dockerfile,
tags,
build_args,
self._intermediate_built_images[name])))
Expand All @@ -344,7 +348,7 @@ def build_multiple_images(self,
platform,
push,
path,
file,
dockerfile,
tags,
build_args,
self._intermediate_built_images[name])
Expand All @@ -355,6 +359,10 @@ def build_multiple_images(self,
for proc in processes:
proc.join()

if cleanup_dockerfile:
bluesliverx marked this conversation as resolved.
Show resolved Hide resolved
if dockerfile and os.path.exists(dockerfile):
os.remove(dockerfile)

return self._intermediate_built_images[name]

def push(self, name: str, dest_names: List[str] = None) -> None:
Expand Down
3 changes: 3 additions & 0 deletions buildrunner/steprunner/tasks/push.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ def run(self, context): # pylint: disable=too-many-branches
tags=repo.tags,
dest_name=repo.repository)

for tag in repo.tags:
self.step_runner.build_runner.committed_images.add(f'{repo.repository}:{tag}')

# add image as artifact
if not self._commit_only:
images = self.step_runner.multi_platform.get_built_images(self.get_unique_build_name())
Expand Down
6 changes: 6 additions & 0 deletions tests/test-files/test-docker-pull-failure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Tests that a failure to pull an image results in a failure.
steps:
use-bogus-image:
run:
image: user1/buildrunner-test-multi-platform:bogus
cmd: echo "Hello World"
20 changes: 20 additions & 0 deletions tests/test-files/test-mp-image-reuse.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Test to ensure that subsequent steps can use the recently built image
steps:
build-container-multi-platform:
build:
dockerfile: |
FROM {{ DOCKER_REGISTRY }}/busybox
platforms:
- linux/amd64
- linux/arm64/v8
push:
repository: user1/buildrunner-test-multi-platform
tags: [ 'latest', '0.0.1' ]
run:
image: user1/buildrunner-test-multi-platform:0.0.1
cmd: echo "Hello World"

use-built-image:
run:
image: user1/buildrunner-test-multi-platform:0.0.1
cmd: echo "Hello World"
3 changes: 3 additions & 0 deletions tests/test_buildrunner_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def _get_exit_code(file_name: str) -> int:
if file_name.startswith('test-inject-nonexistent-dir'):
return os.EX_CONFIG

if file_name.startswith('test-docker-pull-failure'):
return os.EX_CONFIG

return os.EX_OK


Expand Down
4 changes: 4 additions & 0 deletions tests/test_runner.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import sys
import docker

sys.path.insert(
0,
Expand Down Expand Up @@ -58,5 +59,8 @@ def run_tests(argv, master_config_file=None, global_config_files=None):
except BuildRunnerConfigurationError as brce:
print(str(brce))
return os.EX_CONFIG
except docker.errors.ImageNotFound as inf:
print(str(inf))
return os.EX_CONFIG
return os.EX_OK

Loading