"""Generate a Dockerfile from in.Dockerfile and a version JSON file, and write version info.""" import re from pathlib import Path from textwrap import dedent from scripts import python_version DOCKERFILE_TEMPLATE = Path("scripts/in.Dockerfile").read_text("utf-8") DOCKERFILE = Path("Dockerfile") JAIL_CONFIG = Path("config/snekbox.cfg") versions, main_version = python_version.get_all_versions() # Download and copy multiple python images into one layer python_build = "" jail_mounts = "" previous_layer = "first" for version in versions: # Configure NSJail mounts jail_mounts += dedent( f""" mount {{ src: "/usr/local/bin/python{version.version_name}" dst: "/usr/local/bin/python{version.version_name}" is_bind: true rw: false }} """ ) if version.is_main: # Main is handled separately later continue # Add the current version to the Dockerfile layer_name = version.version_name.replace(".", "-") # Dots aren't valid in layer names python_build += dedent( f""" FROM python:{version.image_tag} as base-{layer_name} COPY --from=base-{previous_layer} / / """ ) previous_layer = layer_name # Main version is installed twice, once at the very beginning to make sure # its files aren't overwritten, and once at the end which actually makes use of the version python_build = f"FROM python:{main_version.image_tag} as base-first\n" + python_build # Update mounts for python binaries in the NSJail config new_config = re.sub( r"(?<=# mount-section-key)[\s\S]+(?=# mount-section-key-end)", jail_mounts, JAIL_CONFIG.read_text("utf-8"), ) JAIL_CONFIG.write_text(new_config, "utf-8") # Write new dockerfile DOCKERFILE.write_text( "# THIS FILE IS AUTOGENERATED, DO NOT MODIFY! #\n" + DOCKERFILE_TEMPLATE.replace("{python_install_commands}", python_build) .replace("{final_base}", previous_layer) .replace("{main_version_tag}", main_version.image_tag), "utf-8", ) print("Finished!")