2011-06-03 16:51:39 +01:00
#!/usr/bin/env python
# Software License Agreement (BSD License)
#
# Copyright (c) 2010, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
2011-07-11 21:55:58 -07:00
# Authors:
# Ken Conley <kwc@willowgarage.com>
# James Page <james.page@canonical.com>
# Tully Foote <tfoote@willowgarage.com>
2011-07-14 11:16:22 +01:00
# Matthew Gertner <matthew.gertner@gmail.com>
2011-06-03 16:51:39 +01:00
'''
Python API for Jenkins
2011-09-03 17:00:30 -07:00
Examples : :
2011-06-03 16:51:39 +01:00
2011-09-03 17:00:30 -07:00
j = jenkins . Jenkins ( ' http://your_url_here ' , ' username ' , ' password ' )
j . get_jobs ( )
j . create_job ( ' empty ' , jenkins . EMPTY_CONFIG_XML )
j . disable_job ( ' empty ' )
j . copy_job ( ' empty ' , ' empty_copy ' )
j . enable_job ( ' empty_copy ' )
j . reconfig_job ( ' empty_copy ' , jenkins . RECONFIG_XML )
2011-06-03 16:51:39 +01:00
2011-09-03 17:00:30 -07:00
j . delete_job ( ' empty ' )
j . delete_job ( ' empty_copy ' )
2011-06-03 16:51:39 +01:00
# build a parameterized job
2013-04-13 20:35:11 +02:00
j . build_job ( ' api-test ' , {
' param1 ' : ' test value 1 ' ,
' param2 ' : ' test value 2 ' ,
} )
2011-06-03 16:51:39 +01:00
'''
2013-04-13 20:35:11 +02:00
#import sys
2011-06-03 16:51:39 +01:00
import urllib2
import urllib
import base64
2013-04-13 20:35:11 +02:00
#import traceback
2011-06-03 16:51:39 +01:00
import json
2011-07-19 17:06:18 +01:00
import httplib
2011-06-03 16:51:39 +01:00
2013-04-13 20:35:11 +02:00
LAUNCHER_SSH = ' hudson.plugins.sshslaves.SSHLauncher '
LAUNCHER_COMMAND = ' hudson.slaves.CommandLauncher '
2012-06-20 14:41:59 -07:00
LAUNCHER_WINDOWS_SERVICE = ' hudson.os.windows.ManagedWindowsServiceLauncher '
2013-04-13 20:35:11 +02:00
INFO = ' api/json '
JOB_INFO = ' job/ %(name)s /api/json?depth=0 '
Q_INFO = ' queue/api/json?depth=0 '
2012-06-20 14:41:59 -07:00
CANCEL_QUEUE = ' queue/item/ %(number)s /cancelQueue '
2013-04-13 20:35:11 +02:00
CREATE_JOB = ' createItem?name= %(name)s ' # also post config.xml
CONFIG_JOB = ' job/ %(name)s /config.xml '
DELETE_JOB = ' job/ %(name)s /doDelete '
ENABLE_JOB = ' job/ %(name)s /enable '
DISABLE_JOB = ' job/ %(name)s /disable '
COPY_JOB = ' createItem?name= %(to_name)s &mode=copy&from= %(from_name)s '
BUILD_JOB = ' job/ %(name)s /build '
STOP_BUILD = ' job/ %(name)s / %(number)s /stop '
2011-06-03 16:51:39 +01:00
BUILD_WITH_PARAMS_JOB = ' job/ %(name)s /buildWithParameters '
2013-04-13 20:35:11 +02:00
BUILD_INFO = ' job/ %(name)s / %(number)d /api/json?depth=0 '
2011-06-03 16:51:39 +01:00
CREATE_NODE = ' computer/doCreateItem? %s '
DELETE_NODE = ' computer/ %(name)s /doDelete '
2013-04-13 20:35:11 +02:00
NODE_INFO = ' computer/ %(name)s /api/json?depth=0 '
NODE_TYPE = ' hudson.slaves.DumbSlave$DescriptorImpl '
2012-06-25 12:48:32 +01:00
TOGGLE_OFFLINE = ' computer/ %(name)s /toggleOffline?offlineMessage= %(msg)s '
2011-06-03 16:51:39 +01:00
#for testing only
EMPTY_CONFIG_XML = ''' <?xml version= ' 1.0 ' encoding= ' UTF-8 ' ?>
< project >
< keepDependencies > false < / keepDependencies >
< properties / >
< scm class = ' jenkins.scm.NullSCM ' / >
< canRoam > true < / canRoam >
< disabled > false < / disabled >
< blockBuildWhenUpstreamBuilding > false < / blockBuildWhenUpstreamBuilding >
< triggers class = ' vector ' / >
< concurrentBuild > false < / concurrentBuild >
< builders / >
< publishers / >
< buildWrappers / >
< / project > '''
#for testing only
RECONFIG_XML = ''' <?xml version= ' 1.0 ' encoding= ' UTF-8 ' ?>
< project >
< keepDependencies > false < / keepDependencies >
< properties / >
< scm class = ' jenkins.scm.NullSCM ' / >
< canRoam > true < / canRoam >
< disabled > false < / disabled >
< blockBuildWhenUpstreamBuilding > false < / blockBuildWhenUpstreamBuilding >
< triggers class = ' vector ' / >
< concurrentBuild > false < / concurrentBuild >
2013-04-13 20:35:11 +02:00
< builders >
< jenkins . tasks . Shell >
< command > export FOO = bar < / command >
< / jenkins . tasks . Shell >
< / builders >
2011-06-03 16:51:39 +01:00
< publishers / >
< buildWrappers / >
< / project > '''
2013-04-13 20:35:11 +02:00
2011-09-03 17:00:30 -07:00
class JenkinsException ( Exception ) :
'''
General exception type for jenkins - API - related failures .
'''
pass
2011-06-03 16:51:39 +01:00
2013-04-13 20:35:11 +02:00
2011-06-03 16:51:39 +01:00
def auth_headers ( username , password ) :
'''
2013-04-13 20:35:11 +02:00
Simple implementation of HTTP Basic Authentication . Returns the
' Authentication ' header value .
2011-06-03 16:51:39 +01:00
'''
return ' Basic ' + base64 . encodestring ( ' %s : %s ' % ( username , password ) ) [ : - 1 ]
2013-04-13 20:35:11 +02:00
2011-06-03 16:51:39 +01:00
class Jenkins ( object ) :
2012-03-02 16:26:13 +00:00
2011-06-03 16:51:39 +01:00
def __init__ ( self , url , username = None , password = None ) :
'''
Create handle to Jenkins instance .
2011-09-03 17:00:30 -07:00
: param url : URL of Jenkins server , ` ` str ` `
2011-06-03 16:51:39 +01:00
'''
if url [ - 1 ] == ' / ' :
self . server = url
else :
self . server = url + ' / '
2012-03-02 16:26:13 +00:00
if username is not None and password is not None :
2011-06-03 16:51:39 +01:00
self . auth = auth_headers ( username , password )
else :
self . auth = None
2012-03-02 16:26:13 +00:00
2011-06-03 16:51:39 +01:00
def get_job_info ( self , name ) :
2011-09-03 17:24:56 -07:00
'''
Get job information dictionary .
: param name : Job name , ` ` str ` `
: returns : dictionary of job information
'''
2011-06-03 16:51:39 +01:00
try :
2013-04-13 20:35:11 +02:00
response = self . jenkins_open ( urllib2 . Request (
self . server + JOB_INFO % locals ( ) ) )
2011-07-19 17:06:18 +01:00
if response :
return json . loads ( response )
else :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' job[ %s ] does not exist ' % name )
2011-07-19 17:06:18 +01:00
except urllib2 . HTTPError :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' job[ %s ] does not exist ' % name )
2011-07-19 17:06:18 +01:00
except ValueError :
2013-04-13 20:35:11 +02:00
raise JenkinsException (
" Could not parse JSON info for job[ %s ] " % name )
2012-03-02 16:26:13 +00:00
2011-06-03 16:51:39 +01:00
def debug_job_info ( self , job_name ) :
'''
Print out job info in more readable format
'''
for k , v in self . get_job_info ( job_name ) . iteritems ( ) :
print k , v
def jenkins_open ( self , req ) :
'''
2013-04-13 20:35:11 +02:00
Utility routine for opening an HTTP request to a Jenkins server . This
should only be used to extends the : class : ` Jenkins ` API .
2011-06-03 16:51:39 +01:00
'''
try :
if self . auth :
req . add_header ( ' Authorization ' , self . auth )
return urllib2 . urlopen ( req ) . read ( )
except urllib2 . HTTPError , e :
2013-04-13 20:35:11 +02:00
# Jenkins's funky authentication means its nigh impossible to
# distinguish errors.
2011-06-03 16:51:39 +01:00
if e . code in [ 401 , 403 , 500 ] :
2013-04-13 20:35:11 +02:00
raise JenkinsException (
' Error in request. ' +
' Possibly authentication failed [ %s ] ' % ( e . code )
)
2011-06-03 16:51:39 +01:00
# right now I'm getting 302 infinites on a successful delete
2012-02-29 10:23:45 -07:00
def get_build_info ( self , name , number ) :
2012-03-01 11:03:09 -07:00
'''
2012-03-02 16:26:13 +00:00
Get build information dictionary .
2012-03-01 11:03:09 -07:00
2012-03-02 16:26:13 +00:00
: param name : Job name , ` ` str ` `
: param name : Build number , ` ` int ` `
: returns : dictionary of build information , ` ` dict ` `
2012-03-01 11:03:09 -07:00
Example : :
>> > next_build_number = j . get_job_info ( ' build_name ' ) [ ' next_build_number ' ]
>> > output = j . build_job ( ' build_ ' + kwargs [ ' vcs_server_type ' ] , params )
>> > sleep ( 10 )
>> > build_info = j . get_build_info ( ' build_name ' , next_build_number )
>> > print ( build_info )
{ u ' building ' : False , u ' changeSet ' : { u ' items ' : [ { u ' date ' : u ' 2011-12-19T18:01:52.540557Z ' , u ' msg ' : u ' test ' , u ' revision ' : 66 , u ' user ' : u ' unknown ' , u ' paths ' : [ { u ' editType ' : u ' edit ' , u ' file ' : u ' /branches/demo/index.html ' } ] } ] , u ' kind ' : u ' svn ' , u ' revisions ' : [ { u ' module ' : u ' http://eaas-svn01.i3.level3.com/eaas ' , u ' revision ' : 66 } ] } , u ' builtOn ' : u ' ' , u ' description ' : None , u ' artifacts ' : [ { u ' relativePath ' : u ' dist/eaas-87-2011-12-19_18-01-57.war ' , u ' displayPath ' : u ' eaas-87-2011-12-19_18-01-57.war ' , u ' fileName ' : u ' eaas-87-2011-12-19_18-01-57.war ' } , { u ' relativePath ' : u ' dist/eaas-87-2011-12-19_18-01-57.war.zip ' , u ' displayPath ' : u ' eaas-87-2011-12-19_18-01-57.war.zip ' , u ' fileName ' : u ' eaas-87-2011-12-19_18-01-57.war.zip ' } ] , u ' timestamp ' : 1324317717000 , u ' number ' : 87 , u ' actions ' : [ { u ' parameters ' : [ { u ' name ' : u ' SERVICE_NAME ' , u ' value ' : u ' eaas ' } , { u ' name ' : u ' PROJECT_NAME ' , u ' value ' : u ' demo ' } ] } , { u ' causes ' : [ { u ' userName ' : u ' anonymous ' , u ' shortDescription ' : u ' Started by user anonymous ' } ] } , { } , { } , { } ] , u ' id ' : u ' 2011-12-19_18-01-57 ' , u ' keepLog ' : False , u ' url ' : u ' http://eaas-jenkins01.i3.level3.com:9080/job/build_war/87/ ' , u ' culprits ' : [ { u ' absoluteUrl ' : u ' http://eaas-jenkins01.i3.level3.com:9080/user/unknown ' , u ' fullName ' : u ' unknown ' } ] , u ' result ' : u ' SUCCESS ' , u ' duration ' : 8826 , u ' fullDisplayName ' : u ' build_war #87 ' }
'''
2012-02-29 10:23:45 -07:00
try :
2013-04-13 20:35:11 +02:00
response = self . jenkins_open ( urllib2 . Request (
self . server + BUILD_INFO % locals ( ) ) )
2012-02-29 10:23:45 -07:00
if response :
return json . loads ( response )
else :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' job[ %s ] number[ %d ] does not exist '
% ( name , number ) )
2012-02-29 10:23:45 -07:00
except urllib2 . HTTPError :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' job[ %s ] number[ %d ] does not exist '
% ( name , number ) )
2012-02-29 10:23:45 -07:00
except ValueError :
2013-04-13 20:35:11 +02:00
raise JenkinsException (
' Could not parse JSON info for job[ %s ] number[ %d ] '
% ( name , number )
)
2012-03-02 16:26:13 +00:00
2011-06-03 16:51:39 +01:00
def get_queue_info ( self ) :
'''
2011-09-03 17:00:30 -07:00
: returns : list of job dictionaries , ` ` [ dict ] ` `
Example : :
>> > queue_info = j . get_queue_info ( )
>> > print ( queue_info [ 0 ] )
{ u ' task ' : { u ' url ' : u ' http://your_url/job/my_job/ ' , u ' color ' : u ' aborted_anime ' , u ' name ' : u ' my_job ' } , u ' stuck ' : False , u ' actions ' : [ { u ' causes ' : [ { u ' shortDescription ' : u ' Started by timer ' } ] } ] , u ' buildable ' : False , u ' params ' : u ' ' , u ' buildableStartMilliseconds ' : 1315087293316 , u ' why ' : u ' Build #2,532 is already in progress (ETA:10 min) ' , u ' blocked ' : True }
2011-06-03 16:51:39 +01:00
'''
2013-04-13 20:35:11 +02:00
return json . loads ( self . jenkins_open (
urllib2 . Request ( self . server + Q_INFO )
) ) [ ' items ' ]
2011-06-03 16:51:39 +01:00
2012-06-20 14:41:59 -07:00
def cancel_queue ( self , number ) :
'''
Cancel a queued build .
: param number : Jenkins queue number for the build , ` ` int ` `
'''
# Jenkins returns a 302 from this URL, unless Referer is not set,
# then you get a 404.
self . jenkins_open ( urllib2 . Request ( self . server +
CANCEL_QUEUE % locals ( ) ,
headers = { ' Referer ' : self . server } ) )
2011-07-11 21:55:58 -07:00
def get_info ( self ) :
"""
2011-09-03 17:24:56 -07:00
Get information on this Master . This information
2011-07-11 21:55:58 -07:00
includes job list and view information .
2011-09-03 17:24:56 -07:00
: returns : dictionary of information about Master , ` ` dict ` `
2011-09-03 17:00:30 -07:00
Example : :
>> > info = j . get_info ( )
>> > jobs = info [ ' jobs ' ]
>> > print ( jobs [ 0 ] )
2013-04-13 20:35:11 +02:00
{ u ' url ' : u ' http://your_url_here/job/my_job/ ' , u ' color ' : u ' blue ' ,
u ' name ' : u ' my_job ' }
2011-09-03 17:00:30 -07:00
2011-07-11 21:55:58 -07:00
"""
try :
2013-04-13 20:35:11 +02:00
return json . loads ( self . jenkins_open (
urllib2 . Request ( self . server + INFO ) ) )
2011-07-19 17:06:18 +01:00
except urllib2 . HTTPError :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( " Error communicating with server[ %s ] "
% self . server )
2011-07-19 17:06:18 +01:00
except httplib . BadStatusLine :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( " Error communicating with server[ %s ] "
% self . server )
2011-07-19 17:06:18 +01:00
except ValueError :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( " Could not parse JSON info for server[ %s ] "
% self . server )
2011-07-11 21:55:58 -07:00
def get_jobs ( self ) :
"""
Get list of jobs running . Each job is a dictionary with
' name ' , ' url ' , and ' color ' keys .
2011-09-03 17:00:30 -07:00
: returns : list of jobs , ` ` [ { str : str } ] ` `
2011-07-11 21:55:58 -07:00
"""
return self . get_info ( ) [ ' jobs ' ]
2011-06-03 16:51:39 +01:00
def copy_job ( self , from_name , to_name ) :
'''
Copy a Jenkins job
2011-09-03 17:00:30 -07:00
: param from_name : Name of Jenkins job to copy from , ` ` str ` `
: param to_name : Name of Jenkins job to copy to , ` ` str ` `
2011-06-03 16:51:39 +01:00
'''
self . get_job_info ( from_name )
2013-04-13 20:35:11 +02:00
self . jenkins_open ( urllib2 . Request (
self . server + COPY_JOB % locals ( ) , ' ' ) )
2011-06-03 16:51:39 +01:00
if not self . job_exists ( to_name ) :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' create[ %s ] failed ' % ( to_name ) )
2011-06-03 16:51:39 +01:00
def delete_job ( self , name ) :
'''
Delete Jenkins job permanently .
2013-04-13 20:35:11 +02:00
2011-09-03 17:00:30 -07:00
: param name : Name of Jenkins job , ` ` str ` `
2011-06-03 16:51:39 +01:00
'''
self . get_job_info ( name )
2013-04-13 20:35:11 +02:00
self . jenkins_open ( urllib2 . Request (
self . server + DELETE_JOB % locals ( ) , ' ' ) )
2011-06-03 16:51:39 +01:00
if self . job_exists ( name ) :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' delete[ %s ] failed ' % ( name ) )
2012-03-02 16:26:13 +00:00
2011-06-03 16:51:39 +01:00
def enable_job ( self , name ) :
'''
Enable Jenkins job .
2011-09-03 17:00:30 -07:00
: param name : Name of Jenkins job , ` ` str ` `
2011-06-03 16:51:39 +01:00
'''
self . get_job_info ( name )
2013-04-13 20:35:11 +02:00
self . jenkins_open ( urllib2 . Request (
self . server + ENABLE_JOB % locals ( ) , ' ' ) )
2011-06-03 16:51:39 +01:00
def disable_job ( self , name ) :
'''
2011-09-03 17:00:30 -07:00
Disable Jenkins job . To re - enable , call : meth : ` Jenkins . enable_job ` .
2011-06-03 16:51:39 +01:00
2011-09-03 17:00:30 -07:00
: param name : Name of Jenkins job , ` ` str ` `
2011-06-03 16:51:39 +01:00
'''
self . get_job_info ( name )
2013-04-13 20:35:11 +02:00
self . jenkins_open ( urllib2 . Request (
self . server + DISABLE_JOB % locals ( ) , ' ' ) )
2011-06-03 16:51:39 +01:00
def job_exists ( self , name ) :
'''
2011-09-03 17:00:30 -07:00
: param name : Name of Jenkins job , ` ` str ` `
: returns : ` ` True ` ` if Jenkins job exists
2011-06-03 16:51:39 +01:00
'''
try :
self . get_job_info ( name )
return True
2011-07-19 17:06:18 +01:00
except JenkinsException :
2011-06-03 16:51:39 +01:00
return False
def create_job ( self , name , config_xml ) :
'''
Create a new Jenkins job
2011-09-03 17:00:30 -07:00
: param name : Name of Jenkins job , ` ` str ` `
: param config_xml : config file text , ` ` str ` `
2011-06-03 16:51:39 +01:00
'''
if self . job_exists ( name ) :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' job[ %s ] already exists ' % ( name ) )
2011-06-03 16:51:39 +01:00
headers = { ' Content-Type ' : ' text/xml ' }
2013-04-13 20:35:11 +02:00
self . jenkins_open ( urllib2 . Request (
self . server + CREATE_JOB % locals ( ) , config_xml , headers ) )
2011-06-03 16:51:39 +01:00
if not self . job_exists ( name ) :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' create[ %s ] failed ' % ( name ) )
2012-03-02 16:26:13 +00:00
2011-07-14 11:16:22 +01:00
def get_job_config ( self , name ) :
'''
Get configuration of existing Jenkins job .
2011-09-03 17:00:30 -07:00
: param name : Name of Jenkins job , ` ` str ` `
2011-09-03 17:24:56 -07:00
: returns : job configuration ( XML format )
2011-07-14 11:16:22 +01:00
'''
2012-05-17 16:10:00 +01:00
request = urllib2 . Request ( self . server + CONFIG_JOB %
{ " name " : urllib . quote ( name ) } )
return self . jenkins_open ( request )
2011-07-14 11:16:22 +01:00
2011-06-03 16:51:39 +01:00
def reconfig_job ( self , name , config_xml ) :
'''
2013-04-13 20:35:11 +02:00
Change configuration of existing Jenkins job . To create a new job , see
: meth : ` Jenkins . create_job ` .
2011-06-03 16:51:39 +01:00
2011-09-03 17:00:30 -07:00
: param name : Name of Jenkins job , ` ` str ` `
: param config_xml : New XML configuration , ` ` str ` `
2011-06-03 16:51:39 +01:00
'''
self . get_job_info ( name )
headers = { ' Content-Type ' : ' text/xml ' }
2013-04-13 20:35:11 +02:00
reconfig_url = self . server + CONFIG_JOB % locals ( )
2011-06-03 16:51:39 +01:00
self . jenkins_open ( urllib2 . Request ( reconfig_url , config_xml , headers ) )
def build_job_url ( self , name , parameters = None , token = None ) :
'''
2013-04-13 20:35:11 +02:00
Get URL to trigger build job . Authenticated setups may require
configuring a token on the server side .
2011-09-03 17:00:30 -07:00
: param parameters : parameters for job , or None . , ` ` dict ` `
: param token : ( optional ) token for building job , ` ` str ` `
: returns : URL for building job
2011-06-03 16:51:39 +01:00
'''
if parameters :
if token :
parameters [ ' token ' ] = token
2013-04-13 20:35:11 +02:00
return ( self . server + BUILD_WITH_PARAMS_JOB % locals ( ) +
' ? ' + urllib . urlencode ( parameters ) )
2011-06-03 16:51:39 +01:00
elif token :
2013-04-13 20:35:11 +02:00
return ( self . server + BUILD_JOB % locals ( ) +
' ? ' + urllib . urlencode ( { ' token ' : token } ) )
2011-06-03 16:51:39 +01:00
else :
2013-04-13 20:35:11 +02:00
return self . server + BUILD_JOB % locals ( )
2011-06-03 16:51:39 +01:00
def build_job ( self , name , parameters = None , token = None ) :
'''
2011-09-03 17:24:56 -07:00
Trigger build job .
2013-04-13 20:35:11 +02:00
2011-09-03 17:00:30 -07:00
: param parameters : parameters for job , or ` ` None ` ` , ` ` dict ` `
2011-06-03 16:51:39 +01:00
'''
if not self . job_exists ( name ) :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' no such job[ %s ] ' % ( name ) )
return self . jenkins_open ( urllib2 . Request (
self . build_job_url ( name , parameters , token ) ) )
2012-03-02 16:26:13 +00:00
2012-06-20 14:41:59 -07:00
def stop_build ( self , name , number ) :
'''
Stop a running Jenkins build .
: param name : Name of Jenkins job , ` ` str ` `
: param number : Jenkins build number for the job , ` ` int ` `
'''
self . jenkins_open ( urllib2 . Request ( self . server + STOP_BUILD % locals ( ) ) )
2011-06-03 16:51:39 +01:00
def get_node_info ( self , name ) :
2011-09-03 17:24:56 -07:00
'''
Get node information dictionary
: param name : Node name , ` ` str ` `
: returns : Dictionary of node info , ` ` dict ` `
'''
2011-06-03 16:51:39 +01:00
try :
2013-04-13 20:35:11 +02:00
response = self . jenkins_open ( urllib2 . Request (
self . server + NODE_INFO % locals ( ) ) )
2011-07-19 17:06:18 +01:00
if response :
return json . loads ( response )
else :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' node[ %s ] does not exist ' % name )
2011-07-19 17:06:18 +01:00
except urllib2 . HTTPError :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' node[ %s ] does not exist ' % name )
2011-07-19 17:06:18 +01:00
except ValueError :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( " Could not parse JSON info for node[ %s ] "
% name )
2012-03-02 16:26:13 +00:00
2011-06-03 16:51:39 +01:00
def node_exists ( self , name ) :
'''
2011-09-03 17:00:30 -07:00
: param name : Name of Jenkins node , ` ` str ` `
: returns : ` ` True ` ` if Jenkins node exists
2011-06-03 16:51:39 +01:00
'''
try :
self . get_node_info ( name )
return True
2011-07-19 17:06:18 +01:00
except JenkinsException :
2011-06-03 16:51:39 +01:00
return False
2012-03-02 16:26:13 +00:00
2011-06-03 16:51:39 +01:00
def delete_node ( self , name ) :
'''
Delete Jenkins node permanently .
2013-04-13 20:35:11 +02:00
2011-09-03 17:00:30 -07:00
: param name : Name of Jenkins node , ` ` str ` `
2011-06-03 16:51:39 +01:00
'''
self . get_node_info ( name )
2013-04-13 20:35:11 +02:00
self . jenkins_open ( urllib2 . Request (
self . server + DELETE_NODE % locals ( ) , ' ' ) )
2011-06-03 16:51:39 +01:00
if self . node_exists ( name ) :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' delete[ %s ] failed ' % ( name ) )
2012-03-02 16:26:13 +00:00
2012-06-20 14:41:59 -07:00
def disable_node ( self , name , msg = ' ' ) :
'''
Disable a node
2013-04-13 20:35:11 +02:00
2012-06-20 14:41:59 -07:00
: param name : Jenkins node name , ` ` str ` `
: param msg : Offline message , ` ` str ` `
'''
info = self . get_node_info ( name )
if info [ ' offline ' ] :
return
2013-04-13 20:35:11 +02:00
self . jenkins_open ( urllib2 . Request (
self . server + TOGGLE_OFFLINE % locals ( ) ) )
2012-06-20 14:41:59 -07:00
def enable_node ( self , name ) :
'''
Enable a node
2013-04-13 20:35:11 +02:00
2012-06-20 14:41:59 -07:00
: param name : Jenkins node name , ` ` str ` `
'''
info = self . get_node_info ( name )
if not info [ ' offline ' ] :
return
msg = ' '
2013-04-13 20:35:11 +02:00
self . jenkins_open ( urllib2 . Request (
self . server + TOGGLE_OFFLINE % locals ( ) ) )
2012-06-20 14:41:59 -07:00
2011-06-03 16:51:39 +01:00
def create_node ( self , name , numExecutors = 2 , nodeDescription = None ,
2012-06-20 14:41:59 -07:00
remoteFS = ' /var/lib/jenkins ' , labels = None , exclusive = False ,
launcher = LAUNCHER_COMMAND , launcher_params = { } ) :
2011-06-03 16:51:39 +01:00
'''
2011-09-03 17:00:30 -07:00
: param name : name of node to create , ` ` str ` `
: param numExecutors : number of executors for node , ` ` int ` `
: param nodeDescription : Description of node , ` ` str ` `
: param remoteFS : Remote filesystem location to use , ` ` str ` `
: param labels : Labels to associate with node , ` ` str ` `
: param exclusive : Use this node for tied jobs only , ` ` bool ` `
2012-06-20 14:41:59 -07:00
: param launcher : The launch method for the slave , ` ` jenkins . LAUNCHER_COMMAND ` ` , ` ` jenkins . LAUNCHER_SSH ` ` , ` ` jenkins . LAUNCHER_WINDOWS_SERVICE ` `
: param launcher_params : Additional parameters for the launcher , ` ` dict ` `
2011-06-03 16:51:39 +01:00
'''
if self . node_exists ( name ) :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' node[ %s ] already exists ' % ( name ) )
2012-03-02 16:26:13 +00:00
2011-08-08 20:38:39 +01:00
mode = ' NORMAL '
if exclusive :
mode = ' EXCLUSIVE '
2012-03-02 16:26:13 +00:00
2012-06-20 14:41:59 -07:00
launcher_params [ ' stapler-class ' ] = launcher
inner_params = {
2013-04-13 20:35:11 +02:00
' name ' : name ,
' nodeDescription ' : nodeDescription ,
' numExecutors ' : numExecutors ,
' remoteFS ' : remoteFS ,
' labelString ' : labels ,
' mode ' : mode ,
' type ' : NODE_TYPE ,
' retentionStrategy ' : {
' stapler-class ' :
' hudson.slaves.RetentionStrategy$Always '
} ,
' nodeProperties ' : { ' stapler-class-bag ' : ' true ' } ,
' launcher ' : launcher_params
2012-06-20 14:41:59 -07:00
}
params = {
2013-04-13 20:35:11 +02:00
' name ' : name ,
' type ' : NODE_TYPE ,
' json ' : json . dumps ( inner_params )
2011-06-03 16:51:39 +01:00
}
2012-03-02 16:26:13 +00:00
2013-04-13 20:35:11 +02:00
self . jenkins_open ( urllib2 . Request (
self . server + CREATE_NODE % urllib . urlencode ( params ) ) )
2012-06-20 14:41:59 -07:00
2011-06-03 16:51:39 +01:00
if not self . node_exists ( name ) :
2013-04-13 20:35:11 +02:00
raise JenkinsException ( ' create[ %s ] failed ' % ( name ) )