diff --git a/precise/docker-builder/README b/precise/docker-builder/README new file mode 100644 index 0000000..81eb76c --- /dev/null +++ b/precise/docker-builder/README @@ -0,0 +1,28 @@ + + +Unfinished because untested. But, the script docker-updater is +tested and used. + + +This LXC requires a kernel >3.8 at least. (to be able to run docker in +LXC) It requires also "aufs" capabilities (apparmor.d permission, but +also available in kernel) + +XXXvlab: we could run docker in LXC via a socket towards an host's +install of docker and remove this constraint. + + +It is meant to build image of applications based on a single git-sub +code. + +It provides an IMAGE that does not requires 'git' tool, and won't +contain any git history. + +Then, it'll be able to update this image by small "docker commits" +quite efficiently. + + +Currently the image produced can only be run on docker host that +support running aufs in the containers (this implies, that the docker +fs driver IS NOT aufs, that the host kernel support aufs, and that +permissions are set so that container can mount an aufs filesystem). diff --git a/precise/docker-builder/config b/precise/docker-builder/config new file mode 100644 index 0000000..de6f698 --- /dev/null +++ b/precise/docker-builder/config @@ -0,0 +1 @@ +lxc.aa_profile = unconfined diff --git a/precise/docker-builder/hooks/install b/precise/docker-builder/hooks/install new file mode 100755 index 0000000..4927894 --- /dev/null +++ b/precise/docker-builder/hooks/install @@ -0,0 +1,29 @@ +#!/bin/bash + +set -eux # -x for verbose logging to juju debug-log + +## +## add files +## + +cp src/usr/local/sbin/* src/usr/local/sbin/ + +## Could consider not using docker inside the LXC for compatibility +## reason in this case you need to setup a --lts connection. You can +## use "DOCKER_MAIN_OPTS" to add this to every usage of docker one +## 0k-docker is installed. + +## install +## - 0k-docker for docker-build-charm +ln -sf /opt/apps/0k-docker/bin/docker-build-charm /usr/local/sbin + +## - 0k-charm for charms +ln -sf /opt/apps/0k-charms/precise /srv/charm-store + +apt-get install python-pip ## for 'pip install shyaml' +pip install shyaml ## for docker-build-charm + +apt-get install kal-shlib-pretty ## for docker-build-charm + + + diff --git a/precise/docker-builder/hooks/start b/precise/docker-builder/hooks/start new file mode 100755 index 0000000..9eb7853 --- /dev/null +++ b/precise/docker-builder/hooks/start @@ -0,0 +1,3 @@ +#!/bin/bash + +juju-log "Nothing to Start for base." diff --git a/precise/docker-builder/hooks/stop b/precise/docker-builder/hooks/stop new file mode 100755 index 0000000..170162b --- /dev/null +++ b/precise/docker-builder/hooks/stop @@ -0,0 +1,3 @@ +#!/bin/bash + +juju-log "Nothing to stop for base." diff --git a/precise/docker-builder/metadata.yaml b/precise/docker-builder/metadata.yaml new file mode 100644 index 0000000..777584c --- /dev/null +++ b/precise/docker-builder/metadata.yaml @@ -0,0 +1,11 @@ +name: docker-builder +summary: "Docker Builder" +maintainer: "Valentin Lab " +inherit: docker +description: | + Docker Builder +data-resources: + - /var/lib/docker + - /srv/docker-updates +config-resources: + - /etc/docker diff --git a/precise/docker-builder/revision b/precise/docker-builder/revision new file mode 100644 index 0000000..573541a --- /dev/null +++ b/precise/docker-builder/revision @@ -0,0 +1 @@ +0 diff --git a/precise/docker-builder/src/usr/lib/docker-updater/wrap-application b/precise/docker-builder/src/usr/lib/docker-updater/wrap-application new file mode 100644 index 0000000..a51465a --- /dev/null +++ b/precise/docker-builder/src/usr/lib/docker-updater/wrap-application @@ -0,0 +1,38 @@ +#!/bin/bash + +orig=$0.diverted + +if [ -z "$APP_LOCATION" ]; then + echo "Error: APP_LOCATION was not defined." + exit 1 +fi + +app=/srv/app +root=$app/root +changes=$app/changes/0000 +mnt=$app/mnt + +## All these should be in the root image +#mkdir -p $root $mnt +#mkdir -p "$(dirname "$APP_LOCATION")" + +if [ -d "$changes" ]; then + clean_all() { + cd / + mountpoint "$mnt" 2>/dev/null && umount "$mnt" + } + + + trap "clean_all" EXIT + mount -t aufs -o br=$changes:$root -o udba=none none "$mnt" + if [ "$?" != 0 ]; then + echo "Error: aufs mount failed." + exit 1 + fi + + ln -sf "$mnt" "$APP_LOCATION" +else + ln -sf "$root" "$APP_LOCATION" +fi + +"$orig" "$@" diff --git a/precise/docker-builder/src/usr/local/bin/docker-build b/precise/docker-builder/src/usr/local/bin/docker-build new file mode 100755 index 0000000..f6f0c93 --- /dev/null +++ b/precise/docker-builder/src/usr/local/bin/docker-build @@ -0,0 +1,68 @@ +#!/bin/bash + +## Called by git-hooks or by hand, it should produce a master git-sub repository + +## it should: +## - checkout the correct BRANCH of GIT_REPOS in DOCKER_UPDATE_PATH +## - launch a build of IMAGE with special option to copy the git repos checkouted +## - push the image to UPDATED_IMAGE_NAME + + +#!- +. /etc/shlib +#!- + + +DOCKER_UPDATE_PATH=${DOCKER_UPDATE_PATH:-/srv/docker-builder} + + +include common +include pretty + +usage="$exname COMPONENT CHARM MASTER_IMAGE_NAME BRANCH" + +if [ "$#" == 0 ]; then + print_usage + exit 0 +fi + +COMPONENT_NAME="$1" +CHARM="$2" +MASTER_IMAGE_NAME="$3" +BRANCH="$4" + +if [ -z "$COMPONENT_NAME" ]; then + print_error "You need to specify a component name as first argument." +fi + +if [ -z "$CHARM" ]; then + print_error "You need to specify a charm name as second argument." +fi + +if [ -z "$MASTER_IMAGE_NAME" ]; then + print_error "You need to specify a master image ame as first argument. (ie: docker.0k.io/odoo:master)" +fi + +if [ -z "$BRANCH" ]; then + print_error "You need to specify a branch as fourth argument. (ie: 8.0/0k/dev/master)" +fi + + +. /etc/charm/global.conf + +## git-sub co should be so much better ! +set -ex + +mkdir -p "$DOCKER_UPDATE_PATH" +cd "$DOCKER_UPDATE_PATH" +rm -rf "$COMPONENT_NAME" +time git sub clone $GIT_0K_CLONE_OPTIONS $GIT_0K_SUB_CLONE_OPTIONS -b "$BRANCH" \ + "$GIT_0K_BASE"/0k/"$COMPONENT_NAME" +docker rmi "$CHARM" || true +export DOCKER_RUN_OPTS="-v $DOCKER_UPDATE_PATH/$COMPONENT_NAME:$DOCKER_UPDATE_PATH/$COMPONENT_NAME" +time ODOO_CP_FROM_DIR="$DOCKER_UPDATE_PATH/$COMPONENT_NAME" EXTRA_CHARM_VARS="ODOO_CP_FROM_DIR" docker-build-charm "$CHARM" + +docker tag "$CHARM" "$MASTER_IMAGE_NAME" + +docker push "$MASTER_IMAGE_NAME" + diff --git a/precise/docker-builder/src/usr/local/bin/docker-update b/precise/docker-builder/src/usr/local/bin/docker-update new file mode 100755 index 0000000..5e1302c --- /dev/null +++ b/precise/docker-builder/src/usr/local/bin/docker-update @@ -0,0 +1,110 @@ +#!/bin/bash + + +#!- +. /etc/shlib +#!- + + +DOCKER_UPDATE_PATH=${DOCKER_UPDATE_PATH:-/srv/docker-builder} + + +include common +include pretty + +usage="$exname COMPONENT MASTER_IMAGE_NAME BRANCH UPDATED_IMAGE_NAME" + + +COMPONENT_NAME="$1" +MASTER_IMAGE_NAME="$2" +BRANCH="$3" +UPDATED_IMAGE_NAME="$4" + +## Note: we will need in the DOCKER_UPDATE_HOST: +## - git-sub + +## should we check for aufs ? + +mkdir -p "$DOCKER_UPDATE_PATH" +cd "$DOCKER_UPDATE_PATH" +if ! [ -d "$COMPONENT_NAME" ]; then + echo "ERROR: repository $DOCKER_UPDATE_PATH/$COMPONENT_NAME is not existent." + echo "You should build it on this host prior to run this hook." + echo "As a remainder: this host is supposed to keep the reference git that" + echo "was used to built the master image." + exit 1 +fi + +if [ -e "$COMPONENT_NAME.locked" ]; then + echo "Master is being updated." + echo "Or '$COMPONENT_NAME.locked' file was left dangling over." + exit 1 +fi + + +clean_all() { + cd / + mountpoint "$tmpdir_root" 2>/dev/null && umount "$tmpdir_root" + [ -d "$tmpdir_root" ] && rmdir "$tmpdir_root" + [ -d "$tmpdir_changes" ] && rm -rf "$tmpdir_changes" +} + +tmpdir_changes=$(mktemp -d /tmp/$COMPONENT_NAME.changes.XXXXXX) +tmpdir_root=$(mktemp -d /tmp/$COMPONENT_NAME.root.XXXXXX) + +trap "clean_all" EXIT +mount -t aufs -o br=$tmpdir_changes:$DOCKER_UPDATE_PATH/$COMPONENT_NAME -o udba=none none "$tmpdir_root" +cd "$tmpdir_root" + +## XXXvlab: We probably would need to: +## - fetch only the module concerned +## - fetch only the ref concerned +git fetch origin "$BRANCH" +git checkout "$BRANCH" +git sub update + +cd / && +umount "$tmpdir_root" && +rmdir "$tmpdir_root" +if [ "$?" != 0 ]; then + echo "Uh oh... could not umount aufs $tmpdir_root or delete it." + exit 1 +fi +cd "$tmpdir_changes" + +echo "Cleaning the change layer." +find . -name .git -type d -exec rm -rf {} \; -prune + + + +## XXXvlab: if we produced it we shouldn't have to pull it +# +#echo "Pulling $MASTER_IMAGE_NAME" +#docker pull "$MASTER_IMAGE_NAME" || exit 1 +container_id=$( + docker run -d \ + -v $tmpdir_changes:/mnt/changes \ + --entrypoint '/bin/bash' \ + "$MASTER_IMAGE_NAME" \ + -c " + mkdir -p /srv/app/{root,changes} + cp -a /mnt/changes /srv/app/changes/0000 + ls /srv/app/changes/0000 + ") +if [ "$?" != 0 ]; then + echo "Failed to call docker run..." + exit 1 +fi +if [ "$(docker wait "$container_id")" != "0" ]; then + echo "Copy of changes to docker images failed !" + echo "Log of container:" + docker logs "$container_id" + exit 1 +fi + +docker commit --author "$exname" \ + --message "Automatic Updater" \ + "$container_id" \ + "$UPDATED_IMAGE_NAME" + +docker push "$UPDATED_IMAGE_NAME"