Start jenkins-slave using systemd on modern systems
diff --git a/jenkins/files/slave/default b/jenkins/files/slave/default
new file mode 100644
index 0000000..e5ab906
--- /dev/null
+++ b/jenkins/files/slave/default
@@ -0,0 +1,56 @@
+{%- from "jenkins/map.jinja" import slave with context %}
+# defaults for jenkins-slave component of the jenkins continuous integration
+# system
+
+# pulled in from the init script; makes things easier.
+NAME=jenkins-slave
+
+# location of java
+JAVA=/usr/bin/java
+
+# arguments to pass to java - optional
+#JAVA_ARGS="-Xmx256m"
+
+# for daemon to use
+PIDFILE=/var/run/$NAME.pid
+
+# user id to be invoked as (otherwise will run as root; not wise!)
+JENKINS_USER=jenkins
+
+# location of jenkins arch indep files
+JENKINS_ROOT=/usr/share/jenkins
+
+# jenkins home location
+JENKINS_HOME=/var/lib/jenkins
+
+# jenkins /run location
+JENKINS_RUN=/var/run/jenkins
+
+{%- if slave.user is defined %}
+# Authentication to jenkins master
+JENKINS_LOGIN="{{ slave.user.name }}"
+JENKINS_PASSWORD="{{ slave.user.password }}"
+{%- endif %}
+
+# URL of jenkins server to connect to
+JENKINS_URL="{{ slave.master.protocol }}://{{ slave.master.host }}:{{ slave.master.port }}"
+
+# Name of slave configuration to use at JENKINS_URL
+# Override if it need to be something other than the
+# hostname of the server the slave is running on.
+JENKINS_HOSTNAME="{{ slave.hostname }}"
+
+# Log file location for use in Debian init script
+JENKINS_SLAVE_LOG=/var/log/jenkins/$NAME.log
+
+# OS LIMITS SETUP
+# comment this out to observe /etc/security/limits.conf
+# this is on by default because http://github.com/feniix/hudson/commit/d13c08ea8f5a3fa730ba174305e6429b74853927
+# reported that Ubuntu's PAM configuration doesn't include pam_limits.so, and as a result the # of file
+# descriptors are forced to 1024 regardless of /etc/security/limits.confa
+# NOTE - Ubuntu Users - this is not used by the upstart configuration - please use an upstart overrides file
+# to change the OS limits setup.
+MAXOPENFILES=8192
+
+# Arguments to pass to jenkins slave on startup
+JENKINS_ARGS="-jnlpUrl ${JENKINS_URL}/computer/$JENKINS_HOSTNAME/slave-agent.jnlp -jnlpCredentials ${JENKINS_LOGIN}:${JENKINS_PASSWORD}"
diff --git a/jenkins/files/slave/init.d/jenkins-slave b/jenkins/files/slave/init.d/jenkins-slave
new file mode 100644
index 0000000..688ec2c
--- /dev/null
+++ b/jenkins/files/slave/init.d/jenkins-slave
@@ -0,0 +1,81 @@
+#!/bin/bash
+
+### BEGIN INIT INFO
+# Provides: jenkins-slave
+# Required-Start: $remote_fs $syslog
+# Required-Stop: $remote_fs $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop:
+# Short-Description: Jenkins slave
+### END INIT INFO
+
+set -e
+
+# /etc/init.d/jenkins-slave: start and stop Jenkins slave
+
+if test -f /etc/default/jenkins-slave; then
+ . /etc/default/jenkins-slave
+else
+ echo "Configuration for jenkins-slave does not exist" 1>&2
+ exit 1
+fi
+
+. /lib/lsb/init-functions
+
+COMMAND="/usr/bin/java"
+COMMAND_ARGS="-jar slave.jar ${JENKINS_ARGS}"
+
+function check_running() {
+ start-stop-daemon -T --pidfile ${PIDFILE}
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ log_end_msg 1 || true
+ exit $ret
+ fi
+}
+
+function start() {
+ # Get slave.jar from master
+ [ -n "${JENKINS_LOGIN}" ] && WGET_ARGS="--user=$JENKINS_LOGIN --password=$JENKINS_PASSWORD"
+ [ -f ${JENKINS_HOME}/slave.jar ] || wget $WGET_ARGS -O ${JENKINS_HOME}/slave.jar -q ${JENKINS_URL}/jnlpJars/slave.jar
+
+ if start-stop-daemon -c ${JENKINS_USER} -d ${JENKINS_HOME} --background --start --quiet --oknodo -m --pidfile ${PIDFILE} --exec ${COMMAND} -- ${COMMAND_ARGS}; then
+ log_end_msg 0 || true
+ else
+ log_end_msg 1 || true
+ fi
+}
+
+function stop() {
+ if start-stop-daemon --stop --quiet --oknodo --pidfile ${PIDFILE}; then
+ log_end_msg 0 || true
+ else
+ log_end_msg 1 || true
+ fi
+}
+
+case "$1" in
+ start)
+ log_daemon_msg "Starting Jenkins slave" "jenkins-slave" || true
+ start
+ ;;
+ stop)
+ log_daemon_msg "Stopping Jenkins slave" "jenkins-slave" || true
+ stop
+ ;;
+ status)
+ status_of_proc -p ${PIDFILE} ${COMMAND} jenkins-slave && exit 0 || exit $?
+ ;;
+ restart)
+ log_daemon_msg "Restarting Jenkins slave" "jenkins-slave" || true
+ stop
+ start
+ ;;
+
+ *)
+ log_action_msg "Usage: /etc/init.d/jenkins-slave {start|stop|restart}" || true
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/jenkins/files/slave/jenkins-slave b/jenkins/files/slave/jenkins-slave
new file mode 100644
index 0000000..b6b7c9d
--- /dev/null
+++ b/jenkins/files/slave/jenkins-slave
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+if test -f /etc/default/jenkins-slave; then
+ . /etc/default/jenkins-slave
+else
+ echo "Configuration for jenkins-slave does not exist" 1>&2
+ exit 1
+fi
+
+# Get slave.jar from master
+[ -n "${JENKINS_LOGIN}" ] && WGET_ARGS="--user=$JENKINS_LOGIN --password=$JENKINS_PASSWORD"
+[ -f ${JENKINS_HOME}/slave.jar ] || wget $WGET_ARGS -O ${JENKINS_HOME}/slave.jar -q ${JENKINS_URL}/jnlpJars/slave.jar
+
+java -jar ${JENKINS_HOME}/slave.jar ${JENKINS_ARGS}
diff --git a/jenkins/files/slave/jenkins-slave.service b/jenkins/files/slave/jenkins-slave.service
new file mode 100644
index 0000000..74f7fc2
--- /dev/null
+++ b/jenkins/files/slave/jenkins-slave.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Jenkins Slave
+After=network.target
+
+[Service]
+User=jenkins
+ExecStart=/usr/local/bin/jenkins-slave
+Restart=always
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target
diff --git a/jenkins/files/slave/keystonerc b/jenkins/files/slave/keystonerc
new file mode 100644
index 0000000..d9d2e38
--- /dev/null
+++ b/jenkins/files/slave/keystonerc
@@ -0,0 +1,5 @@
+{%- set server = pillar.jenkins.slave.keystone %}
+export OS_USERNAME="{{ server.user }}"
+export OS_PASSWORD="{{ server.password }}"
+export OS_TENANT_NAME="{{ server.tenant }}"
+export OS_AUTH_URL="{{ server.url }}"
diff --git a/jenkins/files/slave/pbuilderrc b/jenkins/files/slave/pbuilderrc
new file mode 100644
index 0000000..4312a75
--- /dev/null
+++ b/jenkins/files/slave/pbuilderrc
@@ -0,0 +1,120 @@
+{%- from "jenkins/map.jinja" import slave with context %}
+{%- if slave.pbuilder is defined %}
+
+{%- if slave.pbuilder.mirrorsite is defined %}
+MIRRORSITE="{{ slave.pbuilder.mirrorsite }}"
+{%- endif %}
+
+{%- if slave.pbuilder.othermirror is defined %}
+OTHERMIRROR="deb{% if slave.pbuilder.othermirror.get('trusted', True) %} [trusted=yes]{% endif %} {{ slave.pbuilder.othermirrror.url }} {{ slave.pbuilder.othermirror.dist }} {{ slave.pbuilder.othermirror.components|join(' ') }}"
+{%- endif %}
+
+{%- if slave.pbuilder.components is defined %}
+COMPONENTS="{{ slave.pbuilder.components|join(' ') }}"
+{%- endif %}
+
+{%- set keyring = slave.pbuilder.get('keyring', '/etc/apt/trusted.gpg') %}
+DEBOOTSTRAPOPTS=(${DEBOOTSTRAPOPTS[@]} "--keyring={{ keyring }}")
+APTKEYRINGS=(${APTKEYRINGS[@]} "{{ keyring }}")
+
+{%- if slave.pbuilder.aptcache is defined %}
+APTCACHE="{{ slave.pbuilder.aptcache }}"
+{%- endif %}
+
+{%- if slave.pbuilder.aptcachehardlink is defined %}
+APTCACHEHARDLINK="{{ 'yes' if slave.pbuilder.aptcachehardlink else 'no' }}"
+{%- endif %}
+
+{%- if slave.pbuilder.buildplace is defined %}
+BUILDPLACE="{{ slave.pbuilder.buildplace }}"
+{%- endif %}
+
+{%- if slave.pbuilder.buildresult is defined %}
+BUILDRESULT="{{ slave.pbuilder.buildresult }}"
+{%- endif %}
+
+{%- if slave.pbuilder.ccachedir is defined %}
+CCACHEDIR="{{ slave.pbuilder.ccachedir }}"
+{%- endif %}
+
+{%- if slave.pbuilder.usenetwork is defined %}
+USENETWORK="{{ 'yes' if slave.pbuilder.usenetwork else 'no' }}"
+{%- endif %}
+
+BINDMOUNTS="/var/cache/pbuilder/build"
+
+{%- if slave.pbuilder.parallel is defined %}
+{%- if slave.pbuilder.parallel %}
+{# Automatically set jobs to no. of cpus #}
+JOBS=$(grep -c processor /proc/cpuinfo)
+{%- else %}
+JOBS={{ slave.pbuilder.parallel }}
+{%- endif %}
+
+DEB_BUILD_OPTIONS="parallel=${JOBS} $DEB_BUILD_OPTIONS"
+{%- endif %}
+
+{%- if slave.pbuilder.get('eatmydata', False) %}
+EXTRAPACKAGES="$EXTRAPACKAGES eatmydata"
+export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+"$LD_LIBRARY_PATH:"}/usr/lib/libeatmydata
+export LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}libeatmydata.so"
+{%- endif %}
+
+{%- for os, distribution in slave.pbuilder.get('os', {}).iteritems() %}
+if [ "$OS" == "{{ os }}" ]; then
+ {%- for dist_name, dist in distribution.iteritems() %}
+ if [ "$DIST" == "{{ dist_name }}" ]; then
+ DISTRIBUTION="$DIST"
+ MIRRORSITE="{{ dist.mirrorsite }}"
+
+ {%- if dist.othermirror is defined %}
+ OTHERMIRROR="deb{% if dist.othermirror.get('trusted', True) %} [trusted=yes]{% endif %} {{ dist.othermirror.url }} {{ dist.othermirror.get('dist', dist_name) }} {{ dist.othermirror.components|join(' ') }}"
+ {%- endif %}
+
+ COMPONENTS="{{ dist.components|join(' ') }}"
+
+ {%- if dist.keyring is defined %}
+ DEBOOTSTRAPOPTS=(${DEBOOTSTRAPOPTS[@]} "--keyring={{ dist.keyring }}")
+ APTKEYRINGS=(${APTKEYRINGS[@]} "{{ dist.keyring }}")
+ {%- endif %}
+ ARCH="${ARCH:-{{ dist.get('arch', '$(dpkg --print-architecture)') }}}"
+
+ {%- if dist.extrapackages is defined %}
+ EXTRAPACKAGES="$EXTRAPACKAGES {{ dist.extrapackages|join(' ') }}"
+ {%- endif %}
+
+ {%- if dist.get('eatmydata', False) %}
+ EXTRAPACKAGES="$EXTRAPACKAGES eatmydata"
+ export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+"$LD_LIBRARY_PATH:"}/usr/lib/libeatmydata
+ export LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}libeatmydata.so"
+ {%- endif %}
+
+ NAME="${OS}-${DIST}-${ARCH}"
+ BASETGZ="/var/cache/pbuilder/${NAME}-base.tgz"
+ BUILDRESULT="/var/cache/pbuilder/${NAME}/result/"
+ APTCACHE="/var/cache/pbuilder/${NAME}/aptcache/"
+ BASEPATH="/var/cache/pbuilder/${NAME}-base.cow"
+ fi
+ {%- endfor %}
+fi
+{%- endfor %}
+
+ARCH="${ARCH:-{{ slave.pbuilder.get('arch', '$(dpkg --print-architecture)') }}}"
+
+if [ "$ARCH" == "armel" ] && [ "$(dpkg --print-architecture)" != "armel" ]; then
+ DEBOOTSTRAP="qemu-debootstrap"
+fi
+if [ "$ARCH" == "armhf" ] && [ "$(dpkg --print-architecture)" != "armhf" ]; then
+ DEBOOTSTRAP="qemu-debootstrap"
+fi
+if [ "$ARCH" == "arm64" ] && [ "$(dpkg --print-architecture)" != "arm64" ]; then
+ DEBOOTSTRAP="qemu-debootstrap"
+fi
+
+DEBOOTSTRAPOPTS=("${DEBOOTSTRAPOPTS[@]}" "--arch=$ARCH")
+
+{%- endif %}
+
+{#-
+vim: syntax=jinja
+-#}
diff --git a/jenkins/files/slave/sudoer b/jenkins/files/slave/sudoer
new file mode 100644
index 0000000..a06260b
--- /dev/null
+++ b/jenkins/files/slave/sudoer
@@ -0,0 +1,5 @@
+# jenkins user with passwordless sudo functionality.
+
+jenkins ALL=(ALL) NOPASSWD:ALL
+
+Defaults:jenkins !requiretty
diff --git a/jenkins/files/slave/sudoer_debian_glue b/jenkins/files/slave/sudoer_debian_glue
new file mode 100644
index 0000000..988682d
--- /dev/null
+++ b/jenkins/files/slave/sudoer_debian_glue
@@ -0,0 +1,4 @@
+# allow jenkins to use cowbuilder, preserve important environment variables
+
+jenkins ALL=NOPASSWD: /usr/sbin/cowbuilder, /usr/sbin/chroot
+Defaults env_keep+="DEB_* DIST ARCH ADT"
diff --git a/jenkins/slave/init.sls b/jenkins/slave/init.sls
index e34d0ec..6e285cd 100644
--- a/jenkins/slave/init.sls
+++ b/jenkins/slave/init.sls
@@ -25,19 +25,34 @@
{% else %}
# No jenkins-slave package, use magic init script instead
-{{ slave.init_script }}:
+{%- if grains.init == 'systemd' %}
+jenkins_slave_init_script:
file.managed:
- - source: salt://jenkins/files/init.d/jenkins-slave
+ - name: /etc/systemd/system/jenkins-slave.service
+ - source: salt://jenkins/files/slave/jenkins-slave.service
+ - user: root
+ - group: root
+ - mode: 644
+ - require:
+ - file: jenkins_slave_start_script
+{%- else %}
+jenkins_slave_init_script:
+ file.managed:
+ - name: {{ slave.init_script }}
+ - source: salt://jenkins/files/slave/init.d/jenkins-slave
- user: root
- group: root
- mode: 755
- template: jinja
+ - require:
+ - file: jenkins_slave_start_script
+{%- endif %}
{% endif %}
{{ slave.config }}:
file.managed:
- - source: salt://jenkins/files/jenkins-slave
+ - source: salt://jenkins/files/slave/default
- user: root
- group: root
- template: jinja
@@ -45,19 +60,29 @@
{% if slave.pkgs %}
- pkg: jenkins_slave_package
{% else %}
- - file: {{ slave.init_script }}
+ - file: jenkins_slave_init_script
{% endif %}
+jenkins_slave_start_script:
+ file.managed:
+ - name: /usr/local/bin/jenkins-slave
+ - source: salt://jenkins/files/slave/jenkins-slave
+ - user: root
+ - group: root
+ - mode: 755
+ - template: jinja
+
jenkins_slave_service:
service.running:
- name: {{ slave.service }}
- watch:
- file: {{ slave.config }}
+ - enable: true
- require:
{% if slave.pkgs %}
- pkg: jenkins_slave_package
{% else %}
- - file: {{ slave.init_script }}
+ - file: jenkins_slave_init_script
{% endif %}
{%- if pillar.linux.system.user.jenkins is not defined %}
@@ -81,7 +106,7 @@
/etc/sudoers.d/99-jenkins-user:
file.managed:
- - source: salt://jenkins/files/sudoer
+ - source: salt://jenkins/files/slave/sudoer
- template: jinja
- user: root
- group: root
diff --git a/jenkins/slave/keystone.sls b/jenkins/slave/keystone.sls
index d308f76..26e51e3 100644
--- a/jenkins/slave/keystone.sls
+++ b/jenkins/slave/keystone.sls
@@ -2,7 +2,7 @@
/var/lib/jenkins/keystonerc:
file.managed:
- - source: salt://jenkins/files/keystonerc
+ - source: salt://jenkins/files/slave/keystonerc
- user: jenkins
- group: jenkins
- mode: 0400
diff --git a/jenkins/slave/pbuilder.sls b/jenkins/slave/pbuilder.sls
index 851d1f7..7ffedb2 100644
--- a/jenkins/slave/pbuilder.sls
+++ b/jenkins/slave/pbuilder.sls
@@ -23,7 +23,7 @@
/etc/sudoers.d/98-jenkins-debian-glue:
file.managed:
- - source: salt://jenkins/files/sudoer_debian_glue
+ - source: salt://jenkins/files/slave/sudoer_debian_glue
- template: jinja
- user: root
- group: root
@@ -33,7 +33,7 @@
/etc/pbuilderrc:
file.managed:
- - source: salt://jenkins/files/pbuilderrc
+ - source: salt://jenkins/files/slave/pbuilderrc
- template: jinja
- user: root
- group: root