diff --git a/check-install.sh b/check-install.sh deleted file mode 100755 index 6364a11..0000000 --- a/check-install.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env bash - -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -source "$DIR/lib/util.sh" - -function show_usage { - echo - echo "Usage: $0 deb_file [image]" - echo - echo "Paramètres: " - echo - echo " - deb_file Chemin vers le paquet Debian dont on doit vérifier l'installation" - echo " - image Optionnel - Nom de l'image Docker à utiliser comme environnement pour tester l'installation. Défaut: debian:jessie" - echo -} - -function create_container { - - # Escape image name - local escaped_basename=$(echo "$BASE_IMAGE" | sed 's/[^a-z0-9\-\_\.]/\_/gi') - # Generate container tag - container_tag="tamarin:${escaped_basename}_$(date +%s)" - # Create temporary dir for the Dockerfile - local temp_dir="$(mktemp -d)" - - # Link lib folder - ln -s $(readlink -f "$DIR/lib") "$temp_dir/lib" - - # Create Dockerfile - cat << EOF > "$temp_dir/Dockerfile" - FROM $BASE_IMAGE - - ENV DEBIAN_FRONTEND noninteractive - - RUN apt-get update && apt-get install --yes gdebi-core - - ADD ./lib /root/.tamarin - RUN chmod +x /root/.tamarin/install.sh - - VOLUME /deb - - ENTRYPOINT ["/root/.tamarin/install.sh"] - -EOF - - # Build image - tar -C "$temp_dir" -czh . | docker build -t "$container_tag" - 2> >(error) 1> >(info) - - # Delete temporary folder - rm -rf "$temp_dir" - -} - -function main { - - # Create container image - create_container - - # Run container and install package - docker run -e "DISTRIB=$BASE_IMAGE" --rm -v="$DEB_DIR:/deb" "$container_tag" "/deb/$DEB_NAME" - - # Check for return - if [ $? != 0 ]; then - fatal "Installation did not complete correctly !" - fi - - info "Installation complete." - -} - -# Test for arguments -if [ -z "$1" ]; then - show_usage - exit 1 -fi - -DEB_PATH=$(readlink -f "$1") -DEB_NAME=$(basename "$DEB_PATH") -DEB_DIR=$(dirname "$DEB_PATH") -BASE_IMAGE="${2:-debian:jessie}" - -main diff --git a/hooks/containerbuild/debian/install-build-essential b/hooks/containerbuild/debian/install-build-essential new file mode 100755 index 0000000..766557a --- /dev/null +++ b/hooks/containerbuild/debian/install-build-essential @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +${TAMARIN_ACBUILD} environment add DEBIAN_FRONTEND noninteractive +sudo -E ${TAMARIN_ACBUILD} run -- apt-get update +sudo -E ${TAMARIN_ACBUILD} run -- apt-get install --yes --no-install-recommends build-essential devscripts equivs +${TAMARIN_ACBUILD} environment remove DEBIAN_FRONTEND diff --git a/hooks/containerbuild/debian/install-git b/hooks/containerbuild/debian/install-git new file mode 100755 index 0000000..890305a --- /dev/null +++ b/hooks/containerbuild/debian/install-git @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +${TAMARIN_ACBUILD} environment add DEBIAN_FRONTEND noninteractive +sudo -E ${TAMARIN_ACBUILD} run -- apt-get update +sudo -E ${TAMARIN_ACBUILD} run -- apt-get install --yes --no-install-recommends git-core +${TAMARIN_ACBUILD} environment remove DEBIAN_FRONTEND diff --git a/hooks/install-git-containerbuild b/hooks/install-git-containerbuild deleted file mode 100755 index b1f91ce..0000000 --- a/hooks/install-git-containerbuild +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -echo "RUN apt-get update && apt-get install --yes --no-install-recommends git-core" >> Dockerfile diff --git a/lib/tamarin.py b/lib/tamarin.py index 22f29a7..f38f53b 100644 --- a/lib/tamarin.py +++ b/lib/tamarin.py @@ -1,6 +1,16 @@ import os, glob, subprocess, configparser import web, system +def run_profile_hooks(profile, step, cwd=None, env=None): + hooks_dir = get_hooks_dir() + step_hooks = profile[step]["hooks"].split(",") + for hook_name in step_hooks: + hook_path = os.path.join(hooks_dir, hook_name) + subprocess.call(hook_path, cwd=cwd, stdin=subprocess.PIPE, env=env) + +def get_hooks_dir(): + return os.path.realpath(os.path.dirname(os.path.abspath(__file__)) + "/../hooks") + def load_profile(profile_name): profile_filename = profile_name+".conf" for profile_file in get_available_profiles(): @@ -41,10 +51,6 @@ def get_rkt_achive_dest_dir(): workspace_tmp = get_workspace_subdir('tmp') return glob.glob(os.path.join(os.sep, workspace_tmp, 'rkt-v*'))[0] -def get_acbuild_workspace_dir(): - """Return the current path (linked to the process pid) to the acbuild workspace""" - return get_workspace_subdir("tmp/build_{:d}".format(os.getpid())) - def download_rkt(): """Download a local copy of rkt in the tamarin workspace and return the absolute path to the archive""" url = "https://github.com/coreos/rkt/releases/download/v1.22.0/rkt-v1.22.0.tar.gz" diff --git a/package b/package index 89f65df..f040d8d 100755 --- a/package +++ b/package @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -import argparse, sys, shutil, os +import argparse, sys, shutil, os, hashlib sys.path.append(os.path.dirname(__file__) + '/lib') @@ -15,6 +15,7 @@ def configure_args_parser(): # Define available/required arguments and flags parser.add_argument("project_path", help="The path to your project to package") parser.add_argument("-p", "--profile", help="The profile to use to package this project (default: debian)", choices=profile_names, default='debian') + parser.add_argument("--rebuild", help="Ignore cache and rebuild container's image", action="store_true", default=False) return parser @@ -23,6 +24,7 @@ if __name__ == "__main__": parser = configure_args_parser() args = parser.parse_args() + # Load build profile profile = tamarin.load_profile(args.profile) workspace = tamarin.get_workspace_dir() @@ -46,13 +48,11 @@ if __name__ == "__main__": shutil.rmtree(local_acbuild_dir, ignore_errors=True) os.rename(acbuild_archive_dir, local_acbuild_dir) - acbuild_workspace = tamarin.get_acbuild_workspace_dir() pid = os.getpid() - image_name = "image_{:d}.aci".format(pid) - image_path = os.path.join(os.sep, acbuild_workspace, image_name) - acbuild_flags = ["--work-path", acbuild_workspace] + build_workspace = tamarin.get_workspace_subdir('tmp/build_{:d}'.format(pid)) - rkt_flags = ["--dir={:s}".format(workspace_tmp)] + rkt_store = tamarin.get_workspace_subdir('store') + rkt_flags = ["--dir={:s}".format(rkt_store)] base_image = profile['profile']['default_image'] # If the base image is Docker-based, preload it and get its name from the store @@ -63,28 +63,45 @@ if __name__ == "__main__": base_image ] + rkt_flags) - name_pattern = base_image.split('/')[-1] + '$' - image = rkt.find_image_by_name(name_pattern, rkt_flags=rkt_flags) + aci_file = os.path.join(os.sep, build_workspace, 'image.aci') + acbuild_flags = ["--modify", aci_file, "--work-path", build_workspace] + # Use cached image base on base_image and containerbuild hooks + containerbuild_hooks = profile['containerbuild']['hooks'] + hasher = hashlib.sha1() + hasher.update(base_image.encode()) + hasher.update(containerbuild_hooks.encode()) + image_hash = hasher.hexdigest() + cache_dir = tamarin.get_workspace_subdir('cache') + cached_image_file = os.path.join(os.sep, cache_dir, '{:s}.aci'.format(image_hash[:12])); - base_aci_name = image['id'][:21]+'.aci' - base_aci_file = workspace_tmp+'/'+base_aci_name + if not args.rebuild and os.path.exists(cached_image_file): + # Copy cached image + shutil.copyfile(cached_image_file, aci_file) + else: + # Find and export base image from rkt' store + name_pattern = base_image.split('/')[-1] + '$' + image = rkt.find_image_by_name(name_pattern, rkt_flags=rkt_flags) + rkt.export_image(image['id'], aci_file, rkt_flags=rkt_flags); - if not os.path.isfile(base_aci_file): - rkt.export_image(image['id'], workspace_tmp+'/'+base_aci_name, rkt_flags=rkt_flags); + # Build image + tamarin.run_acbuild(acbuild_flags+["set-name", "image_{:d}".format(pid)]) + tamarin.run_acbuild(acbuild_flags+["set-exec", "--", "/bin/sh", "-c", "echo Hello World"]) - # Start building image - tamarin.run_acbuild(acbuild_flags+["begin", base_aci_file]) - tamarin.run_acbuild(acbuild_flags+["set-name", "image_{:d}".format(pid)]) - tamarin.run_acbuild(acbuild_flags+["set-exec", "--", "/bin/sh", "-c", "uname -a"]) - tamarin.run_acbuild(acbuild_flags+["write", image_path]) - tamarin.run_acbuild(acbuild_flags+["end"]) + # Execute containerbuild hooks + cpb_hooks_env = os.environ.copy() + cpb_hooks_env["PATH"] = os.environ['PATH'] + ':' + local_acbuild_dir + cpb_hooks_env["TAMARIN_ACBUILD"] = " ".join([system.which('acbuild', local_acbuild_dir)]+acbuild_flags) + tamarin.run_profile_hooks(profile, 'containerbuild', cwd=build_workspace, env=cpb_hooks_env) - # rkt run --insecure-options=image ./nginx.aci --volume html,kind=host,source=/path/to/test --net=host + # Cache image + shutil.copyfile(aci_file, cached_image_file) + + # Start container rkt.run([ "run", "--insecure-options=image", - image_path, "--net=host" + aci_file, "--net=host" ] + rkt_flags, as_root=True) # Cleanup @@ -99,4 +116,4 @@ if __name__ == "__main__": "gc" ] + rkt_flags, as_root=True) - shutil.rmtree(acbuild_workspace, ignore_errors=True) + shutil.rmtree(build_workspace, ignore_errors=True) diff --git a/profiles/debian.conf b/profiles/debian.conf index ccd8216..3a8a572 100644 --- a/profiles/debian.conf +++ b/profiles/debian.conf @@ -4,8 +4,8 @@ default_image=docker://debian:jessie # Configuration de l'étape de pré-construction du conteneur -[containerprebuild] -hooks=install-git-containerbuild +[containerbuild] +hooks=containerbuild/debian/install-build-essential,containerbuild/debian/install-git # Configuration de l'étape de pré-construction du paquet [prebuild]