Carlos Sanchez | 7d165ac | 2016-08-14 11:13:12 +0200 | [diff] [blame] | 1 | #!/bin/bash -eu |
Nicolas De Loof | 0ef5a62 | 2016-05-27 19:14:29 +0200 | [diff] [blame] | 2 | |
Sýlvan Heuser | b20f388 | 2016-06-01 15:47:38 +0200 | [diff] [blame] | 3 | # 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 Sanchez | 3a83b9d | 2016-08-08 09:36:28 +0200 | [diff] [blame] | 8 | set -o pipefail |
| 9 | |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 10 | REF_DIR=${REF:-/usr/share/jenkins/ref/plugins} |
| 11 | FAILED="$REF_DIR/failed-plugins.txt" |
Sýlvan Heuser | b20f388 | 2016-06-01 15:47:38 +0200 | [diff] [blame] | 12 | |
Vincent Latombe | c14af95 | 2016-07-18 10:20:12 +0200 | [diff] [blame] | 13 | . /usr/local/bin/jenkins-support |
| 14 | |
Charles Duffy | 3eec42c | 2016-09-20 12:11:33 -0500 | [diff] [blame] | 15 | getLockFile() { |
| 16 | printf '%s' "$REF_DIR/${1}.lock" |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 17 | } |
| 18 | |
Charles Duffy | 3eec42c | 2016-09-20 12:11:33 -0500 | [diff] [blame] | 19 | getArchiveFilename() { |
| 20 | printf '%s' "$REF_DIR/${1}.jpi" |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 21 | } |
Sýlvan Heuser | b20f388 | 2016-06-01 15:47:38 +0200 | [diff] [blame] | 22 | |
Charles Duffy | 3eec42c | 2016-09-20 12:11:33 -0500 | [diff] [blame] | 23 | download() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 24 | local plugin originalPlugin version lock ignoreLockFile |
| 25 | plugin="$1" |
| 26 | version="${2:-latest}" |
| 27 | ignoreLockFile="${3:-}" |
| 28 | lock="$(getLockFile "$plugin")" |
Nicolas De Loof | 0ef5a62 | 2016-05-27 19:14:29 +0200 | [diff] [blame] | 29 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 30 | 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 Loof | a7a34c3 | 2016-05-30 09:10:58 +0200 | [diff] [blame] | 42 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 43 | 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 |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 48 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 49 | resolveDependencies "$plugin" |
| 50 | fi |
Nicolas De Loof | 0ef5a62 | 2016-05-27 19:14:29 +0200 | [diff] [blame] | 51 | } |
| 52 | |
Charles Duffy | 3eec42c | 2016-09-20 12:11:33 -0500 | [diff] [blame] | 53 | doDownload() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 54 | local plugin version url jpi |
| 55 | plugin="$1" |
| 56 | version="$2" |
| 57 | jpi="$(getArchiveFilename "$plugin")" |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 58 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 59 | # 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 |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 64 | |
Carlos Sanchez | 0d167af | 2016-08-29 11:02:57 +0200 | [diff] [blame] | 65 | JENKINS_UC_DOWNLOAD=${JENKINS_UC_DOWNLOAD:-"$JENKINS_UC/download"} |
Jean-Louis Boudart | ad0ff9c | 2016-08-22 09:00:30 +0200 | [diff] [blame] | 66 | |
| 67 | url="$JENKINS_UC_DOWNLOAD/plugins/$plugin/$version/${plugin}.hpi" |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 68 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 69 | echo "Downloading plugin: $plugin from $url" |
Carlos Sanchez | 21b0f37 | 2016-10-06 13:26:17 -0700 | [diff] [blame] | 70 | 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 Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 71 | return $? |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 72 | } |
| 73 | |
Charles Duffy | 3eec42c | 2016-09-20 12:11:33 -0500 | [diff] [blame] | 74 | checkIntegrity() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 75 | local plugin jpi |
| 76 | plugin="$1" |
| 77 | jpi="$(getArchiveFilename "$plugin")" |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 78 | |
Gareth Harcombe-Minson | d6a7512 | 2016-09-26 09:59:36 -0500 | [diff] [blame] | 79 | unzip -t -qq "$jpi" >/dev/null |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 80 | return $? |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 81 | } |
| 82 | |
Charles Duffy | 3eec42c | 2016-09-20 12:11:33 -0500 | [diff] [blame] | 83 | resolveDependencies() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 84 | local plugin jpi dependencies |
| 85 | plugin="$1" |
| 86 | jpi="$(getArchiveFilename "$plugin")" |
Nicolas De Loof | 0ef5a62 | 2016-05-27 19:14:29 +0200 | [diff] [blame] | 87 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 88 | 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 Loof | 0ef5a62 | 2016-05-27 19:14:29 +0200 | [diff] [blame] | 89 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 90 | if [[ ! $dependencies ]]; then |
| 91 | echo " > $plugin has no dependencies" |
| 92 | return |
| 93 | fi |
Nicolas De Loof | 0ef5a62 | 2016-05-27 19:14:29 +0200 | [diff] [blame] | 94 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 95 | echo " > $plugin depends on $dependencies" |
Nicolas De Loof | 0ef5a62 | 2016-05-27 19:14:29 +0200 | [diff] [blame] | 96 | |
Charles Duffy | 3eec42c | 2016-09-20 12:11:33 -0500 | [diff] [blame] | 97 | IFS=',' read -r -a array <<< "$dependencies" |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 98 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 99 | 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 Sanchez | 119703c | 2016-08-15 10:59:54 +0200 | [diff] [blame] | 109 | local minVersion; minVersion=$(versionFromPlugin "${d}") |
| 110 | if versionLT "${versionInstalled}" "${minVersion}"; then |
| 111 | echo "Upgrading bundled dependency $d ($minVersion > $versionInstalled)" |
| 112 | download "$plugin" & |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 113 | else |
Carlos Sanchez | 119703c | 2016-08-15 10:59:54 +0200 | [diff] [blame] | 114 | echo "Skipping already bundled dependency $d ($minVersion <= $versionInstalled)" |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 115 | fi |
| 116 | else |
Carlos Sanchez | 119703c | 2016-08-15 10:59:54 +0200 | [diff] [blame] | 117 | download "$plugin" & |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 118 | fi |
| 119 | fi |
| 120 | done |
| 121 | wait |
Nicolas De Loof | 0ef5a62 | 2016-05-27 19:14:29 +0200 | [diff] [blame] | 122 | } |
| 123 | |
Charles Duffy | 3eec42c | 2016-09-20 12:11:33 -0500 | [diff] [blame] | 124 | bundledPlugins() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 125 | 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 Sanchez | e1b99f4 | 2016-07-06 14:22:39 +0200 | [diff] [blame] | 144 | } |
| 145 | |
Charles Duffy | 3eec42c | 2016-09-20 12:11:33 -0500 | [diff] [blame] | 146 | versionFromPlugin() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 147 | local plugin=$1 |
| 148 | if [[ $plugin =~ .*:.* ]]; then |
| 149 | echo "${plugin##*:}" |
| 150 | else |
| 151 | echo "latest" |
| 152 | fi |
Carlos Sanchez | e1b99f4 | 2016-07-06 14:22:39 +0200 | [diff] [blame] | 153 | |
| 154 | } |
| 155 | |
Charles Duffy | 3eec42c | 2016-09-20 12:11:33 -0500 | [diff] [blame] | 156 | installedPlugins() { |
Carlos Sanchez | b5ae0c5 | 2016-08-15 11:38:24 +0200 | [diff] [blame] | 157 | for f in "$REF_DIR"/*.jpi; do |
| 158 | echo "$(basename "$f" | sed -e 's/\.jpi//'):$(get_plugin_version "$f")" |
| 159 | done |
| 160 | } |
| 161 | |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 162 | main() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 163 | local plugin version |
Sýlvan Heuser | b20f388 | 2016-06-01 15:47:38 +0200 | [diff] [blame] | 164 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 165 | mkdir -p "$REF_DIR" || exit 1 |
Nicolas De Loof | a7a34c3 | 2016-05-30 09:10:58 +0200 | [diff] [blame] | 166 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 167 | # 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 |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 172 | |
Carlos Sanchez | 2fb0684 | 2016-10-06 14:13:05 -0700 | [diff] [blame] | 173 | echo "Analyzing war..." |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 174 | bundledPlugins="$(bundledPlugins)" |
Carlos Sanchez | e1b99f4 | 2016-07-06 14:22:39 +0200 | [diff] [blame] | 175 | |
Carlos Sanchez | 2fb0684 | 2016-10-06 14:13:05 -0700 | [diff] [blame] | 176 | echo "Downloading plugins..." |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 177 | for plugin in "$@"; do |
| 178 | version="" |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 179 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 180 | if [[ $plugin =~ .*:.* ]]; then |
| 181 | version=$(versionFromPlugin "${plugin}") |
| 182 | plugin="${plugin%%:*}" |
| 183 | fi |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 184 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 185 | download "$plugin" "$version" "true" & |
| 186 | done |
| 187 | wait |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 188 | |
Carlos Sanchez | b5ae0c5 | 2016-08-15 11:38:24 +0200 | [diff] [blame] | 189 | echo |
| 190 | echo "WAR bundled plugins:" |
| 191 | echo "${bundledPlugins}" |
| 192 | echo |
| 193 | echo "Installed plugins:" |
| 194 | installedPlugins |
| 195 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 196 | if [[ -f $FAILED ]]; then |
Carlos Sanchez | 2fb0684 | 2016-10-06 14:13:05 -0700 | [diff] [blame] | 197 | echo "Some plugins failed to download!" "$(<"$FAILED")" >&2 |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 198 | exit 1 |
| 199 | fi |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 200 | |
Carlos Sanchez | 2fb0684 | 2016-10-06 14:13:05 -0700 | [diff] [blame] | 201 | echo "Cleaning up locks" |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 202 | rm -r "$REF_DIR"/*.lock |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 203 | } |
| 204 | |
Brian Antonelli | 6706b26 | 2016-06-24 06:31:54 -0400 | [diff] [blame] | 205 | main "$@" |