web-dev-qa-db-fra.com

Vérifier l'état du travail Jenkins après avoir déclenché une génération à distance

J'ai un script pour déclencher un travail sur Jenkins à distance en utilisant un jeton. Voici mon script:

JENKINS_URL='http://jenkins.myserver.com/jenkins'
JOB_NAME='job/utilities/job/my_job'
JOB_TOKEN='my_token'

curl "${JENKINS_URL}/${JOB_NAME}/buildWithParameters?token=${JOB_TOKEN}"

Après l'avoir exécuté, j'obtiens la réponse suivante:

* Hostname was NOT found in DNS cache
*   Trying 10.5.187.225...
* Connected to jenkins.myserver.com (10.5.187.225) port 80 (#0)
> GET /jenkins/job/utilities/job/my_job/buildWithParameters?token=my_token HTTP/1.1
> User-Agent: curl/7.37.1
> Host: jenkins.myserver.com
> Accept: */*
> 
< HTTP/1.1 201 Created
* Server nginx/1.6.2 is not blacklisted
< Server: nginx/1.6.2
< Date: Tue, 03 Feb 2015 23:40:47 GMT
< Content-Length: 0
< Location: http://jenkins.myserver.com/jenkins/queue/item/91/
< Connection: keep-alive
< Cache-Control: private
< Expires: Wed, 31 Dec 1969 16:00:00 PST
< 
* Connection #0 to Host jenkins.myserver.com left intact

J'ai remarqué qu'il renvoie l'url de la file d'attente dans l'en-tête: http://jenkins.myserver.com/jenkins/queue/item/91 . Mais je ne sais pas comment utiliser cette URL de retour.

1) Je me demande si quelqu'un sait comment vérifier le statut de l'emploi que je viens de créer?

2) Étant donné que la réponse ci-dessus ne renvoie pas le travail #, je ne peux pas vraiment utiliser cet appel api:

curl http://jenkins.myserver.com/jenkins/job/utilities/job/my_job/8/api/json

pour vérifier l'état. Alors, où puis-je obtenir le nom et le numéro du travail après avoir obtenu l'URL de l'emplacement à partir de la réponse ci-dessus?

Merci

13
Nam Nguyen

Lorsque vous déclenchez un travail, le travail est placé dans la file d'attente. La version réelle est créée uniquement lorsqu'elle commence à s'exécuter et à ce stade, la version obtient un numéro de version. Si tous vos exécuteurs sont occupés, il peut parfois s'écouler un certain temps avant que la génération soit créée et commence à s'exécuter.

La seule façon d'obtenir le numéro de build lors du déclenchement d'un travail est d'utiliser la commande "build" de la Jenkins CLI . Si vous utilisez l'option -w, la commande ne reviendra que lorsque la construction commencera, puis elle affichera "Démarrage de la construction #N"

Vous n'avez pas réellement besoin du Java cli.jar, juste un client ssh suffit. Voir https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+ SSH

À part cela, il n'y a pas de solution connue. Vous pourrez peut-être parcourir les versions et en trouver une qui a été déclenchée au moment où vous avez déclenché le travail, mais cela représente beaucoup de travail.

7
sti

J'ai résolu ce problème en utilisant l'interrogation du serveur Jenkins. Lorsqu'un travail est démarré à distance, les en-têtes de retour ont l'URL de la file d'attente des travaux. L'utilisation de celui-ci peut faire plus d'appels API pour obtenir le statut.

Pas:

  • commencer le travail
  • retour d'analyse en-tête "Emplacement"
  • interroger la file d'attente à la recherche d'un travail pour commencer
    • l'entrée de la file d'attente des travaux aura une entrée 'exécutable' dans son json ou xml avec le numéro de travail une fois qu'elle aura commencé
  • interroger le statut du travail en attente d'un résultat

J'ai utilisé python et le module Requests pour ce faire

#!/usr/bin/python

import requests
import re
import sys 
import json
import time

# secs for polling Jenkins API
#
QUEUE_POLL_INTERVAL = 2 
JOB_POLL_INTERVAL = 20
OVERALL_TIMEOUT = 3600 # 1 hour

# job specifics: should be passed in
auth_token = 'buildmaster:173223588624f980c3AAA68d4d8efe0c'
jenkins_uri = '192.168.115.187:8080'
job_name = 'rf_systest'
build_token = 'rf_systest_auth_token'

# start the build
#
start_build_url = 'http://{}@{}/job/{}/build?token={}'.format(
        auth_token, jenkins_uri, job_name, build_token)
r = requests.post(start_build_url)

# from return headers get job queue location
#
m = re.match(r"http.+(queue.+)\/", r.headers['Location'])
if not m:
    # To Do: handle error
    print "Job starte request did not have queue location"
    sys.exit(1)

# poll the queue looking for job to start
#
queue_id = m.group(1)
job_info_url = 'http://{}@{}/{}/api/json'.format(auth_token, jenkins_uri, queue_id)
elasped_time = 0 
print '{} Job {} added to queue: {}'.format(time.ctime(), job_name, job_info_url)
while True:
    l = requests.get(job_info_url)
    jqe = l.json()
    task = jqe['task']['name']
    try:
        job_id = jqe['executable']['number']
        break
    except:
        #print "no job ID yet for build: {}".format(task)
        time.sleep(QUEUE_POLL_INTERVAL)
        elasped_time += QUEUE_POLL_INTERVAL

    if (elasped_time % (QUEUE_POLL_INTERVAL * 10)) == 0:
        print "{}: Job {} not started yet from {}".format(time.ctime(), job_name, queue_id)

# poll job status waiting for a result
#
job_url = 'http://{}@{}/job/{}/{}/api/json'.format(auth_token, jenkins_uri, job_name, job_id)
start_Epoch = int(time.time())
while True:
    print "{}: Job started URL: {}".format(time.ctime(), job_url)
    j = requests.get(job_url)
    jje = j.json()
    result = jje['result']
    if result == 'SUCCESS':
        # Do success steps
        print "{}: Job: {} Status: {}".format(time.ctime(), job_name, result)
        break
    Elif result == 'FAILURE':
        # Do failure steps
        print "{}: Job: {} Status: {}".format(time.ctime(), job_name, result)
        break
    Elif result == 'ABORTED':
        # Do aborted steps
        print "{}: Job: {} Status: {}".format(time.ctime(), job_name, result)
        break
    else:
        print "{}: Job: {} Status: {}. Polling again in {} secs".format(
                time.ctime(), job_name, result, JOB_POLL_INTERVAL)

    cur_Epoch = int(time.time())
    if (cur_Epoch - start_Epoch) > OVERALL_TIMEOUT:
        print "{}: No status before timeout of {} secs".format(OVERALL_TIMEOUT)
        sys.exit(1)

    time.sleep(JOB_POLL_INTERVAL)

Production:

Tue Jan 30 16:24:08 2018: Job rf_systest added to queue: http://buildmaster:[email protected]:8080/queue/item/164/api/json
Tue Jan 30 16:24:39 2018: Job rf_systest not started yet from queue/item/164
Tue Jan 30 16:25:00 2018: Job started URL: http://buildmaster:[email protected]:8080/job/rf_systest/79/api/json
Tue Jan 30 16:25:01 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:25:21 2018: Job started URL: http://buildmaster:[email protected]:8080/job/rf_systest/79/api/json
Tue Jan 30 16:25:21 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:25:41 2018: Job started URL: http://buildmaster:[email protected]:8080/job/rf_systest/79/api/json
Tue Jan 30 16:25:41 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:26:01 2018: Job started URL: http://buildmaster:[email protected]:8080/job/rf_systest/79/api/json
Tue Jan 30 16:26:01 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:26:21 2018: Job started URL: http://buildmaster:[email protected]:8080/job/rf_systest/79/api/json
Tue Jan 30 16:26:21 2018: Job: rf_systest Status: SUCCESS

JSON d'une file d'attente Jenkins une fois que son travail a commencé:

{
    "_class": "hudson.model.Queue$LeftItem",
    "actions": [
        {
            "_class": "hudson.model.CauseAction",
            "causes": [
                {
                    "_class": "hudson.model.Cause$RemoteCause",
                    "addr": "10.20.30.60",
                    "note": null,
                    "shortDescription": "Started by remote Host 10.20.30.60"
                }
            ]
        }
    ],
    "blocked": false,
    "buildable": false,
    "cancelled": false,
    "executable": {
        "_class": "org.jenkinsci.plugins.workflow.job.WorkflowRun",
        "number": 45,
        "url": "http://192.168.115.187:8080/job/rf_systest/45/"
    },
    "id": 95,
    "inQueueSince": 1517342648136,
    "params": "",
    "stuck": false,
    "task": {
        "_class": "org.jenkinsci.plugins.workflow.job.WorkflowJob",
        "color": "blue_anime",
        "name": "rf_systest",
        "url": "http://192.168.115.187:8080/job/rf_systest/"
    },
    "url": "queue/item/95/",
    "why": null
}
8
P. Hawkins

Vous pouvez utiliser l'API Jenkins pour cela. Un exemple de script Python:

import json
import requests
import time



job_name = "testjob" .  #Give your job name here


def jenkins_job_status(job_name):

        try:
                url  = "https://your_jenkins_endpoint/job/%s/lastBuild/api/json" %job_name   #Replace 'your_jenkins_endpoint' with your Jenkins URL
                while True:
                        data = requests.get(url).json()
                        if data['building']:
                                time.sleep(60)
                        else:
                                if data['result'] == "SUCCESS":

                                        print "Job is success"
                                        return True
                                else:
                                        print "Job status failed"
                                        return False


        except Exception as e:
                print str(e)
                return False




if __name__ == "__main__":

        if jenkins_job_status(job_name):

                print "Put your autmation here for 'job is success' condition"

        else:
                print "Put your autmation here for 'job is failed' condition" 

Reportez-vous http://www.easyaslinux.com/tutorials/devops/how-to-check-build-status-of-jenkins-job-using-python-script/ pour une explication détaillée

4
Nijil

J'ai eu un problème similaire pour obtenir l'état avec l'api de repos uniquement.
c'était ma solution (c'est une solution faible et pas stable!):

#Ex. http://jenkins.com/job/test
JOB_URL="${JENKINS_URL}/job/${JOB_NAME}"

#here you can ask for next build job number
function getNextBuildNr(){
  curl --silent ${JOB_URL}/api/json | grep -Po '"nextBuildNumber":\K\d+'
}    

# this will request the Status of job
function getBuildState(){
  buildNr=$1
  curl --silent ${JOB_URL}/${buildNr}/api/json | grep -Po '"result":\s*"\K\w+'
}

#this will wait for your Job state, by polling Jenkins every second
function waitForJob() {
  buildNr=$1
  state=""

  while [ "${state}" == "" ]
  do
     sleep 1
     state=$(getBuildState ${buildNr})
     echo -n '.'
  done

  echo -e "\n"
}

#now you can run and build
BUILD_NR=$(getNextBuildNr)

# input here your code/function to trigger the job

waitForJob ${BUILD_NR}
BUILD_STATE=$(getBuildState ${BUILD_NR})
echo "$BUILD_STATE"
1
ya_dimon