mirror of
https://github.com/jenkinsci/kubernetes-operator.git
synced 2026-09-30 05:01:10 +02:00
feat(operator): several updates (#806)
- prepare to switch from `master` to `main` - avoid to run workflow in case is not needed - add a way to bump the lts via make - use latest jenkins lts 2.387.1 - add the docker labels - update base plugins - fix #797 - Add more tests with bats - Update base plugin to latest version - Temporary revert #807 - Better nightly job
This commit is contained in:
@@ -36,8 +36,7 @@ func (r *JenkinsBaseConfigurationReconciler) verifyPlugins(jenkinsClient jenkins
|
||||
continue
|
||||
}
|
||||
if found, ok := isPluginVersionCompatible(allPluginsInJenkins, plugin); !ok {
|
||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("Incompatible plugin '%s' version, actual '%+v'", plugin, found.Version))
|
||||
status = false
|
||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("The plugin you specified as code is incompatible with this jenkins version: plugin '%s' version, actual '%+v'", plugin, found.Version))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ func TestJenkinsBaseConfigurationReconciler_verifyPlugins(t *testing.T) {
|
||||
got, err := r.verifyPlugins(jenkinsClient)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, got)
|
||||
assert.True(t, got)
|
||||
})
|
||||
t.Run("plugin version matter for user plugins", func(t *testing.T) {
|
||||
jenkins := &v1alpha2.Jenkins{
|
||||
@@ -377,7 +377,7 @@ func TestJenkinsBaseConfigurationReconciler_verifyPlugins(t *testing.T) {
|
||||
got, err := r.verifyPlugins(jenkinsClient)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, got)
|
||||
assert.True(t, got)
|
||||
})
|
||||
t.Run("missing base plugin", func(t *testing.T) {
|
||||
jenkins := &v1alpha2.Jenkins{
|
||||
|
||||
@@ -14,307 +14,6 @@ import (
|
||||
|
||||
const installPluginsCommand = "jenkins-plugin-cli"
|
||||
|
||||
// bash scripts installs single jenkins plugin with specific version
|
||||
const installPluginsBashScript = `#!/bin/bash -eu
|
||||
|
||||
# Resolve dependencies and download plugins given on the command line
|
||||
#
|
||||
# FROM jenkins
|
||||
# RUN install-plugins.sh docker-slaves github-branch-source
|
||||
#
|
||||
# Environment variables:
|
||||
# REF: directory with preinstalled plugins. Default: /usr/share/jenkins/ref/plugins
|
||||
# JENKINS_WAR: full path to the jenkins.war. Default: /usr/share/jenkins/jenkins.war
|
||||
# JENKINS_UC: url of the Update Center. Default: ""
|
||||
# JENKINS_UC_EXPERIMENTAL: url of the Experimental Update Center for experimental versions of plugins. Default: ""
|
||||
# JENKINS_INCREMENTALS_REPO_MIRROR: url of the incrementals repo mirror. Default: ""
|
||||
# JENKINS_UC_DOWNLOAD: download url of the Update Center. Default: JENKINS_UC/download
|
||||
# CURL_OPTIONS When downloading the plugins with curl. Curl options. Default: -sSfL
|
||||
# CURL_CONNECTION_TIMEOUT When downloading the plugins with curl. <seconds> Maximum time allowed for connection. Default: 20
|
||||
# CURL_RETRY When downloading the plugins with curl. Retry request if transient problems occur. Default: 3
|
||||
# CURL_RETRY_DELAY When downloading the plugins with curl. <seconds> Wait time between retries. Default: 0
|
||||
# CURL_RETRY_MAX_TIME When downloading the plugins with curl. <seconds> Retry only within this period. Default: 60
|
||||
|
||||
set -o pipefail
|
||||
|
||||
echo "WARN: install-plugins.sh is deprecated, please switch to jenkins-plugin-cli"
|
||||
|
||||
JENKINS_WAR=${JENKINS_WAR:-/usr/share/jenkins/jenkins.war}
|
||||
|
||||
. /usr/local/bin/jenkins-support
|
||||
|
||||
REF_DIR="${REF}/plugins"
|
||||
FAILED="$REF_DIR/failed-plugins.txt"
|
||||
|
||||
getLockFile() {
|
||||
printf '%s' "$REF_DIR/${1}.lock"
|
||||
}
|
||||
|
||||
getArchiveFilename() {
|
||||
printf '%s' "$REF_DIR/${1}.jpi"
|
||||
}
|
||||
|
||||
download() {
|
||||
local plugin originalPlugin version lock ignoreLockFile url
|
||||
plugin="$1"
|
||||
version="${2:-latest}"
|
||||
ignoreLockFile="${3:-}"
|
||||
url="${4:-}"
|
||||
lock="$(getLockFile "$plugin")"
|
||||
|
||||
if [[ $ignoreLockFile ]] || mkdir "$lock" &>/dev/null; then
|
||||
if ! doDownload "$plugin" "$version" "$url"; then
|
||||
# some plugin don't follow the rules about artifact ID
|
||||
# typically: docker-plugin
|
||||
originalPlugin="$plugin"
|
||||
plugin="${plugin}-plugin"
|
||||
if ! doDownload "$plugin" "$version" "$url"; then
|
||||
echo "Failed to download plugin: $originalPlugin or $plugin" >&2
|
||||
echo "Not downloaded: ${originalPlugin}" >> "$FAILED"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! checkIntegrity "$plugin"; then
|
||||
echo "Downloaded file is not a valid ZIP: $(getArchiveFilename "$plugin")" >&2
|
||||
echo "Download integrity: ${plugin}" >> "$FAILED"
|
||||
rm $(getArchiveFilename "$plugin")
|
||||
return 1
|
||||
fi
|
||||
|
||||
resolveDependencies "$plugin"
|
||||
fi
|
||||
}
|
||||
|
||||
doDownload() {
|
||||
local plugin version url jpi
|
||||
plugin="$1"
|
||||
version="$2"
|
||||
url="$3"
|
||||
jpi="$(getArchiveFilename "$plugin")"
|
||||
|
||||
# If plugin already exists and is the same version do not download
|
||||
if test -f "$jpi" && unzip -p "$jpi" META-INF/MANIFEST.MF | tr -d '\r' | grep "^Plugin-Version: ${version}$" > /dev/null; then
|
||||
echo "Using provided plugin: $plugin"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -n $url ]] ; then
|
||||
echo "Will use url=$url"
|
||||
elif [[ "$version" == "latest" && -n "$JENKINS_UC_LATEST" ]]; then
|
||||
# If version-specific Update Center is available, which is the case for LTS versions,
|
||||
# use it to resolve latest versions.
|
||||
url="$JENKINS_UC_LATEST/latest/${plugin}.hpi"
|
||||
elif [[ "$version" == "experimental" && -n "$JENKINS_UC_EXPERIMENTAL" ]]; then
|
||||
# Download from the experimental update center
|
||||
url="$JENKINS_UC_EXPERIMENTAL/latest/${plugin}.hpi"
|
||||
elif [[ "$version" == incrementals* ]] ; then
|
||||
# Download from Incrementals repo: https://jenkins.io/blog/2018/05/15/incremental-deployment/
|
||||
# Example URL: https://repo.jenkins-ci.org/incrementals/org/jenkins-ci/plugins/workflow/workflow-support/2.19-rc289.d09828a05a74/workflow-support-2.19-rc289.d09828a05a74.hpi
|
||||
local groupId incrementalsVersion
|
||||
# add a trailing ; so the \n gets added to the end
|
||||
readarray -t "-d;" arrIN <<<"${version};";
|
||||
unset 'arrIN[-1]';
|
||||
groupId=${arrIN[1]}
|
||||
incrementalsVersion=${arrIN[2]}
|
||||
url="${JENKINS_INCREMENTALS_REPO_MIRROR}/$(echo "${groupId}" | tr '.' '/')/${plugin}/${incrementalsVersion}/${plugin}-${incrementalsVersion}.hpi"
|
||||
else
|
||||
JENKINS_UC_DOWNLOAD=${JENKINS_UC_DOWNLOAD:-"$JENKINS_UC/download"}
|
||||
url="$JENKINS_UC_DOWNLOAD/plugins/$plugin/$version/${plugin}.hpi"
|
||||
fi
|
||||
|
||||
echo "Downloading plugin: $plugin from $url"
|
||||
# We actually want to allow variable value to be split into multiple options passed to curl.
|
||||
# This is needed to allow long options and any options that take value.
|
||||
# shellcheck disable=SC2086
|
||||
retry_command curl ${CURL_OPTIONS:--sSfL} --connect-timeout "${CURL_CONNECTION_TIMEOUT:-20}" --retry "${CURL_RETRY:-3}" --retry-delay "${CURL_RETRY_DELAY:-0}" --retry-max-time "${CURL_RETRY_MAX_TIME:-60}" "$url" -o "$jpi"
|
||||
return $?
|
||||
}
|
||||
|
||||
checkIntegrity() {
|
||||
local plugin jpi
|
||||
plugin="$1"
|
||||
jpi="$(getArchiveFilename "$plugin")"
|
||||
|
||||
unzip -t -qq "$jpi" >/dev/null
|
||||
return $?
|
||||
}
|
||||
|
||||
resolveDependencies() {
|
||||
local plugin jpi dependencies
|
||||
plugin="$1"
|
||||
jpi="$(getArchiveFilename "$plugin")"
|
||||
|
||||
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: ##')"
|
||||
|
||||
if [[ ! $dependencies ]]; then
|
||||
echo " > $plugin has no dependencies"
|
||||
return
|
||||
fi
|
||||
|
||||
echo " > $plugin depends on $dependencies"
|
||||
|
||||
IFS=',' read -r -a array <<< "$dependencies"
|
||||
|
||||
for d in "${array[@]}"
|
||||
do
|
||||
plugin="$(cut -d':' -f1 - <<< "$d")"
|
||||
if [[ $d == *"resolution:=optional"* ]]; then
|
||||
echo "Skipping optional dependency $plugin"
|
||||
else
|
||||
local pluginInstalled
|
||||
if pluginInstalled="$(echo -e "${bundledPlugins}\n${installedPlugins}" | grep "^${plugin}:")"; then
|
||||
pluginInstalled="${pluginInstalled//[$'\r']}"
|
||||
local versionInstalled; versionInstalled=$(versionFromPlugin "${pluginInstalled}")
|
||||
local minVersion; minVersion=$(versionFromPlugin "${d}")
|
||||
if versionLT "${versionInstalled}" "${minVersion}"; then
|
||||
echo "Upgrading bundled dependency $d ($minVersion > $versionInstalled)"
|
||||
download "$plugin" &
|
||||
else
|
||||
echo "Skipping already installed dependency $d ($minVersion <= $versionInstalled)"
|
||||
fi
|
||||
else
|
||||
download "$plugin" &
|
||||
fi
|
||||
fi
|
||||
done
|
||||
wait
|
||||
}
|
||||
|
||||
bundledPlugins() {
|
||||
if [ -f "$JENKINS_WAR" ]
|
||||
then
|
||||
TEMP_PLUGIN_DIR=/tmp/plugintemp.$$
|
||||
for i in $(jar tf "$JENKINS_WAR" | grep -E '[^detached-]plugins.*\..pi' | sort)
|
||||
do
|
||||
rm -fr $TEMP_PLUGIN_DIR
|
||||
mkdir -p $TEMP_PLUGIN_DIR
|
||||
PLUGIN=$(basename "$i"|cut -f1 -d'.')
|
||||
(cd $TEMP_PLUGIN_DIR;jar xf "$JENKINS_WAR" "$i";jar xvf "$TEMP_PLUGIN_DIR/$i" META-INF/MANIFEST.MF >/dev/null 2>&1)
|
||||
VER=$(grep -E -i Plugin-Version "$TEMP_PLUGIN_DIR/META-INF/MANIFEST.MF"|cut -d: -f2|sed 's/ //')
|
||||
echo "$PLUGIN:$VER"
|
||||
done
|
||||
rm -fr $TEMP_PLUGIN_DIR
|
||||
else
|
||||
echo "war not found, installing all plugins: $JENKINS_WAR"
|
||||
fi
|
||||
}
|
||||
|
||||
versionFromPlugin() {
|
||||
local plugin=$1
|
||||
if [[ $plugin =~ .*:.* ]]; then
|
||||
echo "${plugin##*:}"
|
||||
else
|
||||
echo "latest"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
installedPlugins() {
|
||||
for f in "$REF_DIR"/*.jpi; do
|
||||
echo "$(basename "$f" | sed -e 's/\.jpi//'):$(get_plugin_version "$f")"
|
||||
done
|
||||
}
|
||||
|
||||
jenkinsMajorMinorVersion() {
|
||||
if [[ -f "$JENKINS_WAR" ]]; then
|
||||
local version major minor
|
||||
version="$(java -jar "$JENKINS_WAR" --version)"
|
||||
major="$(echo "$version" | cut -d '.' -f 1)"
|
||||
minor="$(echo "$version" | cut -d '.' -f 2)"
|
||||
echo "$major.$minor"
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
local plugin jenkinsVersion
|
||||
local plugins=()
|
||||
|
||||
mkdir -p "$REF_DIR" || exit 1
|
||||
rm -f "$FAILED"
|
||||
|
||||
echo "Cleaning up locks"
|
||||
find "$REF_DIR" -regex ".*.lock" | while read -r filepath; do
|
||||
rm -r "$filepath"
|
||||
done
|
||||
|
||||
# Read plugins from stdin or from the command line arguments
|
||||
if [[ ($# -eq 0) ]]; then
|
||||
while read -r line || [ "$line" != "" ]; do
|
||||
# Remove leading/trailing spaces, comments, and empty lines
|
||||
plugin=$(echo "${line}" | tr -d '\r' | sed -e 's/^[ \t]*//g' -e 's/[ \t]*$//g' -e 's/[ \t]*#.*$//g' -e '/^[ \t]*$/d')
|
||||
|
||||
# Avoid adding empty plugin into array
|
||||
if [ ${#plugin} -ne 0 ]; then
|
||||
plugins+=("${plugin}")
|
||||
fi
|
||||
done
|
||||
else
|
||||
plugins=("$@")
|
||||
fi
|
||||
|
||||
# Create lockfile manually before first run to make sure any explicit version set is used.
|
||||
echo "Creating initial locks..."
|
||||
for plugin in "${plugins[@]}"; do
|
||||
mkdir "$(getLockFile "${plugin%%:*}")"
|
||||
done
|
||||
|
||||
echo "Analyzing war $JENKINS_WAR..."
|
||||
bundledPlugins="$(bundledPlugins)"
|
||||
|
||||
echo "Registering preinstalled plugins..."
|
||||
installedPlugins="$(installedPlugins)"
|
||||
|
||||
# Get the update center URL based on the jenkins version
|
||||
jenkinsVersion="$(jenkinsMajorMinorVersion)"
|
||||
# shellcheck disable=SC2086
|
||||
jenkinsUcJson=$(curl ${CURL_OPTIONS:--sSfL} -o /dev/null -w "%{url_effective}" "${JENKINS_UC}/update-center.json?version=${jenkinsVersion}")
|
||||
if [ -n "${jenkinsUcJson}" ]; then
|
||||
JENKINS_UC_LATEST=${jenkinsUcJson//update-center.json/}
|
||||
echo "Using version-specific update center: $JENKINS_UC_LATEST..."
|
||||
else
|
||||
JENKINS_UC_LATEST=
|
||||
fi
|
||||
|
||||
echo "Downloading plugins..."
|
||||
for plugin in "${plugins[@]}"; do
|
||||
local reg='^([^:]+):?([^:]+)?:?([^:]+)?:?(http.+)?'
|
||||
if [[ $plugin =~ $reg ]]; then
|
||||
local pluginId="${BASH_REMATCH[1]}"
|
||||
local version="${BASH_REMATCH[2]}"
|
||||
local lock="${BASH_REMATCH[3]}"
|
||||
local url="${BASH_REMATCH[4]}"
|
||||
download "$pluginId" "$version" "${lock:-true}" "${url}" &
|
||||
else
|
||||
echo "Skipping the line '${plugin}' as it does not look like a reference to a plugin"
|
||||
fi
|
||||
done
|
||||
wait
|
||||
|
||||
echo
|
||||
echo "WAR bundled plugins:"
|
||||
echo "${bundledPlugins}"
|
||||
echo
|
||||
echo "Installed plugins:"
|
||||
installedPlugins
|
||||
|
||||
if [[ -f $FAILED ]]; then
|
||||
echo "Some plugins failed to download!" "$(<"$FAILED")" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Cleaning up locks"
|
||||
find "$REF_DIR" -regex ".*.lock" | while read -r filepath; do
|
||||
rm -r "$filepath"
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
main "$@"
|
||||
`
|
||||
|
||||
var initBashTemplate = template.Must(template.New(InitScriptName).Parse(`#!/usr/bin/env bash
|
||||
set -e
|
||||
set -x
|
||||
@@ -347,7 +46,7 @@ cat > {{ .JenkinsHomePath }}/base-plugins.txt << EOF
|
||||
{{ end }}
|
||||
EOF
|
||||
|
||||
{{ $installPluginsCommand }} --verbose -f {{ .JenkinsHomePath }}/base-plugins.txt
|
||||
{{ $installPluginsCommand }} --verbose --latest {{ .LatestPlugins }} -f {{ .JenkinsHomePath }}/base-plugins.txt
|
||||
echo "Installing plugins required by Operator - end"
|
||||
|
||||
echo "Installing plugins required by user - begin"
|
||||
@@ -357,7 +56,7 @@ cat > {{ .JenkinsHomePath }}/user-plugins.txt << EOF
|
||||
{{ end }}
|
||||
EOF
|
||||
|
||||
{{ $installPluginsCommand }} --verbose -f {{ .JenkinsHomePath }}/user-plugins.txt
|
||||
{{ $installPluginsCommand }} --verbose --latest {{ .LatestPlugins }} -f {{ .JenkinsHomePath }}/user-plugins.txt
|
||||
echo "Installing plugins required by user - end"
|
||||
`))
|
||||
|
||||
@@ -369,6 +68,13 @@ func buildConfigMapTypeMeta() metav1.TypeMeta {
|
||||
}
|
||||
|
||||
func buildInitBashScript(jenkins *v1alpha2.Jenkins) (*string, error) {
|
||||
defaultlatestPlugin := true
|
||||
|
||||
latestP := jenkins.Spec.Master.LatestPlugins
|
||||
if !latestP {
|
||||
latestP = defaultlatestPlugin
|
||||
}
|
||||
|
||||
data := struct {
|
||||
JenkinsHomePath string
|
||||
InitConfigurationPath string
|
||||
@@ -376,6 +82,7 @@ func buildInitBashScript(jenkins *v1alpha2.Jenkins) (*string, error) {
|
||||
JenkinsScriptsVolumePath string
|
||||
BasePlugins []v1alpha2.Plugin
|
||||
UserPlugins []v1alpha2.Plugin
|
||||
LatestPlugins bool
|
||||
}{
|
||||
JenkinsHomePath: getJenkinsHomePath(jenkins),
|
||||
InitConfigurationPath: jenkinsInitConfigurationVolumePath,
|
||||
@@ -383,6 +90,7 @@ func buildInitBashScript(jenkins *v1alpha2.Jenkins) (*string, error) {
|
||||
UserPlugins: jenkins.Spec.Master.Plugins,
|
||||
InstallPluginsCommand: installPluginsCommand,
|
||||
JenkinsScriptsVolumePath: JenkinsScriptsVolumePath,
|
||||
LatestPlugins: latestP,
|
||||
}
|
||||
|
||||
output, err := render.Render(initBashTemplate, data)
|
||||
@@ -410,8 +118,7 @@ func NewScriptsConfigMap(meta metav1.ObjectMeta, jenkins *v1alpha2.Jenkins) (*co
|
||||
TypeMeta: buildConfigMapTypeMeta(),
|
||||
ObjectMeta: meta,
|
||||
Data: map[string]string{
|
||||
InitScriptName: *initBashScript,
|
||||
installPluginsCommand: installPluginsBashScript,
|
||||
InitScriptName: *initBashScript,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ package plugins
|
||||
const (
|
||||
configurationAsCodePlugin = "configuration-as-code:1569.vb_72405b_80249"
|
||||
gitPlugin = "git:5.0.0"
|
||||
jobDslPlugin = "job-dsl:1.81"
|
||||
kubernetesPlugin = "kubernetes:3883.v4d70a_a_a_df034"
|
||||
jobDslPlugin = "job-dsl:1.82"
|
||||
kubernetesPlugin = "kubernetes:3896.v19b_160fd9589"
|
||||
kubernetesCredentialsProviderPlugin = "kubernetes-credentials-provider:1.209.v862c6e5fb_1ef"
|
||||
workflowAggregatorPlugin = "workflow-aggregator:590.v6a_d052e5a_a_b_5"
|
||||
workflowJobPlugin = "workflow-job:1282.ve6d865025906"
|
||||
workflowAggregatorPlugin = "workflow-aggregator:596.v8c21c963d92d"
|
||||
workflowJobPlugin = "workflow-job:1284.v2fe8ed4573d4"
|
||||
)
|
||||
|
||||
// basePluginsList contains plugins to install by operator.
|
||||
|
||||
Reference in New Issue
Block a user