středa 6. října 2010

Working with IBM Jazz via Python through REST api

Have you worked with RTC, RQM or any other IBM Jazz based tool? Maybe you needed to import or export data via your own script?

There are some examples in Java and C#  showing how to interact with RQM  in this document. My preference was python. This post is a little example how to use python to interact with RQM server.



Motivation
It would be nice to have a python RQM client working like this.

from jazzclient import JazzClient  


jazz = JazzClient('https://servername:9443/jazz','username','password')
workItemXml = jazz.getWorkItem('3934')
jazz.changeProgress('3934', '90')



Interacting with the REST interface is easy via the httplib2 python module.


1. Authentication
consists of 3 steps (details on jazz.net here)
  1. requesting a "restricted resource"
  2. supplying credintials and getting togetherthe session ID
  3. requesting the "restricted resource" again, this time we should get it and confirm that our session is authenticated

All the authentication is done during construction, see bellow.

import urllib
import httplib2
from xml.dom.minidom import parse, parseString
from exceptions import Exception


class JazzClient(object):
    def __init__(self, server_url, user, password):
        self.base_url = server_url
      
        self.http = httplib2.Http()
        self.http.follow_redirects = True
        self.headers = {'Content-type': 'text/xml'}
      
        #1) before authentification one needs to go first to a "restricted resource"
        resp, content = self.http.request( self.base_url + "/oslc/workitems/1.xml", 'GET', headers=self.headers)
        #TODO sometimes returns capital X-
        #TODO check before if the key is in dictionary, if not something is wrong as well
        if resp['x-com-ibm-team-repository-web-auth-msg'] != 'authrequired':
            raise Exception("something is wrong seems the server doesn't expect authentication!")

          
        self.headers['Cookie']=  resp['set-cookie']
        self.headers['Content-type'] = 'application/x-www-form-urlencoded'
         
        #2 now we can start the authentication via j_security_check page
        resp, content = self.http.request(self.base_url+'/j_security_check' , 'POST', headers=self.headers,
                    body=urllib.urlencode({'j_username': user, 'j_password': password}))
             
        #TODO check auth worked fine, if not throw exception
        #3 get the requested resource - finish the authentication
        resp, content = self.http.request( self.base_url + "/oslc/workitems/1.xml", 'GET', headers=self.headers)



2. Getting a first "WorkItem" in XML (getWorkItem)

Once we are authenticated  it's just simple (follow the API documentation ). getWorkItem is method of JazzClient class.

    def getWorkItem(self, itemNumber):
        self.headers['Content-type'] = 'text/xml'
        resp, content = self.http.request(self.base_url+'/oslc/workitems/'+ itemNumber +'.xml', 'GET', headers=self.headers)
        if resp.status != 200:
            raise Exception("JazzClient responce status != 200 !!!")
        return content

3. Changing progress field in a WorkItem (changeProgress )
 
Now a small example showing change of progress field in a WorkItem. Again following method belongs to above JazzClient class.

    def changeProgress(self, itemNumber, progress):
        changeRequest = """
                <oslc_cm:changerequest xmlns:atom="http://www.w3.org/2005/Atom" xmlns:calm="http://jazz.net/xmlns/prod/jazz/calm/1.0/" xmlns:dc="http://purl.org/dc/terms/" xmlns:jd="http://jazz.net/xmlns/prod/jazz/discovery/1.0/" xmlns:jp="http://jazz.net/xmlns/prod/jazz/process/1.0/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:oslc_cm="http://open-services.net/xmlns/cm/1.0/" xmlns:oslc_disc="http://open-services.net/xmlns/discovery/1.0/" xmlns:oslc_qm="http://open-services.net/xmlns/qm/1.0/" xmlns:oslc_rm="http://open-services.net/xmlns/rm/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:rtc_cm="http://jazz.net/xmlns/prod/jazz/rtc/cm/1.0/">
                <rtc_cm:progress>%s</rtc_cm:progress>
                </oslc_cm:changerequest>"""
% (progress)               
        self.headers['Content-type'] = 'text/xml'
        resp, content = self.http.request(self.base_url+'/oslc/workitems/'+ itemNumber +'.xml' , 'PUT', headers=self.headers, body=changeRequest)
        if resp.status != 200:
            raise Exception("JazzClient.responce status != 200 !!!")

        return content

Conclusion
With the REST api documentation and bit of python it is fun to interact with Jazz servers.
The above code of JazzClient class were tested so just copy&paste to use it.


Links 
Some links expect registration (free).

1 komentář:

  1. Would you mind checking out this forum post about authenticating to Jazz via Python here: https://jazz.net/forums/viewtopic.php?t=20097 ... I updated your code to work with release 3.01...but it doesn't work.

    OdpovědětVymazat