Created
February 24, 2015 09:29
-
-
Save pvdissel/efe99cb84d93b8ad721c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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