~koddsson/python-jenkins/python-jenkins

« back to all changes in this revision

Viewing changes to jenkins/__init__.py

  • Committer: James Page
  • Date: 2012-03-02 16:31:05 UTC
  • mfrom: (12.1.3 build_info)
  • Revision ID: james.page@canonical.com-20120302163105-bi695il3sahdipz4
Merged branch to add get_build_info method

Show diffs side-by-side

added added

removed removed

Lines of Context:
76
76
COPY_JOB     = 'createItem?name=%(to_name)s&mode=copy&from=%(from_name)s'
77
77
BUILD_JOB    = 'job/%(name)s/build'
78
78
BUILD_WITH_PARAMS_JOB = 'job/%(name)s/buildWithParameters'
 
79
BUILD_INFO   = 'job/%(name)s/%(number)d/api/json?depth=0'
79
80
 
80
81
 
81
82
CREATE_NODE = 'computer/doCreateItem?%s'
133
134
    return 'Basic ' + base64.encodestring('%s:%s' % (username, password))[:-1]
134
135
 
135
136
class Jenkins(object):
136
 
    
 
137
 
137
138
    def __init__(self, url, username=None, password=None):
138
139
        '''
139
140
        Create handle to Jenkins instance.
144
145
            self.server = url
145
146
        else:
146
147
            self.server = url + '/'
147
 
        if username is not None and password is not None:            
 
148
        if username is not None and password is not None:
148
149
            self.auth = auth_headers(username, password)
149
150
        else:
150
151
            self.auth = None
151
 
        
 
152
 
152
153
    def get_job_info(self, name):
153
154
        '''
154
155
        Get job information dictionary.
166
167
            raise JenkinsException('job[%s] does not exist'%name)
167
168
        except ValueError:
168
169
            raise JenkinsException("Could not parse JSON info for job[%s]"%name)
169
 
        
 
170
 
170
171
    def debug_job_info(self, job_name):
171
172
        '''
172
173
        Print out job info in more readable format
188
189
            if e.code in [401, 403, 500]:
189
190
                raise JenkinsException('Error in request. Possibly authentication failed [%s]'%(e.code))
190
191
            # right now I'm getting 302 infinites on a successful delete
191
 
    
 
192
 
 
193
    def get_build_info(self, name, number):
 
194
        '''
 
195
        Get build information dictionary.
 
196
 
 
197
        :param name: Job name, ``str``
 
198
        :param name: Build number, ``int``
 
199
        :returns: dictionary of build information, ``dict``
 
200
 
 
201
        Example::
 
202
 
 
203
            >>> next_build_number = j.get_job_info('build_name')['next_build_number']
 
204
            >>> output = j.build_job('build_'+kwargs['vcs_server_type'], params)
 
205
            >>> sleep(10)
 
206
            >>> build_info = j.get_build_info('build_name', next_build_number)
 
207
            >>> print(build_info)
 
208
            {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'}
 
209
        '''
 
210
        try:
 
211
            response = self.jenkins_open(urllib2.Request(self.server + BUILD_INFO%locals()))
 
212
            if response:
 
213
                return json.loads(response)
 
214
            else:
 
215
                raise JenkinsException('job[%s] number[%d] does not exist'%(name, number))
 
216
        except urllib2.HTTPError:
 
217
            raise JenkinsException('job[%s] number[%d] does not exist'%(name, number))
 
218
        except ValueError:
 
219
            raise JenkinsException('Could not parse JSON info for job[%s] number[%d]'%(name, number))
 
220
 
192
221
    def get_queue_info(self):
193
222
        '''
194
223
        :returns: list of job dictionaries, ``[dict]``
255
284
        self.jenkins_open(urllib2.Request(self.server + DELETE_JOB%locals(), ''))
256
285
        if self.job_exists(name):
257
286
            raise JenkinsException('delete[%s] failed'%(name))
258
 
    
 
287
 
259
288
    def enable_job(self, name):
260
289
        '''
261
290
        Enable Jenkins job.
299
328
        self.jenkins_open(urllib2.Request(self.server + CREATE_JOB%locals(), config_xml, headers))
300
329
        if not self.job_exists(name):
301
330
            raise JenkinsException('create[%s] failed'%(name))
302
 
    
 
331
 
303
332
    def get_job_config(self, name):
304
333
        '''
305
334
        Get configuration of existing Jenkins job.
347
376
        '''
348
377
        if not self.job_exists(name):
349
378
            raise JenkinsException('no such job[%s]'%(name))
350
 
        return self.jenkins_open(urllib2.Request(self.build_job_url(name, parameters, token)))        
351
 
  
 
379
        return self.jenkins_open(urllib2.Request(self.build_job_url(name, parameters, token)))
 
380
 
352
381
    def get_node_info(self, name):
353
382
        '''
354
383
        Get node information dictionary
366
395
            raise JenkinsException('node[%s] does not exist'%name)
367
396
        except ValueError:
368
397
            raise JenkinsException("Could not parse JSON info for node[%s]"%name)
369
 
 
 
398
 
370
399
    def node_exists(self, name):
371
400
        '''
372
401
        :param name: Name of Jenkins node, ``str``
377
406
            return True
378
407
        except JenkinsException:
379
408
            return False
380
 
            
 
409
 
381
410
    def delete_node(self, name):
382
411
        '''
383
412
        Delete Jenkins node permanently.
388
417
        self.jenkins_open(urllib2.Request(self.server + DELETE_NODE%locals(), ''))
389
418
        if self.node_exists(name):
390
419
            raise JenkinsException('delete[%s] failed'%(name))
391
 
    
392
 
    
 
420
 
 
421
 
393
422
    def create_node(self, name, numExecutors=2, nodeDescription=None,
394
423
                    remoteFS='/var/lib/jenkins', labels=None, exclusive=False):
395
424
        '''
402
431
        '''
403
432
        if self.node_exists(name):
404
433
            raise JenkinsException('node[%s] already exists'%(name))
405
 
        
 
434
 
406
435
        mode = 'NORMAL'
407
436
        if exclusive:
408
437
            mode = 'EXCLUSIVE'
409
 
           
 
438
 
410
439
        params = {
411
440
            'name' : name,
412
441
            'type' : NODE_TYPE,
423
452
                'launcher'          : { 'stapler-class' : 'hudson.slaves.JNLPLauncher' }
424
453
            })
425
454
        }
426
 
        
427
 
        self.jenkins_open(urllib2.Request(self.server + CREATE_NODE%urllib.urlencode(params)))                             
 
455
 
 
456
        self.jenkins_open(urllib2.Request(self.server + CREATE_NODE%urllib.urlencode(params)))
428
457
        if not self.node_exists(name):
429
458
            raise JenkinsException('create[%s] failed'%(name))