Skip to content

Instantly share code, notes, and snippets.

@pvdissel
Created February 24, 2015 09:29
Show Gist options
  • Save pvdissel/efe99cb84d93b8ad721c to your computer and use it in GitHub Desktop.
Save pvdissel/efe99cb84d93b8ad721c to your computer and use it in GitHub Desktop.
#!/bin/bash
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONTAINERS_DIR="${DIR}/.containers"
jenkinsVersion="1.580.2"
jenkinsPort="8080"
seedJobName="Seed"
dockerCmd="docker"
function updateGlobals() {
containerName="$(basename "${BASH_SOURCE[0]}")-${jenkinsPort}"
prefixCmd="sudo"
jenkinsUrl="http://localhost:${jenkinsPort}"
which boot2docker > /dev/null 2>&1
if [[ $? == 0 ]]; then
boot2dockerIp=$(boot2docker ip 2>/dev/null)
jenkinsUrl="http://${boot2dockerIp}:${jenkinsPort}"
prefixCmd=""
fi
containerDir="${CONTAINERS_DIR}/${containerName}"
jenkinsDir="${containerDir}/jenkins-home"
jenkinsUserHomeDir="${containerDir}/jenkins-root"
jenkinsJobsDir="${jenkinsDir}/jobs"
jenkinsPluginsDir="${jenkinsDir}/plugins"
pluginUrlsFilename="plugin-urls.txt"
pluginUrlsFile="${DIR}/${pluginUrlsFilename}"
backupPluginsDir="${DIR}/.jenkins-plugins"
backupPluginUrlsFile="${backupPluginsDir}/${pluginUrlsFilename}"
seedJobConfigFile="${DIR}/seed-job-config.xml"
}
function start() {
local projectPath="$1"
local volumes=("${jenkinsDir}:/var/jenkins_home")
volumes+=("${jenkinsUserHomeDir}:/root")
echo "Starting Jenkins..."
if [[ -n "${projectPath}" ]]; then
echo ">> Provided path to project [${projectPath}]"
if [[ ! "${projectPath}" == /* ]]; then
local originalProjectPath="${projectPath}"
projectPath="${DIR}/${projectPath}"
echo ">> Made relative path [${originalProjectPath}] absolute [${projectPath}]"
fi
if [[ -d "${projectPath}" ]]; then
echo " Will mount it to as read-only to [/source] within the container"
volumes+=("${projectPath}:/source:ro")
else
echo "!! Project path [${projectPath}] is not an existing directory"
exit 1
fi
else
echo "!! No project path provided"
echo -e
usage
exit 1
fi
removeContainer
if [[ ! -d "${backupPluginsDir}" || $(diff "${pluginUrlsFile}" "${backupPluginUrlsFile}" > /dev/null 2>&1; echo $?) -ne 0 ]]; then
echo ">> Downloading the plugins..."
wget --input-file "${pluginUrlsFile}" --directory-prefix "${backupPluginsDir}" --continue -nv
if [[ $? -ne 0 ]]; then
echo "!! Error during downloading of the plugins"
exit 1
fi
cp -f "${pluginUrlsFile}" "${backupPluginUrlsFile}"
removeDir "${jenkinsPluginsDir}"
fi
if [[ ! -d "${jenkinsPluginsDir}" ]]; then
echo ">> Copying plugins to Jenkins..."
${prefixCmd} mkdir -p "${jenkinsPluginsDir}"
${prefixCmd} cp -rf "${backupPluginsDir}/." "${jenkinsPluginsDir}/"
echo ">> Pinning plugins to not be overridden by Jenkins' defaults..."
for plugin in "${jenkinsPluginsDir}"/*.hpi; do
${prefixCmd} touch "${plugin}.pinned"
done
fi
fixJobsDirAccess
installSeedJob
echo "Starting [${containerName}] container..."
${dockerCmd} run -d -p ${jenkinsPort}:8080 --name ${containerName} -u root $(printf " -v %s" "${volumes[@]}") jenkins:${jenkinsVersion}
if [[ $? == 0 ]]; then
echo ">> Container [${containerName}] started"
else
echo "!! An error occurred while starting container [${containerName}]"
exit 1
fi
echo ">> Waiting for Jenkins to be fully up and loaded..."
until ${dockerCmd} logs ${containerName} 2>&1 | grep "Jenkins is fully up and running" > /dev/null; do
sleep 1s
done
triggerSeedJob
echo -e
echo "Jenkins is fully up and running at [${jenkinsUrl}]"
}
function fixJobsDirAccess() {
echo ">> Make Jobs directory accessable for current user..."
${prefixCmd} mkdir -p "${jenkinsJobsDir}"
${prefixCmd} chown -R $USER "${jenkinsJobsDir}"
}
function installSeedJob() {
echo ">> Creating [${seedJobName}] job..."
local seedJobDir="${jenkinsJobsDir}/${seedJobName}"
${prefixCmd} mkdir -p "${seedJobDir}"
${prefixCmd} cp -f "${seedJobConfigFile}" "${seedJobDir}/config.xml"
}
function triggerSeedJob() {
echo ">> Triggering a [${seedJobName}] Job build"
curl -X POST "${jenkinsUrl}/job/${seedJobName}/build"
}
function getPublicJenkinsPortOfContainer() {
${dockerCmd} inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $p | eq "8080/tcp"}}{{(index $conf 0).HostPort}}{{end}}{{end}}' ${containerName}
}
function status() {
${dockerCmd} ps -a ${containerName}
}
function stop() {
echo "Stopping container [${containerName}]..."
${dockerCmd} stop ${containerName} > /dev/null 2>&1
echo -e
echo "Stopped container [${containerName}]"
}
function clear() {
echo "Removing any existing jobs..."
removeDir "${jenkinsJobsDir}/"
fixJobsDirAccess
installSeedJob
echo ">> Triggering a Jenkins reload..."
jenkinsPort="$(getPublicJenkinsPortOfContainer)"
jenkinsUrl=$(eval echo ${jenkinsUrl})
curl -X POST "${jenkinsUrl}/reload"
until [[ $(curl -s -o /dev/null -w '%{http_code}' "${jenkinsUrl}") -eq 200 ]]; do
sleep 1s
done
triggerSeedJob
echo -e
echo "Done clearing"
}
function removeContainer() {
echo ">> Remove existing container called [${containerName}]"
${dockerCmd} rm -f ${containerName} > /dev/null 2>&1
}
function remove() {
echo "Removing Jenkins..."
removeContainer
echo ">> Removing Jenkins working directory [${jenkinsDir}]"
removeDir "${jenkinsDir}"
echo -e
echo "Done removing"
}
function removeAll() {
echo "Removing all state..."
for d in ${CONTAINERS_DIR}/*/; do
containerName="$(basename "${d}")"
jenkinsPort="$(echo "${containerName}" | sed 's/^.*-//')"
updateGlobals
echo ">> Removing container [${containerName}]..."
removeContainer
done
echo ">> Removing containers state directory..."
removeDir "${CONTAINERS_DIR}"
echo ">> Removing plugins backup directory..."
removeDir "${backupPluginsDir}"
echo -e
echo "Done removing all state"
}
function removeDir() {
set -o xtrace
${prefixCmd} rm -r "$1"
set +o xtrace
}
function usage() {
echo "Usage: $(basename $0) <command> [<args>]"
echo -e
echo "Available commands:"
echo " start PATH [PORT] Start Jenkins with given Gradle project, which must have the [jenkins-jobdsl] plugin configured"
echo " stop [PORT] Stop Jenkins"
echo " restart [PORT] Restart Jenkins"
echo " status Show if Jenkins is running or not"
echo " clear Remove all jobs from Jenkins"
echo " [${jenkinsJobsDir}]"
echo " remove [PORT] Remove the Jenkins working directory"
echo " [${jenkinsDir}]"
echo " remove-all [PORT] Remove all directories created by this script"
echo " [${jenkinsDir}]"
echo " [${jenkinsUserHomeDir}]"
echo " [${backupPluginsDir}]"
}
function requires() {
local command=$1
which ${command} > /dev/null 2>&1 || { echo "!! This script requires [${command}] to be installed" && exit 1; }
}
requires 'docker'
requires 'curl'
requires 'wget'
updateGlobals
command=$1; shift
case "${command}" in
start)
if [[ $# -ge 2 ]]; then
jenkinsPort="$2"
fi
updateGlobals
start "$@"
;;
stop)
if [[ $# -ge 1 ]]; then
jenkinsPort="$1"
fi
updateGlobals
stop
;;
restart)
if [[ $# -ge 2 ]]; then
jenkinsPort="$2"
fi
updateGlobals
stop && start "$@"
;;
status)
status
;;
clear)
clear
;;
remove)
if [[ $# -ge 1 ]]; then
jenkinsPort="$1"
fi
updateGlobals
remove
;;
remove-all)
removeAll
;;
*)
usage
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment