Jenkins Usage - hqzhang/cloudtestbed GitHub Wiki

Clone Python

install conda


Step 1: Download Anaconda. ...
wget Anaconda3-5.2.0-Linux-x86_64.sh

Step 2: Run Anaconda Installation Script. ...
./Anaconda3-5.2.0-Linux-x86_64.sh

Step 3: Verify Installation. ...
conda list

Step 4: Create a New Environment. ...
conda create -n env38 python=3.8

Step 5: Activate Environment. ...
conda activate env38

Step 6: Install Packages.
conda install numpy

install python by conda

On source machine
1. Open your terminal and create a new environment using the command 
conda create -n offline_env python=3.8. 

2. Activate the new environment using 
conda activate offline_env.

3. Download the necessary packages. For instance, if you need the numpy package, use 
conda install -y numpy. 

4. Once you’ve downloaded all necessary packages, export them to a .tar file using
 conda pack -n offline_env -o offline_env.tar. 

clone and installation

On target machine
1. Unpack the .tar file using 
   tar -xvf offline_env.tar. This will create a directory named offline_env.

2. Activate the environment using 
   source offline_env/bin/activate.

Menu programming

Clone Jenkins

1. source jenkins installed successful:
  tar -czf jenkinsHome.tar.gz .jenkins
  scp  jenkinsHome.tar.gz [email protected]:~/

2. at target machine
  tar -xzvf jenkinsHome.tar.gz
  
3. add inito .bashrc
   export JENKINS_HOME=~/.jenkins
   export PATH=$JENKINS_HOME:$HOME/bin:$HOME/.local/bin:$PATH
   .~/.bashrc

4. run jenkins
   java -jar jenkins


Install Jenkins in centos

00) sudo yum install java-11-openjdk-devel
0) yum install git
   git --version

1) yum install java-11-openjdk-devel
  java -version

2) yum install wget
  wget --no-check-certificate -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
  rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
  yum repolist |grep Jenkins
[jenkins]
name=Jenkins-stable
baseurl=http://pkg.jenkins.io/redhat-stable
gpgcheck=1

3) yum install Jenkins
   systemctl start jenkins
   systemctl status jenkins
/usr/lib/systemd/system/ (or /run/systemd/system/ /etc/systemd/system/)
[Unit]
Description=Jenkins Continuous Integration Server
Requires=network.target
After=network.target
[Service]
Type=notify
NotifyAccess=main
ExecStart=/usr/bin/jenkins
Restart=on-failure
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target

User=jenkins
Group=jenkins
# Directory where Jenkins stores its configuration and workspaces
Environment="JENKINS_HOME=/var/lib/jenkins"
WorkingDirectory=/var/lib/jenkins
Environment="JENKINS_WEBROOT=%C/jenkins/war"
Environment="JAVA_OPTS=-Djava.awt.headless=true"
Environment="JENKINS_PORT=8080"


4) firewall-cmd --add-port=8080/tcp --permanent
   firewall-cmd --reload
   firewall-cmd --list-all

5) http://IP:8080 in browser
   Input pass in /var/lib/jenkins/secrets/initialAdminPassword
   
   Click Install-suggested-plugins
   Set id and password

1. Parameter Definition

@groovy.transform.Field
def envList=['DEV','BAT']
@groovy.transform.Field
def serversList=[DEV: ['s11','ss22','ss33'],
                 BAT: ['s44','s55','s66'] ] 
@groovy.transform.Field
def defaultList=['ss33', 's55']

2. Menu and Method Definition

//Define method here
properties([
    parameters([
    //All Menu Definition here
    //Menu including: choice, choiceParameter, extendedChoice //just use choice
    //CascadeChoiceParameter, //use Cascade for reference
    //DynamicReferenceParameter //use Dynamic for complex implementation HTML
    //3.Environment
    //4.DeployServer
    //5.DeployPackage
    //6.ConfigureFile  
    //7.ConfigureContent
])])

3. Environment: Choice

  Definition: choice( name: 'Environment', description: '', choices: buildDefault(envList,'BAT') ),
  Method: 

  String buildDefault(List out,String key){
      def tmp=[]
      out.each{ if(it.contains(key)){ tmp.add(0, it) } else { tmp.add(it) } }
      return tmp
  } 
  First, we choose deployment Environment.

  Besides, we can use other Method.
  def getFile(String wksp, String dft){
    println("enter getFile()")
    def tmp=[]
    def out="ls ${wksp}/release  ".execute().text
    out.readLines().each{ if( it.contains(dft) ){ tmp.add(0,it) } else { tmp.add(it) } }
    return tmp
  } 
  def getPack(String mypath, String dft){
    println("enter getPack()")
    tmp=[]
    def out="ssh [email protected] ls ${mypath}/*.tar.gz".execute().text
    out.readLines().each{ if( it.contains(dft) ){ tmp.add(0,it) } else { tmp.add(it) } }
    return tmp
 } 
String getFileHub(String repo, String folder, String brch){
   def ret=[]
   def cmd = """curl https://api.github.com/repos/${repo}/git/trees/${brch}?recursive=2  """
   def out = cmd.execute().text
   def jsonSlurper = new JsonSlurper()
   def obj = jsonSlurper.parseText(out)
   obj['tree'].each{ if(it['path'].contains("${folder}/") ) { ret.add(it['path'])}  }
   if (ret.isEmpty()) {return ['NotFound']}
   return ret
}
 def getFileBit(String repo, String folder, String brch){
    def repoPR="https://api.bitbucket.org/2.0/repositories/$repo/src/${brch}/release"
    def ret=[]
    def cmd="curl --request GET ${repoPR}  "
    def out=cmd.execute().text
    def json=new JsonSlurper()
    def obj=json.parseText(out)
    obj['values'].each { ret.add(it['path'])}
    if (ret.isEmpty()) {return ['NotFound']}
    return ret
    }            

4. Server: CascadeChoice with Reference

  Definition: [$class: 'CascadeChoiceParameter', choiceType: 'PT_SINGLE_SELECT', filterLength: 1, filterable: false,
               name: 'Server', randomName: 'choice-parameter-16677189047472', referencedParameters: 'Environment', 
               script: [$class: 'GroovyScript', fallbackScript: [classpath: [], oldScript: '', sandbox: true, script: ''], 
               script: [classpath: [], oldScript: '', sandbox: true, 
               script: getServerScript('Environment') ]]], 
  Method:    
  String getServerScript(String refvar){
    def map=[:]
    envList.eachWithIndex{ it,index->
       map[it]=setDefault(serversList[it],defaultList[index])
    }
    return """def map=${map}
    |return map[${refvar}]
    |""".stripMargin()
  }
  When Environment is chosen, Deployment Server will come out automatically.

5. Package: CascadeChoice with Reference

  Definition: [$class: 'CascadeChoiceParameter', choiceType: 'PT_SINGLE_SELECT', filterLength: 1, filterable: false,
               name: 'Package', randomName: 'choice-parameter-16677189047489', referencedParameters: 'Environment', 
               script: [$class: 'GroovyScript', fallbackScript: [classpath: [], oldScript: '', sandbox: false, script: ''], 
               script: [classpath: [], oldScript: '', sandbox: false, 
               script: getPackScript('/root/workspace/myscripts','myfile') ]]], 
  Method:
  def getPackScript(String mypath, String dft){
      println("enter getPackScript()")
      return """tmp=[]
      |def out="ssh [email protected] ls ${mypath}/*.tar.gz".execute().text
      |out.readLines().each{ if( it.contains(\"${dft}\") ){ tmp.add(0,it) } else { tmp.add(it) } }
      |return tmp
      |""".stripMargin()
  }
  When put a package under mypath on deploy server, Package menu will update automatically.
  this method call xxxScript that means, we return a script by calling this method.

6. ConfigureFile: CascadeChoice with Reference

    Definition:
              [$class: 'CascadeChoiceParameter', choiceType: 'PT_SINGLE_SELECT', filterLength: 1, filterable: false,
               name: 'getFileBitScript', randomName: 'choice-parameter-16677189047450', referencedParameters: 'Environment', 
               script: [$class: 'GroovyScript', fallbackScript: [classpath: [], oldScript: '', sandbox: true, script: ''], 
               script: [classpath: [], oldScript: '', sandbox: true, 
               script: getFileHubScript("hqzhang/groovytest","releases",'mytest') ]]],
    Method:
    String getFileHubScript(String repo, String folder,String brch ){
       return """import groovy.json.JsonSlurper
       |def ret=[]
       |def cmd = "curl https://api.github.com/repos/${repo}/git/trees/${brch}?recursive=2  "
       |def out = cmd.execute().text
       |def jsonSlurper = new JsonSlurper()
       |def obj = jsonSlurper.parseText(out)
       |obj['tree'].each{ if(it['path'].contains("${folder}/") ) { ret.add(it['path'])}  }
       |if (ret.isEmpty()) {return ['NotFound']}
       |return ret
       | """.stripMargin()
     }
    When repo add file under ./releases/, ConfigFile will be update automatically.

7. Branches: CascadeChoice with Reference

    Definition:
    [$class: 'CascadeChoiceParameter', choiceType: 'PT_SINGLE_SELECT', filterLength: 1, filterable: false,
               name: 'BranchScript', randomName: 'choice-parameter-16677189047440', referencedParameters: 'Environment', 
               script: [$class: 'GroovyScript', fallbackScript: [classpath: [], oldScript: '', sandbox: true, script: ''], 
               script: [classpath: [], oldScript: '', sandbox: true, 
               script: getBranchScript(repo,brch) ]]],
    Method:
    String getBranchScript(String repo, String dft ){
    return """def ret=[]
       |def out = "git ls-remote --heads https://[email protected]/${repo}".execute().text
       |out = out.readLines().collect { it.split()[1].replaceAll('refs/heads/', '') }
       |out.each{ if( it.contains(\"${dft}\") ){ ret.add(0,it) } else { ret.add(it) } }
       |return ret
       | """.stripMargin()
    }

8. ConfigureContent: DynamicReference with Reference

    Definition:
           [$class: 'DynamicReferenceParameter', choiceType: 'ET_FORMATTED_HTML', name: 'ConfigContent',
            omitValueField: false, randomName: 'choice-parameter-138673186839723', referencedParameters: 'ConfigFile', 
            script: [$class: 'GroovyScript', fallbackScript: [classpath: [], oldScript: '', sandbox: false, script: ''],
            script: [classpath: [], oldScript: '', sandbox: false, 
            script: getContentScript(wksp,'ConfigFile')]] ],
    Method:
    def getContentScript(String wksp, String refvar ){
      println("enter getContentScript()....")
      return """
      |def out="cat ${wksp}/release/\${${refvar}}".execute().text
      |out=out.replaceAll('components:\\n','')
      |return \"\"\" <textarea name=\"value\"  value  class=\"setting-input  \" type=\"text\" rows="10" cols="25">\${out}</textarea> \"\"\"
      | """.stripMargin()
    }
    When ConfigFile is chosen, ConfigContent will be updated automatically.

8. Conclusion

 Following show an example of Jenkins Menu.
properties([
    //pipelineTriggers([bitbucketPush()]),
    parameters([
            choice( name: 'Environment', description: '', choices: buildDefault(envList,'BAT') ),
            [$class: 'CascadeChoiceParameter', choiceType: 'PT_SINGLE_SELECT', filterLength: 1, filterable: false,
               name: 'Server', randomName: 'choice-parameter-16677189047472', referencedParameters: 'Environment', 
               script: [$class: 'GroovyScript', fallbackScript: [classpath: [], oldScript: '', sandbox: true, script: ''], 
               script: [classpath: [], oldScript: '', sandbox: true, 
               script: getServerScript('Environment') ]]],

            [$class: 'CascadeChoiceParameter', choiceType: 'PT_SINGLE_SELECT', filterLength: 1, filterable: false,
               name: 'Package', randomName: 'choice-parameter-16677189047489', referencedParameters: 'filebackup', 
               script: [$class: 'GroovyScript', fallbackScript: [classpath: [], oldScript: '', sandbox: false, script: ''], 
               script: [classpath: [], oldScript: '', sandbox: false, 
               script: getPackScript('/root/workspace/myscripts','myfile') ]]],

            [ $class: 'CascadeChoiceParameter', choiceType: 'PT_SINGLE_SELECT', filterLength: 1, filterable: false,
               name: 'SolutionConfig', randomName: 'choice-parameter-16677189047798', referencedParameters: 'filebackup', 
               script: [$class: 'GroovyScript', fallbackScript: [classpath: [], oldScript: '', sandbox: false, script: ''], 
               script: [classpath: [], oldScript: '', sandbox: false, 
               script: getFileScript(wksp,'solution') ]]],

            [$class: 'DynamicReferenceParameter', choiceType: 'ET_FORMATTED_HTML', name: 'Component',
             omitValueField: false, randomName: 'choice-parameter-138673186839723', referencedParameters: 'SolutionConfig', 
            script: [$class: 'GroovyScript', fallbackScript: [classpath: [], oldScript: '', sandbox: false, script: ''],
                     script: [classpath: [], oldScript: '', sandbox: false, 
                              script: getContentScript(wksp,'SolutionConfig')]] ], 

9. Choice

choice( name: 'mypack', description: '', choices: getFile('/root/workspace/myscripts','tar.gz','myfile') ),
def getFile(String mypath,String type, String dft){
    println("enter getFile()")
    def out="ssh [email protected] ls ${mypath}/*.${type}".execute().text
    out=out.readLines().collect{ it }
    out.eachWithIndex{ it, id-> 
    if ( it.contains(dft) ){ index=id } }
    out.add(0, out.remove(index))
    return out
}

10. Cascade Choice

[$class: 'CascadeChoiceParameter', choiceType: 'PT_SINGLE_SELECT', filterLength: 1, filterable: false,
               name: 'dynpack', randomName: 'choice-parameter-16677189047472', referencedParameters: 'mypack', 
               script: [$class: 'GroovyScript', fallbackScript: [classpath: [], oldScript: '', sandbox: false, script: ''], 
               script: [classpath: [], oldScript: '', sandbox: false, 
               script:getFileScript('/root/workspace/myscripts/','tar.gz','myfile') ]]],
def getFileScript(String mypath,String type, String dft){
  return """
  |def out="ssh [email protected] ls ${mypath}/*.${type}".execute().text
  |out=out.readLines().collect{it}
  |out.eachWithIndex{ it, id-> 
  |if ( it.contains(\"${dft}\") ){ index=id } }
  |out.add(0, out.remove(index))
  |return out
  |""".stripMargin()
}

11. Dynamic Choice

[$class: 'DynamicReferenceParameter', choiceType: 'ET_FORMATTED_HTML', name: 'Component', 
             omitValueField: false, randomName: 'choice-parameter-138673186839723', referencedParameters: 'SolutionConfig', 
             script: [$class: 'GroovyScript', fallbackScript: [classpath: [], oldScript: '', sandbox: false, script: ''],
                     script: [classpath: [], oldScript: '', sandbox: false, 
                              script: getFileContHTML('SolutionConfig' )]] ], 
def getFileContHTML(String refvar, String mypath,String type){
    return """
      |def out="cat ${mypath}/\${${refvar}}.${yaml}".execute().text
      |out=out.replaceAll('components:\\n','')
      |return \"\"\"<textarea name=\"value\" value class=\"setting-input\" type=\"text\" rows="10" cols="25">\${out}</textarea> \"\"\"
      | """.stripMargin()
}    
def getFileTAB(String refvar, String mypath){
    println "enter getContent99=================================="
    return """
    |def yaml = new Yaml()
    |def ret=''
    |ret="cat ${mypath}/release/\${${refvar}}.yaml".execute().text
    |ret=(Map)yaml.load(ret)
    |def rendered = "<table><tr>"
    |ret.each { mark="-"; 
    | it.each { kk,vv->
    |  if ( kk != "name") {  mark="&nbsp;&nbsp;" }
    |  rendered = \"\"\"\${rendered}<tr>
    |  <td><input name=\"value\" alt=\"\${kk}\" json=\"\${kk}\" type=\"checkbox\" style=\"opacity:0\" class=\" \" checked>
    |  <span>\${mark}&nbsp;</span>
    |  <label name=\"value\" class=\" \" value=\"\${kk}\">\${kk}</label></td>
    |  <td><input  type=\"text\" class=\" \" name=\"value\" value=\"\${vv}\"> </br> </td></tr> \"\"\"    } }
    |return "\${rendered}</tr></table>"
    |""".stripMargin()
}

Jenkins configuration

There are 3 files created as part of the install for OSX for launching:

/Library/Preferences/org.jenkins-ci.plist

/Library/Application\ Support/Jenkins/jenkins-runner.sh

/Library/LaunchDaemons/org.jenkins-ci.plist

Jekins shared Library

1) in pipeline define: 
library("set-name-in-sysconfig@$verion") _
2) in vars define groovy file
//run command under directory , for example git command
@NonCPS
def exeCmd(String cmd, String directory){
    def command = cmd.split()
    def processBuilder = new ProcessBuilder(command)
    processBuilder.directory(new File(directory))
    def process = processBuilder.start()
    process.waitFor()
    def reader = new BufferedReader(new InputStreamReader(process.getInputStream()))
    def line = null
    def output=''
    while ((line = reader.readLine()) != null) {
        output = output +line+ "\n"
    }
    return output
}
@NonCPS
def gitStatus(String repoDir){
    def cmd="git status"
    def out=exeCmd(cmd,repoDir)
    return out
}

//run anycommand without directory
@NonCPS
def executeCmd(String cmd){
    def proc=cmd.execute()
    proc.waitFor()
    def out=proc.text
    def err=proc.exitValue()
    return [out,err]
}
def shellCmd(String cmd){
    println "define command to nexus/github/bitbucket"
    def data=[ version: "$version"]
    def boday=JsonOutput.toJson(JsonOutput.toJson(data))
    def cmd="""curl http://google.com --data $body"""

    println "execute and parse"
    def out=executeCmd(cmd)
    def out=proc.text
    def json=new JsonSlurper()
    def obj=json.parseText(out)
    println obj.values
    
    return [out,err]
}

Port Assignment

Jenkins-lts 9999
Nexus       8081

change Jenkins port

1. change file /usr/local/Cellar/jenkins-lts/2.235.1/homebrew.mxcl.jenkins-lts.plist
2. brew services restart jenkins-lts

Jenkins and Tool

0. Trigger Job
  job=Football
  user=hongqi
  token=b3923d9729b371fad60d46a8d3dbac44
  url="127.0.0.1:8080"
  jenksrc="java -jar jenkins-cli.jar -s http://${user}:${tokensrc}@${urlsrc}"

  echo "download cli.jar ..."
  # wget https://${user}:${token}@${url}/jnlpJars/jenkins-cli.jar

  echo "Trigger a build"
  buildNo0=$(curl -X GET http://${user}:${token}@${url}/job/${job}/lastBuild/buildNumber)
  curl -I -X POST http://${user}:${token}@${url}/job/${job}/build

  sleep 10
  echo "get job logs"
  buildNo=$(curl -X GET http://${user}:${token}@${url}/job/${job}/lastBuild/buildNumber)
  curl -X POST http://${user}:${token}@${url}/job/${job}/lastBuild/consoleText
  echo "build logs From:$buildNo0 to $buildNo"

1. Job clone
  user=hongqi
  token=b3923d9729b371fad60d46a8d3dxxx
  url="127.0.0.1:8080"
  jenksrc="java -jar jenkins-cli.jar -s http://${user}:${token}@${url}"
  token=b3923d9729b371fad60d46a8d3dyyy
  url="192.168.0.34:8080"
  jenktgt="java -jar jenkins-cli.jar -s http://${user}:${token}@${url}"
  plugurl="http://updates.jenkins-ci.org/download/plugins"

  echo "download cli.jar ..."
  #  wget https://${user}:${token}@${url}/jnlpJars/jenkins-cli.jar

  echo "Get Jobs List"
  jobs=$( ${jenktgt} list-jobs )
  echo ${jobs}

  for job in ${jobs}
  do
    echo "create job: ${job}"
    ${jenksrc} get-job  ${job} |${jenktgt} create-job ${job}
  done

2. plugins clone
  user=hongqi
  token=b3923d9729b371fad60d46a8d3dbxxx
  url="127.0.0.1:8080"
  jenksrc="java -jar jenkins-cli.jar -s http://${user}:${token}@${url}"
  token=b3923d9729b371fad60d46a8d3dbuuu
  url="127.0.0.1:8080"
  jenktgt="java -jar jenkins-cli.jar -s http://${user}:${token}@${url}"
  plugurl="http://updates.jenkins-ci.org/download/plugins"

  echo "download cli.jar a..."
  #  wget https://${user}:${token}@${url}/jnlpJars/jenkins-cli.jar

  echo "retrieve plugins info.."
  plugins=$(${jenksrc} list-plugins |sed -e 's/(.*)//' | awk '{print $1 "/" $NF "/" $1 ".hpi"}' )
  echo $plugins

  echo "install plugins on target"
  for var in ${plugins}
  do
        echo "install plugin: ${plugurl}/${var}"
        ${jenktgt} install-plugin parameterized-trigger ${plugurl}/${var}
  done

3. Jenkins.war clone (upgrage)
  download new jenkins.war
  warurl="http://updates.jenkins-ci.org/download/war"
  wget ${warurl}/2.204.1/jenkins.war

  find java.class.path in jenkins system info and copy war
  macos: cp jenkins.war /usr/local/opt/jenkins-lts/libexec/jenkins.war
  Ubuntu: cp jenkins.war /usr/share/jenkins
   
  restart jenkins

Jenkinsfile vs Groovy

Jenkinsfile is coded by Groovy, I will introduce as following
1. Shared Library
   @Library('mygroovylibrary') _.      //defind groovy lib in Jenkins system config.
   import groovy.json.JsonSlurper

2. File Read/write
   def amap = 
      ['something': 'my datas',
       'size': 3,'isEmpty': false]
   sh "rm datas.yaml output.json"
   writeYaml(file: 'datas.yaml', data: amap)
   writeJSON( file: 'output.json', json: amap, pretty: 4)
   sh "cat output.json"
   sh "cat datas.yaml"
   def read = readJSON( file: 'output.json')
   println read
   def myrd = readYaml( file: 'datas.yaml')
   println myrd

3. Docker Ops
   echo "Stage: Build Docker Image"
   def myimg = docker.build("myimage")
   echo "Tag Docker Image ${myimg}"
   def mytag = myimg.tag("mytag1")
   echo "tag result: ${mytag}"

   echo "Login Docker Hub"
   docker.withRegistry('https://index.docker.io/v1/', 'docker_id'){
       echo "Push Docker Image"
       myimg.push()
   }
   echo "Remove Docker Image"
   sh "docker rmi $myapp"

   echo "Run Docker Image"
   def myarg="--name mynginx-app -p ${myport}:${myport}"
   def mycon = myimg.run(myarg)

   echo "Run Docker Image"
   def myarg="--name mynginx-app -p ${myport}:${myport}"
   def mycon = myimg.run(myarg)

   echo "and then remove the container"
   mycon.stop()                
                 
4. Openshift Ops
   echo "Login to openshift localOC"
   openshift.withCluster("localOC"){
       echo "Switch to project..."
       openshift.withProject("myproject"){
           echo "Turn on debug..."
           openshift.verbose()
           openshift.logLevel(3)

           def tmp = pwd()
           echo "Deploy file:  ${tmp}/projecttemp.yaml"
           String tempFile = new File(tmp+'/projecttemp.yaml').getText('UTF-8')
           echo "Start process template to create kubemodel"
           def mykube = openshift.process(tempFile)
           "Deploy by kube model")
           def mycrt = openshift.create(mykube)
      }
  }

//Jenkinsfile (Scripted Pipeline)
@Library('mygroovylibrary') _.      //defind groovy lib in Jenkins system config.
import groovy.json.JsonSlurper
pipeline {
    agent { node('master')}.  //define target to run

    parameters {
        extendedChoice( name: 'TagName', defaultValue: '', description: 'tag name',
            type: 'PT_SINGLE_SELECT',
            groovyScript: """def gettags = ("git ls-remote -t https://github.com/hqzhang/octest.git").execute()
               return gettags.text.readLines().collect { it.split()[1].replaceAll('refs/tags/', '').replaceAll("\\\\^\\\\{\\\\}", '')}
                          """,)
        choice(name: 'project', choices: ['localOC'], description: 'input cluster')
        choice(name: 'cluster', choices: ['myproject'], description: 'input project(namespace)')
        booleanParam(name: 'deployCfg', defaultValue: true, description: 'deploy deployConfig')
        booleanParam(name: 'imgStr', defaultValue: true, description: 'deploy imageStream')
        booleanParam(name: 'service', defaultValue: true, description: 'deploy service')
        booleanParam(name: 'route', defaultValue: true, description: 'deploy route')
        booleanParam(name: 'configMaps', defaultValue: true, description: 'deploy configmaps')
        booleanParam(name: 'secrets', defaultValue: true, description: 'deploy secrets')
        string(name: 'StringSet', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
        password(name: 'PasswordSet', defaultValue: 'SECRET', description: 'Enter a password')
    }
    triggers { pollSCM('*/1 * * * *') }  //define build polling trigger 
    options { timestamps () }             //define log timestamp
    stages {
         stage('Sonarqube Openeration') {
           environment {.   scanner = tool 'Sonar-Scanner' }
           steps {
               script {
               println(scanner)
               echo "run with bash"
               sh """mvn compile sonar:sonar \
                   -Dsonar.projectKey=mytest \
                   -Dsonar.host.url=http://localhost:9000 \
                   -Dsonar.login=cd2ff10b50b4055aa5d4988208e4dcdfa3c861e6
                  """
               echo "run with Env"
               withSonarQubeEnv('SonarQubeServer') {
                 sh """mvn compile sonar:sonar  \
                          -Dsonar.projectKey=mytest \
                          -Dsonar.java.binaries=./target/classes
                   """
               }
               echo "run with scanner"
               withSonarQubeEnv('SonarQubeServer') {
                 sh """${scanner}/bin/sonar-scanner -v """
                 sh """${scanner}/bin/sonar-scanner 
                      -Dsonar.projectKey=mytest 
                      -Dsonar.java.binaries=./target/classes
                  """ 
               }
               echo "run with docker"
               def
            }
           }
        }
        stage('Stage: Openshift Openeration...'){
            steps {
                script {
                    echo "Stage: Initial and Clean..."
                    echo "Input Parameters: ${params}"
                    echo "Deploy ${params.project} in ${params.cluster}"
                    //login to openshift and enter project(namespace)
                    openshift.withCluster("localOC"){
                        openshift.withProject("myproject"){
                            def mycluster = openshift.cluster()
                            def myproject = openshift.project()
                            echo "deploy $myproject in $mycluster"

                            echo "clean all stuff--dc,is,svc,route"
                            def mydc = openshift.selector('dc').delete()
                            def mysvc = openshift.selector('svc').delete()
                            def myis = openshift.selector('is').delete()
                            def myrte= openshift.selector('route').delete()
                        }
                    }
                }
            }
        }

start Jenkins on mac

sudo launchctl load /Library/LaunchDaemons/org.jenkins-ci.plist

# stop Jenkins on mac
sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
#add the default parameters - this will edit /Library/Preferences/org.jenkins-ci.plist

sudo defaults write /Library/Preferences/org.jenkins-ci httpPort 7070

#*****How to Install Jenkins

Jenkins is a schedulor server for executing git or shell script.
It is a center of continuous integration and continuous delivery for software development.

1. install jenkins
   sudo apt-get install java-1.8.0-openjdk 
   wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
   sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
   sudo apt-get update
   sudo apt-get install jenkins

2. config file /etc/init.d/jenkins
   change default 8080 to any number.

3. http://localhost:8080 
   passwd: cat cat /var/lib/jenkins/secrets/initialAdminPassword
   
4. click button for install suguested plogins and then set a addmin user/passwd

#*****How to Use Jenkins

1. setup a github account :https://github.com/
   and create a repository in github.com

2. New item button for create new project with freestyple.

3. Set input data from other project
   click This project is parameterized: and add the Run parameter,ie PARAMETER_NAME
  PARAMETER_NAME=<jenkins_url>/job/<job_name>/<run_number>/
  PARAMETER_NAME_JOBNAME=<job_name>
  PARAMETER_NAME_NUMBER=<run_number>
  PARAMETER_NAME_NAME=<display_name>
  PARAMETER_NAME_RESULT=<run_result>

4. set input source tree from github
   Source Code Management: git : https://github.com/hqzhang/Mytest.git
   and credential by ssh key

5. set build name and put command/shell script into (including compiling; running and testing)
   Build: Execute Shell
 
6. Set output data in section:
  Post-build Actions: Archive artifacts

About Jenkins pipeline and Jenkinsfile

1.install jenkins 2.0
2.create pipeline Job
3.create jenkinsfile in https://github.com/hqzhang/Mytest.git:
     set jenkinsfile from github above and filename: jenkinsfile
4.build now:
pipeline {it
    agent any
    stages {
        stage('Build') {
            steps {
                echo 'Building..'
            }
        }
        stage('Test') {
            steps {
                echo 'Testing..'
            }
        }
        stage('Deploy') {
            steps {
                echo 'Deploying....'
            }
        }
    }
}
node {
    stage 'Clone the project'
    git 'https://github.com/eugenp/tutorials.git'
    dir('spring-jenkins-pipeline') {
        stage("Compilation and Analysis") {
            parallel 'Compilation': {
                sh "./mvnw clean install -DskipTests"
            }, 'Static Analysis': {
                stage("Checkstyle") {
                    sh "./mvnw checkstyle:checkstyle"              
                    step([$class: 'CheckStylePublisher',
                      canRunOnFailed: true,
                      defaultEncoding: '',
                      healthy: '100',
                      pattern: '**/target/checkstyle-result.xml',
                      unHealthy: '90',
                      useStableBuildAsReference: true
                    ])
                }
            }
        }
        stage("Tests and Deployment") {
            parallel 'Unit tests': {
                stage("Runing unit tests") {
                    try {
                        sh "./mvnw test -Punit"
                    } catch(err) {
                        step([$class: 'JUnitResultArchiver', testResults: 
                          '**/target/surefire-reports/TEST-*UnitTest.xml'])
                        throw err
                    }
                   step([$class: 'JUnitResultArchiver', testResults: 
                     '**/target/surefire-reports/TEST-*UnitTest.xml'])
                }
            }, 'Integration tests': {
                stage("Runing integration tests") {
                    try {
                        sh "./mvnw test -Pintegration"
                    } catch(err) {
                        step([$class: 'JUnitResultArchiver', testResults: 
                          '**/target/surefire-reports/TEST-'
                            + '*IntegrationTest.xml'])
                        throw err
                    }
                    step([$class: 'JUnitResultArchiver', testResults: 
                      '**/target/surefire-reports/TEST-'
                        + '*IntegrationTest.xml'])
                }
            }
            stage("Staging") {
                sh "pid=\$(lsof -i:8989 -t); kill -TERM \$pid "
                  + "|| kill -KILL \$pid"
                withEnv(['JENKINS_NODE_COOKIE=dontkill']) {
                    sh 'nohup ./mvnw spring-boot:run -Dserver.port=8989 &'
                }   
            }
        }
    }
}
⚠️ **GitHub.com Fallback** ⚠️