blob: 233b739b1ddb03a8a11c852f321167621e40ccbf [file] [log] [blame]
Carlos Sanchez7d165ac2016-08-14 11:13:12 +02001#!/bin/bash -eu
Nicolas De Loof0ef5a622016-05-27 19:14:29 +02002
Sýlvan Heuserb20f3882016-06-01 15:47:38 +02003# Resolve dependencies and download plugins given on the command line
4#
5# FROM jenkins
6# RUN install-plugins.sh docker-slaves github-branch-source
7
Carlos Sanchez3a83b9d2016-08-08 09:36:28 +02008set -o pipefail
9
apotterebbd13d02016-06-23 12:24:15 -040010REF_DIR=${REF:-/usr/share/jenkins/ref/plugins}
11FAILED="$REF_DIR/failed-plugins.txt"
Sýlvan Heuserb20f3882016-06-01 15:47:38 +020012
Vincent Latombec14af952016-07-18 10:20:12 +020013. /usr/local/bin/jenkins-support
14
Charles Duffy3eec42c2016-09-20 12:11:33 -050015getLockFile() {
16 printf '%s' "$REF_DIR/${1}.lock"
apotterebbd13d02016-06-23 12:24:15 -040017}
18
Charles Duffy3eec42c2016-09-20 12:11:33 -050019getArchiveFilename() {
20 printf '%s' "$REF_DIR/${1}.jpi"
apotterebbd13d02016-06-23 12:24:15 -040021}
Sýlvan Heuserb20f3882016-06-01 15:47:38 +020022
Charles Duffy3eec42c2016-09-20 12:11:33 -050023download() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +020024 local plugin originalPlugin version lock ignoreLockFile
25 plugin="$1"
26 version="${2:-latest}"
27 ignoreLockFile="${3:-}"
28 lock="$(getLockFile "$plugin")"
Nicolas De Loof0ef5a622016-05-27 19:14:29 +020029
Carlos Sanchezc0f63792016-08-15 10:30:16 +020030 if [[ $ignoreLockFile ]] || mkdir "$lock" &>/dev/null; then
31 if ! doDownload "$plugin" "$version"; then
32 # some plugin don't follow the rules about artifact ID
33 # typically: docker-plugin
34 originalPlugin="$plugin"
35 plugin="${plugin}-plugin"
36 if ! doDownload "$plugin" "$version"; then
37 echo "Failed to download plugin: $originalPlugin or $plugin" >&2
38 echo "Not downloaded: ${originalPlugin}" >> "$FAILED"
39 return 1
40 fi
41 fi
Nicolas De Loofa7a34c32016-05-30 09:10:58 +020042
Carlos Sanchezc0f63792016-08-15 10:30:16 +020043 if ! checkIntegrity "$plugin"; then
44 echo "Downloaded file is not a valid ZIP: $(getArchiveFilename "$plugin")" >&2
45 echo "Download integrity: ${plugin}" >> "$FAILED"
46 return 1
47 fi
apotterebbd13d02016-06-23 12:24:15 -040048
Carlos Sanchezc0f63792016-08-15 10:30:16 +020049 resolveDependencies "$plugin"
50 fi
Nicolas De Loof0ef5a622016-05-27 19:14:29 +020051}
52
Charles Duffy3eec42c2016-09-20 12:11:33 -050053doDownload() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +020054 local plugin version url jpi
55 plugin="$1"
56 version="$2"
57 jpi="$(getArchiveFilename "$plugin")"
apotterebbd13d02016-06-23 12:24:15 -040058
Carlos Sanchezc0f63792016-08-15 10:30:16 +020059 # If plugin already exists and is the same version do not download
60 if test -f "$jpi" && unzip -p "$jpi" META-INF/MANIFEST.MF | tr -d '\r' | grep "^Plugin-Version: ${version}$" > /dev/null; then
61 echo "Using provided plugin: $plugin"
62 return 0
63 fi
apotterebbd13d02016-06-23 12:24:15 -040064
Carlos Sanchez0d167af2016-08-29 11:02:57 +020065 JENKINS_UC_DOWNLOAD=${JENKINS_UC_DOWNLOAD:-"$JENKINS_UC/download"}
Jean-Louis Boudartad0ff9c2016-08-22 09:00:30 +020066
67 url="$JENKINS_UC_DOWNLOAD/plugins/$plugin/$version/${plugin}.hpi"
apotterebbd13d02016-06-23 12:24:15 -040068
Carlos Sanchezc0f63792016-08-15 10:30:16 +020069 echo "Downloading plugin: $plugin from $url"
Carlos Sanchez21b0f372016-10-06 13:26:17 -070070 curl --connect-timeout ${CURL_CONNECTION_TIMEOUT:-20} --retry ${CURL_RETRY:-5} --retry-delay ${CURL_RETRY_DELAY:-0} --retry-max-time ${CURL_RETRY_MAX_TIME:-60} -s -f -L "$url" -o "$jpi"
Carlos Sanchezc0f63792016-08-15 10:30:16 +020071 return $?
apotterebbd13d02016-06-23 12:24:15 -040072}
73
Charles Duffy3eec42c2016-09-20 12:11:33 -050074checkIntegrity() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +020075 local plugin jpi
76 plugin="$1"
77 jpi="$(getArchiveFilename "$plugin")"
apotterebbd13d02016-06-23 12:24:15 -040078
Gareth Harcombe-Minsond6a75122016-09-26 09:59:36 -050079 unzip -t -qq "$jpi" >/dev/null
Carlos Sanchezc0f63792016-08-15 10:30:16 +020080 return $?
apotterebbd13d02016-06-23 12:24:15 -040081}
82
Charles Duffy3eec42c2016-09-20 12:11:33 -050083resolveDependencies() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +020084 local plugin jpi dependencies
85 plugin="$1"
86 jpi="$(getArchiveFilename "$plugin")"
Nicolas De Loof0ef5a622016-05-27 19:14:29 +020087
Carlos Sanchezc0f63792016-08-15 10:30:16 +020088 dependencies="$(unzip -p "$jpi" META-INF/MANIFEST.MF | tr -d '\r' | tr '\n' '|' | sed -e 's#| ##g' | tr '|' '\n' | grep "^Plugin-Dependencies: " | sed -e 's#^Plugin-Dependencies: ##')"
Nicolas De Loof0ef5a622016-05-27 19:14:29 +020089
Carlos Sanchezc0f63792016-08-15 10:30:16 +020090 if [[ ! $dependencies ]]; then
91 echo " > $plugin has no dependencies"
92 return
93 fi
Nicolas De Loof0ef5a622016-05-27 19:14:29 +020094
Carlos Sanchezc0f63792016-08-15 10:30:16 +020095 echo " > $plugin depends on $dependencies"
Nicolas De Loof0ef5a622016-05-27 19:14:29 +020096
Charles Duffy3eec42c2016-09-20 12:11:33 -050097 IFS=',' read -r -a array <<< "$dependencies"
apotterebbd13d02016-06-23 12:24:15 -040098
Carlos Sanchezc0f63792016-08-15 10:30:16 +020099 for d in "${array[@]}"
100 do
101 plugin="$(cut -d':' -f1 - <<< "$d")"
102 if [[ $d == *"resolution:=optional"* ]]; then
103 echo "Skipping optional dependency $plugin"
104 else
105 local pluginInstalled
106 if pluginInstalled="$(echo "${bundledPlugins}" | grep "^${plugin}:")"; then
107 pluginInstalled="${pluginInstalled//[$'\r']}"
108 local versionInstalled; versionInstalled=$(versionFromPlugin "${pluginInstalled}")
Carlos Sanchez119703c2016-08-15 10:59:54 +0200109 local minVersion; minVersion=$(versionFromPlugin "${d}")
110 if versionLT "${versionInstalled}" "${minVersion}"; then
111 echo "Upgrading bundled dependency $d ($minVersion > $versionInstalled)"
112 download "$plugin" &
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200113 else
Carlos Sanchez119703c2016-08-15 10:59:54 +0200114 echo "Skipping already bundled dependency $d ($minVersion <= $versionInstalled)"
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200115 fi
116 else
Carlos Sanchez119703c2016-08-15 10:59:54 +0200117 download "$plugin" &
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200118 fi
119 fi
120 done
121 wait
Nicolas De Loof0ef5a622016-05-27 19:14:29 +0200122}
123
Charles Duffy3eec42c2016-09-20 12:11:33 -0500124bundledPlugins() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200125 local JENKINS_WAR=/usr/share/jenkins/jenkins.war
126 if [ -f $JENKINS_WAR ]
127 then
128 TEMP_PLUGIN_DIR=/tmp/plugintemp.$$
129 for i in $(jar tf $JENKINS_WAR | egrep '[^detached-]plugins.*\..pi' | sort)
130 do
131 rm -fr $TEMP_PLUGIN_DIR
132 mkdir -p $TEMP_PLUGIN_DIR
133 PLUGIN=$(basename "$i"|cut -f1 -d'.')
134 (cd $TEMP_PLUGIN_DIR;jar xf "$JENKINS_WAR" "$i";jar xvf "$TEMP_PLUGIN_DIR/$i" META-INF/MANIFEST.MF >/dev/null 2>&1)
135 VER=$(egrep -i Plugin-Version "$TEMP_PLUGIN_DIR/META-INF/MANIFEST.MF"|cut -d: -f2|sed 's/ //')
136 echo "$PLUGIN:$VER"
137 done
138 rm -fr $TEMP_PLUGIN_DIR
139 else
140 rm -f "$TEMP_ALREADY_INSTALLED"
141 echo "ERROR file not found: $JENKINS_WAR"
142 exit 1
143 fi
Carlos Sancheze1b99f42016-07-06 14:22:39 +0200144}
145
Charles Duffy3eec42c2016-09-20 12:11:33 -0500146versionFromPlugin() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200147 local plugin=$1
148 if [[ $plugin =~ .*:.* ]]; then
149 echo "${plugin##*:}"
150 else
151 echo "latest"
152 fi
Carlos Sancheze1b99f42016-07-06 14:22:39 +0200153
154}
155
Charles Duffy3eec42c2016-09-20 12:11:33 -0500156installedPlugins() {
Carlos Sanchezb5ae0c52016-08-15 11:38:24 +0200157 for f in "$REF_DIR"/*.jpi; do
158 echo "$(basename "$f" | sed -e 's/\.jpi//'):$(get_plugin_version "$f")"
159 done
160}
161
apotterebbd13d02016-06-23 12:24:15 -0400162main() {
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200163 local plugin version
Sýlvan Heuserb20f3882016-06-01 15:47:38 +0200164
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200165 mkdir -p "$REF_DIR" || exit 1
Nicolas De Loofa7a34c32016-05-30 09:10:58 +0200166
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200167 # Create lockfile manually before first run to make sure any explicit version set is used.
168 echo "Creating initial locks..."
169 for plugin in "$@"; do
170 mkdir "$(getLockFile "${plugin%%:*}")"
171 done
apotterebbd13d02016-06-23 12:24:15 -0400172
Carlos Sanchez2fb06842016-10-06 14:13:05 -0700173 echo "Analyzing war..."
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200174 bundledPlugins="$(bundledPlugins)"
Carlos Sancheze1b99f42016-07-06 14:22:39 +0200175
Carlos Sanchez2fb06842016-10-06 14:13:05 -0700176 echo "Downloading plugins..."
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200177 for plugin in "$@"; do
178 version=""
apotterebbd13d02016-06-23 12:24:15 -0400179
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200180 if [[ $plugin =~ .*:.* ]]; then
181 version=$(versionFromPlugin "${plugin}")
182 plugin="${plugin%%:*}"
183 fi
apotterebbd13d02016-06-23 12:24:15 -0400184
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200185 download "$plugin" "$version" "true" &
186 done
187 wait
apotterebbd13d02016-06-23 12:24:15 -0400188
Carlos Sanchezb5ae0c52016-08-15 11:38:24 +0200189 echo
190 echo "WAR bundled plugins:"
191 echo "${bundledPlugins}"
192 echo
193 echo "Installed plugins:"
194 installedPlugins
195
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200196 if [[ -f $FAILED ]]; then
Carlos Sanchez2fb06842016-10-06 14:13:05 -0700197 echo "Some plugins failed to download!" "$(<"$FAILED")" >&2
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200198 exit 1
199 fi
apotterebbd13d02016-06-23 12:24:15 -0400200
Carlos Sanchez2fb06842016-10-06 14:13:05 -0700201 echo "Cleaning up locks"
Carlos Sanchezc0f63792016-08-15 10:30:16 +0200202 rm -r "$REF_DIR"/*.lock
apotterebbd13d02016-06-23 12:24:15 -0400203}
204
Brian Antonelli6706b262016-06-24 06:31:54 -0400205main "$@"