def _container_env(version: CMKVersion) -> Dict[str, str]: return { "LANG": "C", "PIPENV_PIPFILE": "/git/Pipfile", "PIPENV_VENV_IN_PROJECT": "true", "VERSION": version.version_spec, "EDITION": version.edition_short, "BRANCH": version.branch(), "RESULT_PATH": "/results", # Write to this result path by default (may be overridden e.g. by integration tests) "PYTEST_ADDOPTS": os.environ.get("PYTEST_ADDOPTS", "") + " --junitxml=/results/junit.xml", }
def _create_cmk_image(client: docker.DockerClient, base_image_name: str, docker_tag: str, version: CMKVersion) -> str: base_image_name_with_tag = "%s:%s" % (base_image_name, docker_tag) logger.info("Preparing base image [%s]", base_image_name_with_tag) base_image = _get_or_load_image(client, base_image_name_with_tag) # This installs the requested Checkmk Edition+Version into the new image, for this reason we add # these parts to the target image name. The tag is equal to the origin image. image_name = "%s-%s-%s" % (base_image_name, version.edition_short, version.version) image_name_with_tag = "%s:%s" % (image_name, docker_tag) logger.info("Preparing image [%s]", image_name_with_tag) # First try to get the pre-built image from the local or remote registry image = _get_or_load_image(client, image_name_with_tag) if image: # We found something locally or remote and ensured it's available locally. # # Only use it when it's based on the latest available base image. Otherwise # skip it. The following code will re-build one based on the current base image if _is_based_on_current_base_image(client, image, base_image): return image_name_with_tag # already found, nothing to do. logger.info("Build image from [%s]", base_image_name_with_tag) if base_image is None: raise Exception( 'Image [%s] is not available locally and the registry "%s" is not reachable. It is ' "not implemented yet to build the image locally. Terminating." % (base_image_name_with_tag, _DOCKER_REGISTRY_URL)) with _start( client, image=base_image_name_with_tag, labels={ "org.tribe29.build_time": "%d" % time.time(), "org.tribe29.build_id": base_image.short_id, "org.tribe29.base_image": base_image_name_with_tag, "org.tribe29.base_image_hash": base_image.short_id, "org.tribe29.cmk_edition_short": version.edition_short, "org.tribe29.cmk_version": version.version, "org.tribe29.cmk_branch": version.branch(), }, command=["tail", "-f", "/dev/null"], # keep running volumes=list(_image_build_volumes().keys()), host_config=client.api.create_host_config( # needed to make the overlay mounts work on the /git directory # Should work, but does not seem to be enough: 'cap_add=["SYS_ADMIN"]'. Using this instead: privileged=True, binds=[ ":".join([k, v["bind"], v["mode"]]) for k, v in _image_build_volumes().items() ], ), ) as container: logger.info("Building in container %s (from [%s])", container.short_id, base_image_name_with_tag) assert _exec_run(container, ["mkdir", "-p", "/results"]) == 0 # Ensure we can make changes to the git directory (not persisting it outside of the container) _prepare_git_overlay(container, "/git-lowerdir", "/git") _prepare_virtual_environment(container, version) _persist_virtual_environment(container, version) logger.info("Install Checkmk version") assert (_exec_run( container, ["scripts/run-pipenv", "run", "/git/tests/scripts/install-cmk.py"], workdir="/git", environment=_container_env(version), stream=True, ) == 0) logger.info("Check whether or not installation was OK") assert _exec_run(container, ["ls", "/omd/versions/default"], workdir="/") == 0 logger.info("Finalizing image") container.stop() image = container.commit(image_name_with_tag) logger.info("Commited image [%s] (%s)", image_name_with_tag, image.short_id) try: logger.info("Uploading [%s] to registry (%s)", image_name_with_tag, image.short_id) client.images.push(image_name_with_tag) logger.info(" Upload complete") except docker.errors.APIError as e: logger.warning(" An error occurred") _handle_api_error(e) return image_name_with_tag