Ejemplo n.º 1
0
class ServiceNowClient(object):
    def __init__(self, httpConnection, username=None, password=None):
        self.httpRequest = HttpRequest(httpConnection, username, password)

    @staticmethod
    def create_client(httpConnection, username=None, password=None):
        return ServiceNowClient(httpConnection, username, password)


    def get_change_request_states(self):
        servicenow_api_url = '/api/now/v1/table/%s?element=state&name=task&sysparm_fields=%s' % ('sys_choice','value,label')
        response = self.httpRequest.get(servicenow_api_url, contentType = 'application/json')
        if response.getStatus() == SN_RESULT_STATUS:
            data = json.loads(response.getResponse())
            return data['result']
        self.throw_error(response)

    def get_change_request(self, table_name,number,fields):
        servicenow_api_url = '/api/now/v1/table/%s?number=%s&sysparm_fields=%s' % (table_name,number,",".join(fields))
        response = self.httpRequest.get(servicenow_api_url, contentType = 'application/json')
        if response.getStatus() == SN_RESULT_STATUS:
            data = json.loads(response.getResponse())
            if len(data['result']) == 1:
                return data['result'][0]
        self.throw_error(response)

    def print_table(self, headers, rows):
        print "\n|", "|".join(headers), "|"
        print "|", " ------ |" * len(headers)
        for r in rows:
            print "| ", "  |".join(r), " |"
        print "\n"

    def throw_error(self, response):
        print "Error from ServiceNow, HTTP Return: %s\n" % (response.getStatus())
        sys.exit(1)
 def __init__(self, http_connection, username=None, password=None):
     self.http_request = HttpRequest(http_connection, username, password)
