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