Khi này thì mình đã build jenkins agent bằng docker để thêm 1 tool của mình vào jenkins như là:
– appium
– adb
– và vân vân.
Chúng ta cần build docker image có jenkins agent sau đó cài các apps nhữ đã nêu ở trên.
1) Build-Self a docker image Of Jenkins-agent
###Dockerfile ############# FROM ubuntu:18.04 MAINTAINER Khai Phan <mr.nim94@gmail.com> ARG JENKINS_AGENT_VERSION=4.3 ARG user=jenkins ARG group=jenkins ARG uid=1000 ARG gid=1000 ARG AGENT_WORKDIR=/home/${user}/agent # INSTALL DOCKER RUN apt-get -y update RUN apt-get -y install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ gnupg2 \ software-properties-common \ docker.io \ build-essential \ zlib1g-dev \ vim \ unzip \ sudo \ dialog \ git \ python-pip python3.6 python3-pip\ gettext-base \ jq \ openssh-server openssh-client \ openjdk-11-jdk \ dirmngr \ lsb-release RUN curl --create-dirs -sSLo /usr/share/jenkins/agent.jar https://repo.jenkins-ci.org/public/org/jenkins-ci/main/remoting/${JENKINS_AGENT_VERSION}/remoting-${JENKINS_AGENT_VERSION}.jar \ && chmod 755 /usr/share/jenkins \ && chmod 644 /usr/share/jenkins/agent.jar \ && ln -sf /usr/share/jenkins/agent.jar /usr/share/jenkins/slave.jar \ && apt-get autoclean RUN groupadd -g ${gid} ${group} \ && useradd -c "Jenkins user" -d /home/${user} -u ${uid} -g ${gid} -m ${user} COPY jenkins-agent /usr/local/bin/jenkins-agent RUN chmod 755 /usr/local/bin/jenkins-agent && chown ${user}:${group} /usr/local/bin/jenkins-agent && \ chown ${user}:${group} /home/${user} USER ${user} RUN mkdir -p /home/${user}/.jenkins && mkdir -p ${AGENT_WORKDIR} VOLUME /home/${user}/.jenkins VOLUME ${AGENT_WORKDIR} WORKDIR /home/${user} ENTRYPOINT ["/usr/local/bin/jenkins-agent"]
tiếp đến chúng ta sẽ có 1 file script
Để Auto Kết nối đến jenkins master
File: jenkins-agent
#!/usr/bin/env sh # The MIT License # # Copyright (c) 2015-2020, CloudBees, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # Usage jenkins-agent.sh [options] -url http://jenkins [SECRET] [AGENT_NAME] # Optional environment variables : # * JENKINS_TUNNEL : HOST:PORT for a tunnel to route TCP traffic to jenkins host, when jenkins can't be directly accessed over network # * JENKINS_URL : alternate jenkins URL # * JENKINS_SECRET : agent secret, if not set as an argument # * JENKINS_AGENT_NAME : agent name, if not set as an argument # * JENKINS_AGENT_WORKDIR : agent work directory, if not set by optional parameter -workDir # * JENKINS_AGENT_INTERNALDIR : agent work sub directory, if not set by optional parameter -internalDir # * JENKINS_WEB_SOCKET: true if the connection should be made via WebSocket rather than TCP # * JENKINS_DIRECT_CONNECTION: Connect directly to this TCP agent port, skipping the HTTP(S) connection parameter download. # Value: "<HOST>:<PORT>" # * JENKINS_INSTANCE_IDENTITY: The base64 encoded InstanceIdentity byte array of the Jenkins master. When this is set, # the agent skips connecting to an HTTP(S) port for connection info. # * JENKINS_PROTOCOLS: Specify the remoting protocols to attempt when instanceIdentity is provided. if [ $# -eq 1 ]; then # if `docker run` only has one arguments, we assume user is running alternate command like `bash` to inspect the image exec "$@" else # Copy ssh key if [ -d "/tiki/ssh" ]; then mkdir -p /home/jenkins/.ssh cp -fr /tiki/ssh/* /home/jenkins/.ssh fi # if -tunnel is not provided, try env vars case "$@" in *"-tunnel "*) ;; *) if [ ! -z "$JENKINS_TUNNEL" ]; then TUNNEL="-tunnel $JENKINS_TUNNEL" fi ;; esac # if -workDir is not provided, try env vars if [ ! -z "$JENKINS_AGENT_WORKDIR" ]; then case "$@" in *"-workDir"*) echo "Warning: Work directory is defined twice in command-line arguments and the environment variable" ;; *) WORKDIR="-workDir $JENKINS_AGENT_WORKDIR" ;; esac fi if [ ! -z "$JENKINS_AGENT_INTERNALDIR" ]; then case "$@" in *"-workDir"*) echo "Warning: Work directory is defined twice in command-line arguments and the environment variable" ;; *) INTERNALDIR="-internalDir $JENKINS_AGENT_INTERNALDIR" ;; esac fi if [ -n "$JENKINS_URL" ]; then URL="-url $JENKINS_URL" fi if [ -n "$JENKINS_NAME" ]; then JENKINS_AGENT_NAME="$JENKINS_NAME" fi if [ "$JENKINS_WEB_SOCKET" = true ]; then WEB_SOCKET=-webSocket fi if [ -n "$JENKINS_PROTOCOLS" ]; then PROTOCOLS="-protocols $JENKINS_PROTOCOLS" fi if [ -n "$JENKINS_DIRECT_CONNECTION" ]; then DIRECT="-direct $JENKINS_DIRECT_CONNECTION" fi if [ -n "$JENKINS_INSTANCE_IDENTITY" ]; then INSTANCE_IDENTITY="-instanceIdentity $JENKINS_INSTANCE_IDENTITY" fi # if java home is defined, use it JAVA_BIN="java" if [ "$JAVA_HOME" ]; then JAVA_BIN="$JAVA_HOME/bin/java" fi # if both required options are defined, do not pass the parameters OPT_JENKINS_SECRET="" eval DYNAMIC_JENKINS_SECRET='$JENKINS_SECRET_'$(echo ${HOSTNAME} | sed -e 's|[-\.]|_|g') echo $DYNAMIC_JENKINS_SECRET if [ -n "$DYNAMIC_JENKINS_SECRET" ]; then JENKINS_SECRET=$DYNAMIC_JENKINS_SECRET fi if [ -n "$JENKINS_SECRET" ]; then case "$@" in *"${JENKINS_SECRET}"*) echo "Warning: SECRET is defined twice in command-line arguments and the environment variable" ;; *) OPT_JENKINS_SECRET="${JENKINS_SECRET}" ;; esac fi OPT_JENKINS_AGENT_NAME="" if [ -n "$JENKINS_AGENT_NAME" ]; then case "$@" in *"${JENKINS_AGENT_NAME}"*) echo "Warning: AGENT_NAME is defined twice in command-line arguments and the environment variable" ;; *) OPT_JENKINS_AGENT_NAME="${JENKINS_AGENT_NAME}" ;; esac fi #TODO: Handle the case when the command-line and Environment variable contain different values. #It is fine it blows up for now since it should lead to an error anyway. echo "execute: $JAVA_BIN $JAVA_OPTS -cp /usr/share/jenkins/agent.jar hudson.remoting.jnlp.Main -headless $TUNNEL $URL $WORKDIR $INTERNALDIR $WEB_SOCKET $DIRECT $PROTOCOLS $INSTANCE_IDENTITY $OPT_JENKINS_SECRET $OPT_JENKINS_AGENT_NAME "$@"" exec $JAVA_BIN $JAVA_OPTS -cp /usr/share/jenkins/agent.jar hudson.remoting.jnlp.Main -headless $TUNNEL $URL $WORKDIR $INTERNALDIR $WEB_SOCKET $DIRECT $PROTOCOLS $INSTANCE_IDENTITY $OPT_JENKINS_SECRET $OPT_JENKINS_AGENT_NAME "$@" fi
Giờ bạn gõ lệnh build và push
docker build -t docker.nimtechnology.com/nim/android-container:0.0.16 --force-rm -f Dockerfile .
docker push docker.nimtechnology.com/nim/android-container:0.0.16
Nếu bạn triển khai trên docker hay k8s đừng quên các env sau:
- env: - name: JENKINS_AGENT_NAME value: appium-agent-k8s-0 - name: JENKINS_AGENT_WORKDIR value: /home/jenkins/agent - name: JENKINS_NAME value: appium-agent-k8s-0 - name: JENKINS_SECRET value: 9253b38efa86615c430a669bbd88df43be75b4588225fd49553c660d6034f951 - name: JENKINS_TUNNEL value: jenkins-controller-agent:50000 - name: JENKINS_URL value: http://jenkins-controller:8080
Ở bài này thì đã khắc phục được điểm trong bài post cũ: agent register master(.jar)
Mỗi khi deployment jenkins agent restart nó sẽ tự động kết nối đến jenkins controller.
2) Add any application or any tools into Jenkins agent Container.
Ở các bước trên thì chúng ta đã build được image và run được container của Jenkins agent trên k8s.
Giờ dô một bài thực tế:
Mình được team android tạo 1 job testing và mình cần cài lên con agent những tool như video bên dưới đây:
Sau khi coi xong thì mình viết ra 1 file Dockerfile mới:
FROM ubuntu:18.04 MAINTAINER Khai Phan <mr.nim94@gmail.com> ARG JENKINS_AGENT_VERSION=4.3 ARG user=jenkins ARG group=jenkins ARG uid=1000 ARG gid=1000 ARG AGENT_WORKDIR=/home/${user}/agent # INSTALL DOCKER RUN apt-get -y update RUN apt-get -y install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ gnupg2 \ software-properties-common \ docker.io \ build-essential \ zlib1g-dev \ vim \ unzip \ sudo \ dialog \ git \ python-pip python3.6 python3-pip\ gettext-base \ jq \ openssh-server openssh-client \ openjdk-11-jdk \ dirmngr \ lsb-release #install Node.js RUN curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - \ && echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list \ && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - \ && curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - \ && apt-get install -y google-cloud-sdk rsync nodejs RUN apt-get -y update #install Appium RUN sudo npm install -g appium --unsafe-perm=true --allow-root RUN npm install -g appium-doctor ##Install Commandlinetools Android RUN wget https://dl.google.com/android/repository/commandlinetools-linux-6858069_latest.zip \ && mkdir -p /opt/devtools/android \ && unzip commandlinetools-linux-6858069_latest.zip \ && rm -f commandlinetools-linux-6858069_latest.zip \ && mv cmdline-tools /opt/devtools/android \ && export PATH="/opt/devtools/android/cmdline-tools/bin:/opt/devtools/android/platform-tools:$PATH" \ && yes | sdkmanager --sdk_root=/opt/devtools/android "platform-tools" "platforms;android-30" \ && yes | sdkmanager --sdk_root=/opt/devtools/android "build-tools;30.0.2" \ && yes | sdkmanager --sdk_root=/opt/devtools/android "platform-tools" "platforms;android-29" \ && yes | sdkmanager --sdk_root=/opt/devtools/android "build-tools;29.0.3" \ && yes | sdkmanager --sdk_root=/opt/devtools/android "platform-tools" "platforms;android-28" \ && yes | sdkmanager --sdk_root=/opt/devtools/android "build-tools;28.0.3" \ && yes | sdkmanager --sdk_root=/opt/devtools/android "platform-tools" "platforms;android-27" \ && yes | sdkmanager --sdk_root=/opt/devtools/android "build-tools;27.0.3" \ && yes | sdkmanager --sdk_root=/opt/devtools/android --licenses RUN curl --create-dirs -sSLo /usr/share/jenkins/agent.jar https://repo.jenkins-ci.org/public/org/jenkins-ci/main/remoting/${JENKINS_AGENT_VERSION}/remoting-${JENKINS_AGENT_VERSION}.jar \ && chmod 755 /usr/share/jenkins \ && chmod 644 /usr/share/jenkins/agent.jar \ && ln -sf /usr/share/jenkins/agent.jar /usr/share/jenkins/slave.jar \ && apt-get autoclean RUN groupadd -g ${gid} ${group} \ && useradd -c "Jenkins user" -d /home/${user} -u ${uid} -g ${gid} -m ${user} COPY jenkins-agent /usr/local/bin/jenkins-agent RUN chmod 755 /usr/local/bin/jenkins-agent && chown ${user}:${group} /usr/local/bin/jenkins-agent && \ chown ${user}:${group} /home/${user} ARG ANDROID_HOME="/opt/devtools/android" USER ${user} RUN mkdir -p /home/${user}/.jenkins && mkdir -p ${AGENT_WORKDIR} \ && echo "export ANDROID_HOME=${ANDROID_HOME}" >> /home/jenkins/.bashrc \ && echo "export PATH=${ANDROID_HOME}/platform-tools:${PATH}" >> /home/jenkins/.bashrc VOLUME /home/${user}/.jenkins VOLUME ${AGENT_WORKDIR} WORKDIR /home/${user} ENTRYPOINT ["/usr/local/bin/jenkins-agent"]
và giờ mình run command trên jenkins và chỉ định agent appium
npm -v node -v java --version echo $PATH appium-doctor --android adb devices
Bạn để ý trên Dockerfile mình đã add thêm trong .brashrc
Nhưng khi run job trên jenkins nó hình như không ăn!
Khi gặp case này thì chúng ta hay run command.source ./bashrc
Giờ sửa file thôi:
source /home/jenkins/.bashrc npm -v node -v java --version echo $PATH appium-doctor --android adb devices
Started by user Jenkins Admin Running as SYSTEM Building remotely on appium-agent-k8s-0 (appium) in workspace /home/jenkins/agent/workspace/stf-run-test [stf-run-test] $ /bin/sh -xe /tmp/jenkins8941517299883340116.sh + source /home/jenkins/.bashrc /tmp/jenkins8941517299883340116.sh: 3: /tmp/jenkins8941517299883340116.sh: source: not found Build step 'Execute shell' marked build as failure Finished: FAILURE
Giờ mình đưa luôn export vào command luôn.
export PATH=/opt/devtools/android/platform-tools:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin npm -v node -v java --version echo $PATH appium-doctor --android adb devices