class XLReleaseClient(object):
    def __init__(self, http_connection, username=None, password=None):
        self.http_request = HttpRequest(http_connection, username, password)

    @staticmethod
    def create_client(http_connection, username=None, password=None):
        return XLReleaseClient(http_connection, username, password)

    def get_template(self, template_name):
        xlr_api_url = '/api/v1/templates?filter=%s' % urllib.quote(
            template_name)
        print "Going to use xlr_api_url: ", xlr_api_url
        xlr_response = self.http_request.get(xlr_api_url,
                                             contentType='application/json')
        if xlr_response.isSuccessful():
            data = json.loads(xlr_response.getResponse())
            for template in data:
                if template["title"] == template_name:
                    print "Found template %s with id %s" % (template_name,
                                                            template["id"])
                    return XLTemplate(template["id"],
                                      [str(t) for t in template["tags"]])
        print "Failed to find template in XL Release %s" % template_name
        xlr_response.errorDump()
        raise ServerError(str(xlr_response.getResponse()))

    def create_release(self, release_title, release_description, variables,
                       tags, template_id):
        content = """
        {"title":"%s","description":"%s","scheduledStartDate":"%sT23:58:00.000Z","dueDate":"%sT23:59:00.000Z","plannedDuration":null,"variables":%s,"tags":%s,"flag":{"status":"OK"},"templateId":"%s"}
        """ % (release_title, release_description, date.today(), date.today(),
               variables, tags, template_id)

        print "Sending content %s" % content

        xlr_api_url = '/releases'
        xlr_response = self.http_request.post(xlr_api_url,
                                              content,
                                              contentType='application/json')

        if xlr_response.isSuccessful():
            data = json.loads(xlr_response.getResponse())
            release_id = data["id"]
            print "Created %s in XLR" % release_id
            return release_id
        else:
            print "Failed to create release in XLR"
            xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))

    def start_release(self, release_id):
        # Start Release
        content = """
        {}
        """

        xlr_api_url = '/releases/' + release_id + "/start"
        xlr_response = self.http_request.post(xlr_api_url,
                                              content,
                                              contentType='application/json')
        if xlr_response.isSuccessful():
            print "Started %s in XLR" % (release_id)
        else:
            print "Failed to start release in XLR"
            xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))

    def get_release_status(self, release_id):
        xlr_api_url = '/releases/' + release_id
        xlr_response = self.http_request.get(xlr_api_url,
                                             contentType='application/json')
        if xlr_response.isSuccessful():
            data = json.loads(xlr_response.getResponse())
            status = data["status"]
            print "Subrelease [%s] has status [%s] in XLR" % (release_id,
                                                              status)
            return status
        else:
            print "Failed to get release status in XLR"
            xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))

    def get_updatable_variables(self, template_id):
        xlr_api_url = 'api/v1/releases/%s/variables' % template_id
        xlr_response = self.http_request.get(xlr_api_url,
                                             contentType='application/json')
        if xlr_response.isSuccessful():
            data = json.loads(xlr_response.getResponse())
            return data
        else:
            print "Failed to get variables in XLR"
            xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))

    def add_new_task(self, new_task_title, new_task_type, container_id):
        xlr_api_url = '/tasks/%s' % container_id
        content = {"title": new_task_title, "taskType": new_task_type}
        xlr_response = self.http_request.post(xlr_api_url,
                                              json.dumps(content),
                                              contentType='application/json')
        if xlr_response.isSuccessful():
            new_task = json.loads(xlr_response.getResponse())
            print "Created %s\n" % new_task_title
        else:
            print "Failed to create %s\n" % new_task_title
            print xlr_response.errorDump()
            sys.exit(1)
        return new_task

    def update_task(self, updated_task):
        xlr_api_url = '/tasks/%s' % updated_task['id']
        content = updated_task
        xlr_response = self.http_request.put(xlr_api_url,
                                             json.dumps(content),
                                             contentType='application/json')
        if xlr_response.isSuccessful():
            print "Updated task %s\n" % updated_task['title']
        else:
            print "Failed to update task\n" % updated_task['title']
            print xlr_response.errorDump()
            sys.exit(1)

    def add_link(self, container_id, source_task_id, target_task_id):
        xlr_api_url = '/planning/links/%s' % container_id
        content = {"sourceId": source_task_id, "targetId": target_task_id}
        xlr_response = self.http_request.post(xlr_api_url,
                                              json.dumps(content),
                                              contentType='application/json')
        if xlr_response.isSuccessful():
            print "Added task link\n"
        else:
            print "Failed to task link\n"
            print xlr_response.errorDump()
            sys.exit(1)

    def add_dependency(self, dependency_release_id, gate_task_id):
        # the internal api uses a rel-phase-task format instead of Applications/Rel/Phase/Task
        # is there a cleaner way to do this??
        # TODO move to public API once it is possible using the public API
        internal_format_task_id = gate_task_id.replace('Applications/',
                                                       '').replace('/', '-')

        xlr_api_url = '/gates/%s/dependencies' % internal_format_task_id
        content = {"target": {"releaseId": dependency_release_id}}
        xlr_response = self.http_request.post(xlr_api_url,
                                              json.dumps(content),
                                              contentType='application/json')

        if xlr_response.isSuccessful():
            print "Dependency added to Gate task\n"
        else:
            print "Failed to add dependency\n"
            print xlr_response.errorDump()
            sys.exit(1)

    def delete_phase(self, phase_id):
        phase_id = phase_id.replace("Applications/", "").replace("/", "-")
        xlr_response = self.http_request.delete('/phases/%s' % phase_id,
                                                contentType='application/json')
        if xlr_response.isSuccessful():
            print "Deleted phase with id [%s]\n" % phase_id
        else:
            print "Failed to delete phase with id [%s]\n" % phase_id
            print xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))
 def __init__(self, httpConnection, username=None, password=None):
     self.httpRequest = HttpRequest(httpConnection, username, password)
