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 | |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 15 | function getLockFile() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 16 | echo -n "$REF_DIR/${1}.lock" |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 17 | } |
| 18 | |
Carlos Sanchez | 16ae24e | 2016-06-27 13:47:09 +0200 | [diff] [blame] | 19 | function getArchiveFilename() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 20 | echo -n "$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 | |
Nicolas De Loof | 0ef5a62 | 2016-05-27 19:14:29 +0200 | [diff] [blame] | 23 | function 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 | |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 53 | function 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 | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 65 | url="$JENKINS_UC/download/plugins/$plugin/$version/${plugin}.hpi" |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 66 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 67 | echo "Downloading plugin: $plugin from $url" |
| 68 | curl --connect-timeout 5 --retry 5 --retry-delay 0 --retry-max-time 60 -s -f -L "$url" -o "$jpi" |
| 69 | return $? |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 70 | } |
| 71 | |
| 72 | function checkIntegrity() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 73 | local plugin jpi |
| 74 | plugin="$1" |
| 75 | jpi="$(getArchiveFilename "$plugin")" |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 76 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 77 | zip -T "$jpi" >/dev/null |
| 78 | return $? |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 79 | } |
| 80 | |
Fredrik Kers | 96ceb54 | 2016-08-13 00:02:02 +0200 | [diff] [blame] | 81 | function resolveDependencies() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 82 | local plugin jpi dependencies |
| 83 | plugin="$1" |
| 84 | jpi="$(getArchiveFilename "$plugin")" |
Nicolas De Loof | 0ef5a62 | 2016-05-27 19:14:29 +0200 | [diff] [blame] | 85 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 86 | 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] | 87 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 88 | if [[ ! $dependencies ]]; then |
| 89 | echo " > $plugin has no dependencies" |
| 90 | return |
| 91 | fi |
Nicolas De Loof | 0ef5a62 | 2016-05-27 19:14:29 +0200 | [diff] [blame] | 92 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 93 | echo " > $plugin depends on $dependencies" |
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 | IFS=',' read -a array <<< "$dependencies" |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 96 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 97 | for d in "${array[@]}" |
| 98 | do |
| 99 | plugin="$(cut -d':' -f1 - <<< "$d")" |
| 100 | if [[ $d == *"resolution:=optional"* ]]; then |
| 101 | echo "Skipping optional dependency $plugin" |
| 102 | else |
| 103 | local pluginInstalled |
| 104 | if pluginInstalled="$(echo "${bundledPlugins}" | grep "^${plugin}:")"; then |
| 105 | pluginInstalled="${pluginInstalled//[$'\r']}" |
| 106 | local versionInstalled; versionInstalled=$(versionFromPlugin "${pluginInstalled}") |
Carlos Sanchez | 119703c | 2016-08-15 10:59:54 +0200 | [diff] [blame^] | 107 | local minVersion; minVersion=$(versionFromPlugin "${d}") |
| 108 | if versionLT "${versionInstalled}" "${minVersion}"; then |
| 109 | echo "Upgrading bundled dependency $d ($minVersion > $versionInstalled)" |
| 110 | download "$plugin" & |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 111 | else |
Carlos Sanchez | 119703c | 2016-08-15 10:59:54 +0200 | [diff] [blame^] | 112 | echo "Skipping already bundled dependency $d ($minVersion <= $versionInstalled)" |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 113 | fi |
| 114 | else |
Carlos Sanchez | 119703c | 2016-08-15 10:59:54 +0200 | [diff] [blame^] | 115 | download "$plugin" & |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 116 | fi |
| 117 | fi |
| 118 | done |
| 119 | wait |
Nicolas De Loof | 0ef5a62 | 2016-05-27 19:14:29 +0200 | [diff] [blame] | 120 | } |
| 121 | |
Carlos Sanchez | e1b99f4 | 2016-07-06 14:22:39 +0200 | [diff] [blame] | 122 | function bundledPlugins() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 123 | local JENKINS_WAR=/usr/share/jenkins/jenkins.war |
| 124 | if [ -f $JENKINS_WAR ] |
| 125 | then |
| 126 | TEMP_PLUGIN_DIR=/tmp/plugintemp.$$ |
| 127 | for i in $(jar tf $JENKINS_WAR | egrep '[^detached-]plugins.*\..pi' | sort) |
| 128 | do |
| 129 | rm -fr $TEMP_PLUGIN_DIR |
| 130 | mkdir -p $TEMP_PLUGIN_DIR |
| 131 | PLUGIN=$(basename "$i"|cut -f1 -d'.') |
| 132 | (cd $TEMP_PLUGIN_DIR;jar xf "$JENKINS_WAR" "$i";jar xvf "$TEMP_PLUGIN_DIR/$i" META-INF/MANIFEST.MF >/dev/null 2>&1) |
| 133 | VER=$(egrep -i Plugin-Version "$TEMP_PLUGIN_DIR/META-INF/MANIFEST.MF"|cut -d: -f2|sed 's/ //') |
| 134 | echo "$PLUGIN:$VER" |
| 135 | done |
| 136 | rm -fr $TEMP_PLUGIN_DIR |
| 137 | else |
| 138 | rm -f "$TEMP_ALREADY_INSTALLED" |
| 139 | echo "ERROR file not found: $JENKINS_WAR" |
| 140 | exit 1 |
| 141 | fi |
Carlos Sanchez | e1b99f4 | 2016-07-06 14:22:39 +0200 | [diff] [blame] | 142 | } |
| 143 | |
| 144 | function versionFromPlugin() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 145 | local plugin=$1 |
| 146 | if [[ $plugin =~ .*:.* ]]; then |
| 147 | echo "${plugin##*:}" |
| 148 | else |
| 149 | echo "latest" |
| 150 | fi |
Carlos Sanchez | e1b99f4 | 2016-07-06 14:22:39 +0200 | [diff] [blame] | 151 | |
| 152 | } |
| 153 | |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 154 | main() { |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 155 | local plugin version |
Sýlvan Heuser | b20f388 | 2016-06-01 15:47:38 +0200 | [diff] [blame] | 156 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 157 | mkdir -p "$REF_DIR" || exit 1 |
Nicolas De Loof | a7a34c3 | 2016-05-30 09:10:58 +0200 | [diff] [blame] | 158 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 159 | # Create lockfile manually before first run to make sure any explicit version set is used. |
| 160 | echo "Creating initial locks..." |
| 161 | for plugin in "$@"; do |
| 162 | mkdir "$(getLockFile "${plugin%%:*}")" |
| 163 | done |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 164 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 165 | echo -e "\nAnalyzing war..." |
| 166 | bundledPlugins="$(bundledPlugins)" |
Carlos Sanchez | e1b99f4 | 2016-07-06 14:22:39 +0200 | [diff] [blame] | 167 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 168 | echo -e "\nDownloading plugins..." |
| 169 | for plugin in "$@"; do |
| 170 | version="" |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 171 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 172 | if [[ $plugin =~ .*:.* ]]; then |
| 173 | version=$(versionFromPlugin "${plugin}") |
| 174 | plugin="${plugin%%:*}" |
| 175 | fi |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 176 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 177 | download "$plugin" "$version" "true" & |
| 178 | done |
| 179 | wait |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 180 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 181 | if [[ -f $FAILED ]]; then |
| 182 | echo -e "\nSome plugins failed to download!\n$(<"$FAILED")" >&2 |
| 183 | exit 1 |
| 184 | fi |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 185 | |
Carlos Sanchez | c0f6379 | 2016-08-15 10:30:16 +0200 | [diff] [blame] | 186 | echo -e "\nCleaning up locks" |
| 187 | rm -r "$REF_DIR"/*.lock |
apottere | bbd13d0 | 2016-06-23 12:24:15 -0400 | [diff] [blame] | 188 | } |
| 189 | |
Brian Antonelli | 6706b26 | 2016-06-24 06:31:54 -0400 | [diff] [blame] | 190 | main "$@" |