forked from openbmc/openbmc-build-scripts
-
Notifications
You must be signed in to change notification settings - Fork 5
/
build-jenkins.sh
executable file
·267 lines (235 loc) · 10.4 KB
/
build-jenkins.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
#!/bin/bash
################################################################################
#
# Script used to create a Jenkins master that can run amd64 or ppc64le. It can
# be used to launch the Jenkins master as a Docker container locally or as a
# Kubernetes Deployment in a Kubernetes cluster.
#
################################################################################
#
# Script Variables:
# build_scripts_dir The path of the openbmc-build-scripts directory.
# Default: The directory containing this script
# workspace The directory that holds files used to build the Jenkins
# master master image and volumes used to deploy it.
# Default: "~/jenkins-build-${RANDOM}"
#
# Jenkins Dockerfile Variables:
# agent_port The port used as the Jenkins slave agent port.
# Default: "50000"
# http_port The port used as Jenkins UI port.
# Default: "8080"
# img_name The name given to the Docker image when it is built.
# Default: "openbmc/jenkins-master-${ARCH}:${JENKINS_VRSN}"
# img_tag The tag of the OpenJDK image used as the base image.
# Default: "/8-jdk"
# j_gid Jenkins group ID the container will use to run Jenkins.
# Default: "1000"
# j_group Group name tag the container will use to run Jenkins.
# Default: "jenkins"
# j_home Directory used as the Jenkins Home in the container.
# Default: "/var/jenkins_home"
# j_uid Jenkins user ID the container will use to run Jenkins.
# Default: "1000"
# j_user Username tag the container will use to run Jenkins.
# Default: "jenkins"
# j_vrsn The version of the Jenkins war file you wish to use.
# Default: "2.60.3"
# tini_vrsn The version of Tini to use in the Dockerfile, 0.16.1 is
# the first release with ppc64le release support.
# Default: "0.16.1"
#
# Deployment Variables:
# cont_import_mnt The directory on the container used to import extra files.
# Default: "/mnt/jenkins_import", ignored if above not set
# home_mnt The directory on the host used as the Jenkins home.
# Default: "${WORKSPACE}/jenkins_home"
# host_import_mnt The directory on the host used to import extra files.
# Default: "", import mount is ignored if not set
# java_options What will be passed as the environment variable for the
# JAVA_OPTS environment variable.
# Default: "-Xmx4096m"
# jenkins_options What will be passed as the environment variable for the
# JENKINS_OPTS environment variable.
# Default: "--prefix=/jenkins"
# launch docker|k8s
# Method in which the container will be launched. Either as
# a Docker container launched via Docker, or by using a
# helper script to launch into a Kubernetes cluster.
# Default: "docker"
#
################################################################################
set -xeo pipefail
ARCH=$(uname -m)
# Script Variables
build_scripts_dir=${build_scripts_dir:-"$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"}
workspace=${workspace:-${HOME}/jenkins-build-${RANDOM}}
# Jenkins Dockerfile Variables
agent_port=${agent_port:-50000}
http_port=${http_port:-8080}
img_name=${img_name:-openbmc/jenkins-master-${ARCH}:${j_vrsn}}
j_gid=${j_gid:-1000}
j_group=${j_group:-jenkins}
j_home=${j_home:-/var/jenkins_home}
j_uid=${j_uid:-1000}
j_user=${j_user:-jenkins}
j_vrsn=${j_vrsn:-2.60.3}
img_tag=${img_tag:-8-jdk}
tini_vrsn=${tini_vrsn:-0.16.1}
# Deployment Variables
cont_import_mnt=${cont_import_mnt:-/mnt/jenkins_import}
home_mnt=${home_mnt:-${workspace}/jenkins_home}
host_import_mnt=${host_import_mnt:-}
java_options=${java_options:-"-Xmx4096m"}
jenkins_options=${jenkins_options:-"--prefix=/jenkins"}
launch=${launch:-docker}
# Save the Jenkins.war URL to a variable and SHA if we care about verification
j_url=https://repo.jenkins-ci.org/public/org/jenkins-ci/main/jenkins-war/${j_vrsn}/jenkins-war-${j_vrsn}.war
# Make or Clean WORKSPACE
if [[ -d "${workspace}" ]]; then
rm -rf "${workspace}/Dockerfile" \
"${workspace}/docker-jenkins" \
"${workspace}/plugins.*" \
"${workspace}/install-plugins.sh" \
"${workspace}/jenkins.sh" \
"${workspace}/jenkins-support" \
"${workspace}/init.groovy"
else
mkdir -p "${workspace}"
fi
# Determine the prefix of the Dockerfile's base image
case ${ARCH} in
"ppc64le")
docker_base="ppc64le/"
tini_arch="ppc64el"
;;
"x86_64")
docker_base=""
tini_arch="amd64"
;;
"aarch64")
docker_base="arm64v8/"
tini_arch="arm64"
;;
*)
echo "Unsupported system architecture(${ARCH}) found for docker image"
exit 1
esac
# Move Into the WORKSPACE
cd "${workspace}"
# Make the Dockerfile
################################################################################
cat >> Dockerfile << EOF
FROM ${docker_base}openjdk:${img_tag}
RUN apt-get update && apt-get install -y git curl
ENV JENKINS_HOME ${j_home}
ENV JENKINS_SLAVE_AGENT_PORT ${agent_port}
# Jenkins will default to run with user jenkins, uid = 1000
# If you bind mount a volume from the host or a data container,
# ensure you use the same uid
RUN groupadd -g ${j_gid} ${j_group} && \
useradd -d ${j_home} -u ${j_uid} -g ${j_gid} -m -s /bin/bash ${j_user}
# Jenkins home directory is a volume, so configuration and build history
# can be persisted and survive image upgrades
VOLUME ${j_home}
# /usr/share/jenkins/ref/ contains all reference configuration we want
# to set on a fresh new installation. Use it to bundle additional plugins
# or config file with your custom jenkins Docker image.
RUN mkdir -p /usr/share/jenkins/ref/init.groovy.d
# Use tini as subreaper in Docker container to adopt zombie processes
RUN curl -fsSL https://github.com/krallin/tini/releases/download/v${tini_vrsn}/tini-static-${tini_arch} \
-o /bin/tini && \
chmod +x /bin/tini
COPY init.groovy /usr/share/jenkins/ref/init.groovy.d/tcp-slave-agent-port.groovy
# could use ADD but this one does not check Last-Modified header neither does it allow to control checksum
# see https://github.com/docker/docker/issues/8331
RUN curl -fsSL ${j_url} -o /usr/share/jenkins/jenkins.war
ENV JENKINS_UC https://updates.jenkins.io
ENV JENKINS_UC_EXPERIMENTAL=https://updates.jenkins.io/experimental
RUN chown -R ${j_user} ${j_home} /usr/share/jenkins/ref
# for main web interface:
EXPOSE ${http_port}
# will be used by attached slave agents:
EXPOSE ${agent_port}
ENV COPY_REFERENCE_FILE_LOG ${j_home}/copy_reference_file.log
USER ${j_user}
COPY jenkins-support /usr/local/bin/jenkins-support
COPY jenkins.sh /usr/local/bin/jenkins.sh
ENTRYPOINT ["/bin/tini", "--", "/usr/local/bin/jenkins.sh"]
# from a derived Dockerfile, can use RUN plugins.sh active.txt to setup /usr/share/jenkins/ref/plugins from a support bundle
COPY plugins.sh /usr/local/bin/plugins.sh
COPY install-plugins.sh /usr/local/bin/install-plugins.sh
# Install plugins.txt plugins
COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt
EOF
################################################################################
# Clone in the jenkinsci docker jenkins repo and copy some files into WORKSPACE
git clone https://github.com/jenkinsci/docker.git docker-jenkins
cp docker-jenkins/init.groovy .
cp docker-jenkins/jenkins-support .
cp docker-jenkins/jenkins.sh .
cp docker-jenkins/plugins.sh .
cp docker-jenkins/install-plugins.sh .
# Generate Plugins.txt, the plugins you want installed automatically go here
################################################################################
cat >> plugins.txt << EOF
kubernetes
EOF
################################################################################
# Build the image
docker build -t "${img_name}" .
if [[ "${launch}" == "docker" ]]; then
# Ensure directories that will be mounted exist
if [[ -n "${host_import_mnt}" && ! -d "${host_import_mnt}" ]]; then
mkdir -p "${host_import_mnt}"
fi
if [[ ! -d "${home_mnt}" ]]; then
mkdir -p "${home_mnt}"
fi
# Ensure directories that will be mounted are owned by the jenkins user
if [[ "$(id -u)" != 0 ]]; then
echo "Not running as root:"
echo "Checking if j_gid and j_uid are the owners of mounted directories"
# shellcheck disable=SC2012 # use ls to get permissions.
test_1="$(ls -nd "${home_mnt}" | awk '{print $3 " " $4}')"
if [[ "${test_1}" != "${j_uid} ${j_gid}" ]]; then
echo "Owner of ${home_mnt} is not the jenkins user"
echo "${test_1} != ${j_uid} ${j_gid}"
will_fail=1
fi
if [[ -n "${host_import_mnt}" ]]; then
# shellcheck disable=SC2012 # use ls to get permissions.
test_2="$(ls -nd "${host_import_mnt}" | awk '{print $3 " " $4}' )"
if [[ "${test_2}" != "${j_uid} ${j_gid}" ]]; then
echo "Owner of ${host_import_mnt} is not the jenkins user"
echo "${test_2} != ${j_uid} ${j_gid}"
will_fail=1
fi
fi
if [[ "${will_fail}" == 1 ]]; then
echo "Failing before attempting to launch container"
echo "Try again as root or use correct uid/gid pairs"
exit 1
fi
else
if [[ -n "${host_import_mnt}" ]]; then
chown -R "${j_uid}:${j_gid}" "${host_import_mnt}"
fi
chown -R "${j_uid}:${j_gid}" "${home_mnt}"
fi
#If we don't have import mount don't add to docker command
if [[ -n "${host_import_mnt}" ]]; then
import_vol_cmd="-v ${host_import_mnt}:${cont_import_mnt}"
fi
# Launch the jenkins image with Docker
# shellcheck disable=SC2086 # import_vol_cmd is intentially word-split.
docker run -d \
${import_vol_cmd} \
-v "${home_mnt}:${j_home}" \
-p "${http_port}:8080" \
-p "${agent_port}:${agent_port}" \
--env JAVA_OPTS=\""${java_options}"\" \
--env JENKINS_OPTS=\""${jenkins_options}"\" \
"${img_name}"
fi