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