Upgrade plugins if needed (#306)

Each plugin installed through the docker image is now tracked using a
marker file containing the version that was installed through the image.

If later, the container is started from a docker image containing newer
plugins, existing plugins will be upgraded if they haven't been upgraded
in the mean time and if the new docker image provides a new version of
them.

Add tests to check that plugins are upgrade properly
This commit is contained in:
Vincent Latombe 2016-07-13 18:18:14 +02:00 committed by Carlos Sanchez
parent 195787dca5
commit bb8f8c9ad0
5 changed files with 160 additions and 10 deletions

View File

@ -223,6 +223,12 @@ All the data needed is in the /var/jenkins_home directory - so depending on how
As always - please ensure that you know how to drive docker - especially volume handling!
## Upgrading plugins
By default, plugins will be upgraded if they haven't been upgraded manually and if the version from the docker image is newer than the version in the container. Versions installed by the docker image are tracked through a marker file.
The default behaviour when upgrading from a docker image that didn't write marker files is to leave existing plugins in place. If you want to upgrade existing plugins without marker you may run the docker image with `-e TRY_UPGRADE_IF_NO_MARKER=true`. Then plugins will be upgraded if the version provided by the docker image is newer.
# Building
Build with the usual

View File

@ -2,6 +2,19 @@
set -e
# compare if version1 < version2
versionLT() {
[ "$1" = "$2" ] && return 1 || [ "$1" = "`echo -e "$1\n$2" | sort -V | head -n1`" ]
}
# returns a plugin version from a plugin archive
get_plugin_version() {
local archive; archive=$1
local version; version=$(unzip -p $archive META-INF/MANIFEST.MF | grep "^Plugin-Version: " | sed -e 's#^Plugin-Version: ##')
version=${version%%[[:space:]]}
echo $version
}
# Copy files from /usr/share/jenkins/ref into $JENKINS_HOME
# So the initial JENKINS-HOME is set with expected content.
# Don't override, as this is just a reference setup, and use from UI
@ -9,20 +22,94 @@ set -e
copy_reference_file() {
f="${1%/}"
b="${f%.override}"
echo "$f" >> "$COPY_REFERENCE_FILE_LOG"
rel="${b:23}"
version_marker="${rel}.version_from_image"
dir=$(dirname "${b}")
echo " $f -> $rel" >> "$COPY_REFERENCE_FILE_LOG"
if [[ ! -e $JENKINS_HOME/${rel} || $f = *.override ]]
then
echo "copy $rel to JENKINS_HOME" >> "$COPY_REFERENCE_FILE_LOG"
mkdir -p "$JENKINS_HOME/${dir:23}"
cp -r "${f}" "$JENKINS_HOME/${rel}";
# pin plugins on initial copy
[[ ${rel} == plugins/*.jpi ]] && touch "$JENKINS_HOME/${rel}.pinned"
fi;
local action;
local reason;
local container_version;
local image_version;
local marker_version;
local log; log=false
if [[ ${rel} == plugins/*.jpi ]]; then
container_version=$(get_plugin_version $JENKINS_HOME/${rel})
image_version=$(get_plugin_version ${f})
if [[ -e $JENKINS_HOME/${version_marker} ]]; then
marker_version=$(cat $JENKINS_HOME/${version_marker})
if versionLT $marker_version $container_version; then
action="SKIPPED"
reason="Installed version ($container_version) has been manually upgraded from initial version ($marker_version)"
log=true
else
if [[ "$image_version" == "$container_version" ]]; then
action="SKIPPED"
reason="Version from image is the same as the installed version $image_version"
else
if versionLT $image_version $container_version; then
action="SKIPPED"
log=true
reason="Image version ($image_version) is older than installed version ($container_version)"
else
action="UPGRADED"
log=true
reason="Image version ($image_version) is newer than installed version ($container_version)"
fi
fi
fi
else
if [[ -n "$TRY_UPGRADE_IF_NO_MARKER" ]]; then
if [[ "$image_version" == "$container_version" ]]; then
action="SKIPPED"
reason="Version from image is the same as the installed version $image_version (no marker found)"
# Add marker for next time
echo $image_version > $JENKINS_HOME/${version_marker}
else
if versionLT $image_version $container_version; then
action="SKIPPED"
log=true
reason="Image version ($image_version) is older than installed version ($container_version) (no marker found)"
else
action="UPGRADED"
log=true
reason="Image version ($image_version) is newer than installed version ($container_version) (no marker found)"
fi
fi
fi
fi
if [[ ! -e $JENKINS_HOME/${rel} || "$action" == "UPGRADED" || $f = *.override ]]; then
action=${action:-"INSTALLED"}
log=true
mkdir -p "$JENKINS_HOME/${dir:23}"
cp -r "${f}" "$JENKINS_HOME/${rel}";
# pin plugins on initial copy
touch "$JENKINS_HOME/${rel}.pinned"
echo $image_version > $JENKINS_HOME/${version_marker}
reason=${reason:-$image_version}
else
action=${action:-"SKIPPED"}
fi
else
if [[ ! -e $JENKINS_HOME/${rel} || $f = *.override ]]
then
action="INSTALLED"
log=true
mkdir -p "$JENKINS_HOME/${dir:23}"
cp -r "${f}" "$JENKINS_HOME/${rel}";
else
action="SKIPPED"
fi
fi
if [[ -n "$VERBOSE" || "$log" == "true" ]]; then
if [ -z "$reason" ]; then
echo "$action $rel" >> "$COPY_REFERENCE_FILE_LOG"
else
echo "$action $rel : $reason" >> "$COPY_REFERENCE_FILE_LOG"
fi
fi
}
: ${JENKINS_HOME:="/var/jenkins_home"}
export -f versionLT
export -f get_plugin_version
export -f copy_reference_file
touch "${COPY_REFERENCE_FILE_LOG}" || (echo "Can not write to ${COPY_REFERENCE_FILE_LOG}. Wrong volume permissions?" && exit 1)
echo "--- Copying files at $(date)" >> "$COPY_REFERENCE_FILE_LOG"

View File

@ -3,6 +3,7 @@
# check dependencies
(
type docker &>/dev/null || ( echo "docker is not available"; exit 1 )
type unzip &>/dev/null || ( echo "unzip is not available"; exit 1 )
type curl &>/dev/null || ( echo "curl is not available"; exit 1 )
)>&2

View File

@ -78,3 +78,56 @@ load test_helpers
@test "clean test containers" {
cleanup $SUT_CONTAINER
}
@test "plugins are getting upgraded but not downgraded" {
run docker build -t $SUT_IMAGE-install-plugins $BATS_TEST_DIRNAME/install-plugins
assert_success
local work; work="$BATS_TEST_DIRNAME/upgrade-plugins/work"
# Image contains maven-plugin 2.7.1 and ant-plugin 1.3
run bash -c "docker run -ti -v $work:/var/jenkins_home --rm $SUT_IMAGE-install-plugins true"
assert_success
run bash -c "unzip -p $work/plugins/maven-plugin.jpi META-INF/MANIFEST.MF | tr -d '\r'"
assert_line 'Plugin-Version: 2.7.1'
run bash -c "unzip -p $work/plugins/ant.jpi META-INF/MANIFEST.MF | tr -d '\r'"
assert_line 'Plugin-Version: 1.3'
run docker build -t $SUT_IMAGE-upgrade-plugins $BATS_TEST_DIRNAME/upgrade-plugins
assert_success
# Images contains maven-plugin 2.13 and ant-plugin 1.2
run bash -c "docker run -ti -v $work:/var/jenkins_home --rm $SUT_IMAGE-upgrade-plugins true"
assert_success
run bash -c "unzip -p $work/plugins/maven-plugin.jpi META-INF/MANIFEST.MF | tr -d '\r'"
assert_success
# Should be updated
assert_line 'Plugin-Version: 2.13'
run bash -c "unzip -p $work/plugins/ant.jpi META-INF/MANIFEST.MF | tr -d '\r'"
# 1.2 is older than the existing 1.3, so keep 1.3
assert_line 'Plugin-Version: 1.3'
}
@test "clean work directory" {
run bash -c "rm -rf $BATS_TEST_DIRNAME/upgrade-plugins/work"
}
@test "do not upgrade if plugin has been manually updated" {
run docker build -t $SUT_IMAGE-install-plugins $BATS_TEST_DIRNAME/install-plugins
assert_success
local work; work="$BATS_TEST_DIRNAME/upgrade-plugins/work"
# Image contains maven-plugin 2.7.1 and ant-plugin 1.3
run bash -c "docker run -ti -v $work:/var/jenkins_home --rm $SUT_IMAGE-install-plugins curl --connect-timeout 5 --retry 5 --retry-delay 0 --retry-max-time 60 -s -f -L https://updates.jenkins.io/download/plugins/maven-plugin/2.12.1/maven-plugin.hpi -o /var/jenkins_home/plugins/maven-plugin.jpi"
assert_success
run bash -c "unzip -p $work/plugins/maven-plugin.jpi META-INF/MANIFEST.MF | tr -d '\r'"
assert_line 'Plugin-Version: 2.12.1'
run docker build -t $SUT_IMAGE-upgrade-plugins $BATS_TEST_DIRNAME/upgrade-plugins
assert_success
# Images contains maven-plugin 2.13 and ant-plugin 1.2
run bash -c "docker run -ti -v $work:/var/jenkins_home --rm $SUT_IMAGE-upgrade-plugins true"
assert_success
run bash -c "unzip -p $work/plugins/maven-plugin.jpi META-INF/MANIFEST.MF | tr -d '\r'"
assert_success
# Shouldn't be updated
refute_line 'Plugin-Version: 2.13'
}
@test "clean work directory" {
run bash -c "rm -rf $BATS_TEST_DIRNAME/upgrade-plugins/work"
}

View File

@ -0,0 +1,3 @@
FROM bats-jenkins
RUN /usr/local/bin/install-plugins.sh maven-plugin:2.13 ant:1.2