class XLReleaseClient(object):
    def __init__(self, http_connection, username=None, password=None):
        self.http_request = HttpRequest(http_connection, username, password)

    @staticmethod
    def create_client(http_connection, username=None, password=None):
        return XLReleaseClient(http_connection, username, password)


    def get_template(self, template_name):
        xlr_api_url = '/api/v1/templates?filter=%s' % urllib.quote(template_name)
        print "Going to use xlr_api_url: ", xlr_api_url
        xlr_response = self.http_request.get(xlr_api_url, contentType='application/json')
        if xlr_response.isSuccessful():
            data = json.loads(xlr_response.getResponse())
            for template in data:
                if template["title"] == template_name:
                    print "Found template %s with id %s" % (template_name, template["id"])
                    return XLTemplate(template["id"],[str(t) for t in template["tags"]])
        print "Failed to find template in XL Release %s" % template_name
        xlr_response.errorDump()
        raise ServerError(str(xlr_response.getResponse()))


    def create_release(self, release_title, release_description, variables, tags, template_id):
        content = """
        {"title":"%s","description":"%s","scheduledStartDate":"%sT23:58:00.000Z","dueDate":"%sT23:59:00.000Z","plannedDuration":null,"variables":%s,"tags":%s,"flag":{"status":"OK"},"templateId":"%s"}
        """ % (release_title, release_description, date.today(), date.today(), variables, tags, template_id)

        print "Sending content %s" % content

        xlr_api_url = '/releases'
        xlr_response = self.http_request.post(xlr_api_url, content, contentType='application/json')

        if xlr_response.isSuccessful():
            data = json.loads(xlr_response.getResponse())
            release_id = data["id"]
            print "Created %s in XLR" % release_id
            return release_id
        else:
            print "Failed to create release in XLR"
            xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))


    def start_release(self, release_id):
        # Start Release
        content = """
        {}
        """

        xlr_api_url = '/releases/' + release_id + "/start"
        xlr_response = self.http_request.post(xlr_api_url, content, contentType='application/json')
        if xlr_response.isSuccessful():
            print "Started %s in XLR" % (release_id)
        else:
            print "Failed to start release in XLR"
            xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))


    def get_release_status(self, release_id):
        xlr_api_url = '/releases/' + release_id
        xlr_response = self.http_request.get(xlr_api_url, contentType='application/json')
        if xlr_response.isSuccessful():
            data = json.loads(xlr_response.getResponse())
            status = data["status"]
            print "Subrelease [%s] has status [%s] in XLR" % (release_id,status)
            return status
        else:
            print "Failed to get release status in XLR"
            xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))

    def get_updatable_variables(self, template_id):
        xlr_api_url = 'api/v1/releases/%s/variables' % template_id
        xlr_response = self.http_request.get(xlr_api_url, contentType='application/json')
        if xlr_response.isSuccessful():
            data = json.loads(xlr_response.getResponse())
            return data
        else:
            print "Failed to get variables in XLR"
            xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))

    def add_new_task(self, new_task_title, new_task_type, container_id):
      xlr_api_url = '/tasks/%s' % container_id
      content = { "title" : new_task_title, "taskType" : new_task_type }
      xlr_response = self.http_request.post(xlr_api_url, json.dumps(content), contentType='application/json')
      if xlr_response.isSuccessful():
        new_task = json.loads(xlr_response.getResponse())
        print "Created %s\n" % new_task_title
      else:
        print "Failed to create %s\n" % new_task_title
        print xlr_response.errorDump()
        sys.exit(1)  
      return new_task

    def update_task(self, updated_task):
      xlr_api_url = '/tasks/%s' % updated_task['id']
      content = updated_task
      xlr_response = self.http_request.put(xlr_api_url, json.dumps(content), contentType='application/json')
      if xlr_response.isSuccessful():
        print "Updated task %s\n" % updated_task['title']
      else:
        print "Failed to update task\n" % updated_task['title']
        print xlr_response.errorDump()
        sys.exit(1)

    def add_link(self, container_id, source_task_id, target_task_id):
      xlr_api_url = '/planning/links/%s' % container_id
      content = { "sourceId" : source_task_id, "targetId" : target_task_id }
      xlr_response = self.http_request.post(xlr_api_url, json.dumps(content), contentType='application/json')
      if xlr_response.isSuccessful():
        print "Added task link\n"
      else:
        print "Failed to task link\n"
        print xlr_response.errorDump()
        sys.exit(1)

    def add_dependency(self, dependency_release_id, gate_task_id):
        # the internal api uses a rel-phase-task format instead of Applications/Rel/Phase/Task
        # is there a cleaner way to do this??
        # TODO move to public API once it is possible using the public API
        internal_format_task_id = gate_task_id.replace('Applications/', '').replace('/', '-')
        
        xlr_api_url = '/gates/%s/dependencies' % internal_format_task_id
        content = { "target": { "releaseId" : dependency_release_id } }
        xlr_response = self.http_request.post(xlr_api_url, json.dumps(content), contentType='application/json')

        if xlr_response.isSuccessful():
            print "Dependency added to Gate task\n"
        else:
            print "Failed to add dependency\n"
            print xlr_response.errorDump()
            sys.exit(1)

    def delete_phase(self, phase_id):
        phase_id = phase_id.replace("Applications/","").replace("/","-")
        xlr_response = self.http_request.delete('/phases/%s' % phase_id, contentType = 'application/json')
        if xlr_response.isSuccessful():
            print "Deleted phase with id [%s]\n" % phase_id
        else:
            print "Failed to delete phase with id [%s]\n" % phase_id
            print xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))
#
# THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS
# FOR A PARTICULAR PURPOSE. THIS CODE AND INFORMATION ARE NOT SUPPORTED BY XEBIALABS.
#

import sys, time, ast, re
from xml.etree import ElementTree as ET
from httputil.HttpRequest import HttpRequest

poll_interval = 5

httpRequest = HttpRequest(teamcityServer, username, password)

queueBuildURL = 'httpAuth/app/rest/buildQueue'
buildBody = '<build><buildType id="' + buildID + '"/></build>'

queue_response = httpRequest.post(queueBuildURL, buildBody, contentType='application/xml')

if queue_response.isSuccessful():
    # polls until the job completes
    root = ET.fromstring(queue_response.getResponse())
    runID = root.attrib['id']
    statusURL = 'httpAuth/app/rest/buildQueue/taskId:' + runID
    while True:
        time.sleep(poll_interval)
        status_response = httpRequest.get(statusURL, contentType='application/xml')
        if status_response.isSuccessful():
            root = ET.fromstring(status_response.getResponse())
            if root.attrib['state'] == 'finished':
                # Have a build completed
class XLDeployClient(object):
    def __init__(self, httpConnection, username=None, password=None):
        self.httpRequest = HttpRequest(httpConnection, username, password)

    @staticmethod
    def createClient(httpConnection, username=None, password=None):
        return XLDeployClient(httpConnection, username, password)


    def extract_state(self, task_state_xml):
        state_pos = task_state_xml.find('state="')
        state_offset = len('state="')
        state_end_pos = task_state_xml.find('"', state_pos + state_offset + 1)
        state = task_state_xml[state_pos + state_offset:state_end_pos]
        return state


    def getParameterTypeName(self,root):
        params = root.find("parameters")
        if params:
            for child in params:
                return child.tag


    def getParameterNames(self, parameterTypeId):
        metadata_url = "/deployit/metadata/type/%s" % (parameterTypeId)
        metadata_response = self.httpRequest.get(metadata_url, contentType='application/xml')
        root = ET.fromstring(metadata_response.getResponse())
        params = root.find("property-descriptors")
        if params:
            parameterNames = []
            for child in params:
                parameterNames.append(child.get("name"))
        return parameterNames


    def addParameter(self, root, parameterTypeId, parameterName, parameters):
        params = root.find("parameters")
        propertyDict = dict(ast.literal_eval(parameters))
        if params:
            for child in params:
                if child.tag == parameterTypeId:
                    param = ET.SubElement(child, parameterName)
                    param.text = propertyDict[parameterName]


    def prepare_control_task(self, control_task_name, target_ci_id, parameters = None):
        # print 'DEBUG: prepare the control task'
        prepare_control_task_url = "/deployit/control/prepare/%s/%s" % (control_task_name, target_ci_id)
        prepare_response = self.httpRequest.get(prepare_control_task_url, contentType='application/xml')
        control_obj = prepare_response.getResponse()
        root = ET.fromstring(control_obj)
        # print 'DEBUG: Control obj from /prepare', control_obj, '\n'
        parameterTypeId = self.getParameterTypeName(root)
        # print 'DEBUG: got parameterTypeId: %s' % parameterTypeId
        if parameterTypeId:
            parameterNames = self.getParameterNames(parameterTypeId)
            # print 'Found parameter names: %s' % parameterNames
            for parameterName in parameterNames:
                self.addParameter(root, parameterTypeId, parameterName, parameters)
        # print 'DEBUG: Control obj after udating parameters ', ET.tostring(root), '\n'
        invoke_response = self.httpRequest.post('/deployit/control', ET.tostring(root), contentType='application/xml')
        task_id = invoke_response.getResponse()
        # print 'DEBUG: Control task ID', task_id, '\n'
        return task_id


    def invoke_task_and_wait_for_result(self, task_id, polling_interval = 10, number_of_trials = None, continue_if_step_fails = False, number_of_continue_retrials = 0):
        start_task_url = "/deployit/task/%s/start" % (task_id)
        print 'DEBUG: About to invoke task by post %s - continue enabled: %s - trial: %s \n' % (task_id, continue_if_step_fails, number_of_continue_retrials)
        self.httpRequest.post(start_task_url, '', contentType='application/xml')
        trial = 0
        while not number_of_trials or trial < number_of_trials:
            # print 'DEBUG: About to get task status', task_id, '\n'
            trial += 1
            get_task_status_url = "/deployit/task/%s" % (task_id)
            task_state_response = self.httpRequest.get(get_task_status_url, contentType='application/xml')
            task_state_xml = task_state_response.getResponse()
            status = self.extract_state(task_state_xml)
            print 'DEBUG: Task', task_id, 'now in state', status, '\n'
            if status in ('FAILED', 'STOPPED') and continue_if_step_fails and number_of_continue_retrials > 0:
                status = self.invoke_task_and_wait_for_result(task_id,polling_interval,number_of_trials, continue_if_step_fails, number_of_continue_retrials-1)
            if status in ('FAILED', 'STOPPED', 'CANCELLED', 'DONE', 'EXECUTED'):
                break
            time.sleep(polling_interval)
        return status
    
    def deploymentExists(self, deploymentPackage, environment):
        deploymentExistsUrl = "/deployit/deployment/exists?application=%s&environment=%s" % (deploymentPackage.rsplit('/',1)[0],environment)
        # print 'DEBUG: checking deployment exists with url %s \n' % deploymentExistsUrl
        deploymentExists_response = self.httpRequest.get(deploymentExistsUrl, contentType='application/xml')
        response = deploymentExists_response.getResponse()
        return 'true' in response
    
    def deploymentPrepareUpdate(self, deploymentPackage, environment):
        deploymentPrepareUpdateUrl = "/deployit/deployment/prepare/update?version=%s&deployedApplication=%s" % (deploymentPackage, "%s/%s" % (environment, deploymentPackage.rsplit('/',2)[1]))
        deploymentPrepareUpdate_response = self.httpRequest.get(deploymentPrepareUpdateUrl, contentType='application/xml')
        return deploymentPrepareUpdate_response.getResponse()
    
    # GET /deployment/prepare/undeploy
    def deploymentPrepareUndeploy(self, deploymentPackage, environment):
        deploymentPrepareUpdateUrl = "/deployit/deployment/prepare/undeploy?deployedApplication=%s" % ("%s/%s" % (environment, deploymentPackage.rsplit('/',2)[1]))
        deploymentPrepareUpdate_response = self.httpRequest.get(deploymentPrepareUpdateUrl, contentType='application/xml')
        return deploymentPrepareUpdate_response.getResponse()

    def deploymentPrepareInitial(self, deploymentPackage, environment):
        deploymentPrepareInitialUrl = "/deployit/deployment/prepare/initial?version=%s&environment=%s" % (deploymentPackage, environment)
        deploymentPrepareInitial_response = self.httpRequest.get(deploymentPrepareInitialUrl, contentType='application/xml')
        return deploymentPrepareInitial_response.getResponse()

    def add_orchestrators(self, root, orchestrators):
        if orchestrators:
            params = root.find(".//orchestrator")
            params.clear()
            orchs = orchestrators.split(",")
            for orch in orchs:
                orchestrator = ET.SubElement(params, 'value')
                orchestrator.text = orch.strip()
    
    def set_deployed_application_properties(self, root, deployed_application_properties):
        if deployed_application_properties:
            deployeds_application_properties_dict = dict(ast.literal_eval(deployed_application_properties))
            for key in deployeds_application_properties_dict:
                pkey_xml = root.find(key)
                if not pkey_xml:
                    pkey_xml = ET.SubElement(root.find("udm.DeployedApplication"), key)
                pkey_xml.text = deployeds_application_properties_dict[key]
                
    
    def set_deployed_properties(self, root, deployed_properties):
        if deployed_properties:
            deployeds_properties_dict = dict(ast.literal_eval(deployed_properties))
            for key in deployeds_properties_dict:
                for xlr_tag_deployed in root.findall(".//deployeds/*"):
                    print 'DEBUG: deployed is %s \n' % ET.tostring(xlr_tag_deployed)
                    print 'DEBUG: xlrTag exists? %s' % xlr_tag_deployed.findtext('xlrTag')
                    print 'DEBUG: xlrTag key? %s' % key
                    if key == xlr_tag_deployed.findtext('xlrTag'):
                        deployed_properties_dict = dict(ast.literal_eval(deployeds_properties_dict[key]))
                        print 'DEBUG: deployed properties dict is %s \n' % deployed_properties_dict
                        for pkey in deployed_properties_dict:
                            pkey_xml = xlr_tag_deployed.find(pkey)
                            if not pkey_xml:
                                pkey_xml = ET.SubElement(xlr_tag_deployed, pkey)
                            pkey_xml.text = deployed_properties_dict[pkey]
                    
    
    def deployment_prepare_deployeds(self, deployment, orchestrators = None, deployed_application_properties = None, deployed_properties = None):
        deployment_prepare_deployeds = "/deployit/deployment/prepare/deployeds"
        # print 'DEBUG: Prepare deployeds for deployment object %s \n' % deployment
        deployment_prepare_deployeds_response = self.httpRequest.post(deployment_prepare_deployeds, deployment, contentType='application/xml')
        # print 'DEBUG: Deployment object including mapping is now %s \n' % deployment
        deployment_xml = deployment_prepare_deployeds_response.getResponse()
        root = ET.fromstring(deployment_xml)
        self.add_orchestrators(root, orchestrators)
        self.set_deployed_application_properties(root, deployed_application_properties)
        print 'DEBUG: Deployment object after updating orchestrators: %s \n' % ET.tostring(root)
        self.set_deployed_properties(root, deployed_properties)
        return ET.tostring(root)
    
    def get_deployment_task_id(self, deployment):
        getDeploymentTaskId = "/deployit/deployment"
        # print 'DEBUG: creating task id for deployment object %s \n' % deployment
        deploymentTaskId_response = self.httpRequest.post(getDeploymentTaskId, deployment, contentType='application/xml')
        # print 'DEBUG: getDeploymentTaskId response is %s \n' % (deploymentTaskId_response.getResponse())
        return deploymentTaskId_response.getResponse()
    
    def deploymentRollback(self, taskId):
        deploymentRollback = "/deployit/deployment/rollback/%s" % taskId
        # print 'DEBUG: calling rollback for taskId %s \n' % taskId
        deploymentRollback_response = self.httpRequest.post(deploymentRollback,'',contentType='application/xml')
        # print 'DEBUG: received rollback taskId %s \n' % deploymentRollback_response.getResponse()
        return deploymentRollback_response.getResponse()
    
    def archiveTask(self, taskId):
        archiveTask = "/deployit/task/%s/archive" % taskId
        self.httpRequest.post(archiveTask,'',contentType='application/xml')

    def cancelTask(self, taskId):
        cancelTask = "/deployit/task/%s" % taskId
        self.httpRequest.delete(cancelTask, contentType='application/xml')

    def stopTask(self, taskId):
        stopTask = "/deployit/task/%s/stop" % taskId
        self.httpRequest.post(stopTask,'',contentType='application/xml')

    def get_download_uuid(self, deploymentPackage):
        exportTask = "/deployit/export/deploymentpackage/%s" % deploymentPackage
        exportTask_response = self.httpRequest.get(exportTask, contentType='application/xml')
        return exportTask_response.getResponse()

    def fetch_package(self, fetchURL):
        fetchTask = "/deployit/package/fetch"
        self.httpRequest.post(fetchTask, fetchURL, contentType='application/xml')

    def get_latest_package_version(self, applicationId):
        queryTask = "/deployit/repository/query?parent=%s&resultsPerPage=-1" % applicationId
        queryTask_response = self.httpRequest.get(queryTask, contentType='application/xml')
        root = ET.fromstring(queryTask_response.getResponse())
        items = root.findall('ci')
        latestPackage = ''
        latestVersion = 0
        for item in items:
            currNos = re.findall(r'\d+',item.attrib['ref'])
            if len(currNos) > 0:
                if int(currNos[0]) > latestVersion:
                    latestVersion = int(currNos[0])
                    latestPackage = item.attrib['ref']

        return latestPackage

    def check_CI_exist(self, ciId):
        queryTask = "/deployit/repository/exists/%s" % ciId
        queryTask_response = self.httpRequest.get(queryTask, contentType='application/xml')
        return queryTask_response.getResponse().find('true') > 0

    def create_directory(self, ciId):
        createTask = "/deployit/repository/ci/%s" % ciId
        xml = '<core.Directory id="' + ciId + '" />'
        self.httpRequest.post(createTask, xml, contentType='application/xml')

    def create_application(self, appId):
        createTask = "/deployit/repository/ci/%s" % appId
        xml = '<udm.Application id="' + appId + '" />'
        self.httpRequest.post(createTask, xml, contentType='application/xml')
class XLReleaseClient(object):
    def __init__(self, http_connection, username=None, password=None):
        self.httpRequest = HttpRequest(http_connection, username, password)

    @staticmethod
    def create_client(http_connection, username=None, password=None):
        return XLReleaseClient(http_connection, username, password)


    def get_template(self, template_name):
        xlr_api_url = '/api/v1/templates?filter=%s' % urllib.quote(template_name)
        print "Going to use xlr_api_url: ", xlr_api_url
        xlr_response = self.httpRequest.get(xlr_api_url, contentType='application/json')
        if xlr_response.isSuccessful():
            data = json.loads(xlr_response.getResponse())
            for template in data:
                if template["title"] == template_name:
                    print "Found template %s with id %s" % (template_name, template["id"])
                    return XLTemplate(template["id"],[str(t) for t in template["tags"]])
        print "Failed to find template in XL Release %s" % template_name
        xlr_response.errorDump()
        raise ServerError(str(xlr_response.getResponse()))


    def create_release(self, release_title, release_description, variables, tags, template_id):
        content = """
        {"title":"%s","description":"%s","scheduledStartDate":"%sT23:58:00.000Z","dueDate":"%sT23:59:00.000Z","plannedDuration":null,"variables":%s,"tags":%s,"flag":{"status":"OK"},"templateId":"%s"}
        """ % (release_title, release_description, date.today(), date.today(), variables, tags, template_id)

        print "Sending content %s" % content

        xlr_api_url = '/releases'
        xlr_response = self.httpRequest.post(xlr_api_url, content, contentType='application/json')

        if xlr_response.isSuccessful():
            data = json.loads(xlr_response.getResponse())
            release_id = data["id"]
            print "Created %s in XLR" % release_id
            return release_id
        else:
            print "Failed to create release in XLR"
            xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))


    def start_release(self, release_id):
        # Start Release
        content = """
        {}
        """

        xlr_api_url = '/releases/' + release_id + "/start"
        xlr_response = self.httpRequest.post(xlr_api_url, content, contentType='application/json')
        if xlr_response.isSuccessful():
            print "Started %s in XLR" % (release_id)
        else:
            print "Failed to start release in XLR"
            xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))


    def get_release_status(self, release_id):
        xlr_api_url = '/releases/' + release_id
        xlr_response = self.httpRequest.get(xlr_api_url, contentType='application/json')
        if xlr_response.isSuccessful():
            data = json.loads(xlr_response.getResponse())
            status = data["status"]
            print "Subrelease [%s] has status [%s] in XLR" % (release_id,status)
            return status
        else:
            print "Failed to get release status in XLR"
            xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))

    def get_updatable_variables(self,template_id):
        xlr_api_url = '/releases/%s/updatable-variables' % template_id.split("/")[1]
        xlr_response = self.httpRequest.get(xlr_api_url, contentType='application/json')
        if xlr_response.isSuccessful():
            data = json.loads(xlr_response.getResponse())
            return data
        else:
            print "Failed to get variables in XLR"
            xlr_response.errorDump()
            raise ServerError(str(xlr_response.getResponse()))