class VersionOneClient( object ): def __init__(self, v1CI ): self.Token = v1CI['accessToken'] self.uriBase = v1CI['uriBase'] self.storyStatus = v1CI['StoryStatus'] self.httpConnection = v1CI self.httpRequest = HttpRequest( v1CI ) self.optionHeader = {"Accept" : "application/json", "Authorization" : "Bearer %s" % self.Token} # End def @staticmethod def create_v1Client( v1CI ): return VersionOneClient( v1CI ) # End def def getStories(self, whereClause=None): uri = "%s/rest-1.v1/Data/Story" % self.uriBase if whereClause is not None: uri = "%s?where=%s" % ( uri, whereClause ) # End if print( "getStories uri = %s" % uri ) print( "Headers = %s" % self.optionHeader ) response = self.httpRequest.get( uri, headers=self.optionHeader ) reqStatus = response.getStatus() print( "Request Status %s" % reqStatus ) if reqStatus == STATUS_OK: return json.loads( response.getResponse() ) # End if raise ValueError('Error getting stories', reqStatus ) # End def def updateStoryStatus(self, ticket, status): whereClause="Number='%s'" % ticket data = self.getStories( whereClause ) uri = data['Assets'][0]['href'] xml = "<Asset> <Relation name=\"Status\" act=\"set\"> <Asset idref=\"StoryStatus:%s\" /> </Relation> </Asset>" % self.storyStatus[status] print( "Update Status uri = %s" % uri ) print( "Update Status XML ~%s~" % xml ) print( "Update Status Headers = %s" % self.optionHeader ) response = self.httpRequest.post( uri, xml, headers=self.optionHeader ) reqStatus = response.getStatus() print( "Request Status %s" % reqStatus ) if reqStatus == STATUS_OK: return # End if raise ValueError('Error getting stories', reqStatus ) # End def def get_story_status_list(self): uri = "%s/rest-1.v1/Data/StoryStatus" % self.uriBase print( "getStoryStatus uri = %s" % uri ) print( "Headers = %s" % self.optionHeader ) response = self.httpRequest.get( uri, headers=self.optionHeader ) req_status = response.getStatus() print( "Request Status %s" % req_status ) if req_status == STATUS_OK: return json.loads( response.getResponse() ) # End if raise ValueError('Error getting stories', req_status )
def revoke_token(self): print "Revoking token" httpRequest = HttpRequest(self.httpConnection, None, None) servicenowApiUrl = "/oauth_revoke_token.do?token=%s" % self.accessToken response = httpRequest.get(servicenowApiUrl) servicenowApiUrl = "/oauth_revoke_token.do?token=%s" % self.refreshToken response = httpRequest.get(servicenowApiUrl)
class CircleCiClient(object): def __init__(self, http_connection, token=None): self.http_request = HttpRequest( http_connection, token, "" ) # Should not have to pass the empty P/W string, will work on fix. @staticmethod def create_client(http_connection, token=None): return CircleCiClient(http_connection, token) def get_user(self): get_user_endpoint = "/me" get_user_response = self.http_request.get( get_user_endpoint, contentType='application/json') if not get_user_response.isSuccessful(): raise Exception( "Failed to get user information. Server return [%s], with content [%s]" % (get_user_response.status, get_user_response.response)) return json.loads(get_user_response.getResponse()) def trigger_build(self, vcs, username, project, branch, wait, waitInterval): trigger_build_endpoint = "/project/%s/%s/%s/tree/%s" % ( vcs, username, project, branch) trigger_build_response = self.http_request.post( trigger_build_endpoint, '{}', contentType='application/json') if not trigger_build_response.isSuccessful(): raise Exception( "Failed to trigger build for project [%s] on branch [%s]. Server return [%s], with content [%s]" % (project, branch, trigger_build_response.status, trigger_build_response.response)) json_data = json.loads(trigger_build_response.getResponse()) if wait: build_num = json_data["build_num"] while (True): build_information_endpoint = "/project/%s/%s/%s/%s" % ( vcs, username, project, build_num) build_information_response = self.http_request.get( build_information_endpoint, contentType='application/json') if not build_information_response.isSuccessful(): raise Exception( "Failed to retrieve build information for project [%s] on branch [%s] build number[%s]. Server return [%s], with content [%s]" % (project, branch, build_num, build_information_response.status, build_information_response.response)) build_information = json.loads( build_information_response.getResponse()) status = build_information["status"] # TODO: Need to obtain a better understanding of these states and what constitutes fail vs. pass from XLR perspective. if status == "success" or status == "fixed": return build_information elif status == "failed" or status == "canceled" or status == "infrastructure_fail" or status == "timedout" or status == "no_tests": sys.exit(1) else: time.sleep(float(waitInterval)) return json_data
def get_applications(ancestor, applications_count): request = HttpRequest(server, username, password) applications_batch = [] results_remain = True page = 0 while results_remain: endpoint = '/deployit/repository/query?page={}&resultsPerPage=100&type=udm.Application&ancestor={}'.format( page, ancestor) response = request.get(endpoint, contentType='application/json') if not response.isSuccessful(): raise Exception( "Failed to get application information from XL Deploy. Server return [%s], with content [%s]" % (response.status, response.response)) results = json.loads(response.response) if results == []: results_remain = False else: for result in results: applications_batch.append({ "id": "{}".format(applications_count), "name": result["ref"] }) applications_count += 1 page += 1 return {"batch": applications_batch, "count": applications_count}
def get_applications_metadata(applications): request = HttpRequest(server, username, password) application_metadata = {} for application in applications: applicationShortName = application["name"].split('/')[-1] application_metadata[applicationShortName] = {} application_metadata[applicationShortName]["plotId"] = application[ "id"] endpoint = '/deployit/repository/ci/{}'.format(application["name"]) response = request.get(endpoint, contentType='application/json') if not response.isSuccessful(): raise Exception( "Failed to get application information from XL Deploy. Server return [%s], with content [%s]" % (response.status, response.response)) lastVersion = json.loads(response.response)["lastVersion"] application_metadata[applicationShortName]["lastVersion"] = lastVersion if lastVersion == "": applicationDependencies = [] else: endpoint = '/deployit/repository/ci/{}/{}'.format( application["name"], lastVersion) response = request.get(endpoint, contentType='application/json') if not response.isSuccessful(): raise Exception( "Failed to get deployment package information from XL Deploy. Server return [%s], with content [%s]" % (response.status, response.response)) if json.loads(response.response)["type"] == "udm.CompositePackage": applicationDependencies = [] else: applicationDependencies = json.loads( response.response)["applicationDependencies"].keys() application_metadata[applicationShortName][ "applicationDependencies"] = applicationDependencies application_metadata[applicationShortName]["dependedUponCount"] = 0 for application in application_metadata.keys(): for dependency in application_metadata[application][ "applicationDependencies"]: if dependency in application_metadata.keys( ): # only add if dependency exists in XLD application_metadata[dependency]["dependedUponCount"] += 1 return application_metadata
def testServer(self, variables): httpConnection = variables['params'] httpRequest = HttpRequest(httpConnection) response = httpRequest.get("/") self.logger.error("Response Status = %s" % response.getStatus()) if response.getStatus() == 200: return sys.exit(-1)
def isTaskCompleted(self, taskId, username=None, password=None): request = HttpRequest(self.httpConnection, username, password) context = '/api/v1/tasks/%s' % taskId response = request.get(context, contentType='application/json') if response.isSuccessful(): data = json.loads(response.response) status = data["status"] print "Current Task with id [%s] is %s." % (taskId, status) return status == COMPLETED else: print "Failed to get status for task with id: %s" % taskId response.errorDump() sys.exit(1)
def meetup_getpostcomments(self, variables): httpConnection = variables['server'] httpRequest = HttpRequest(httpConnection, variables['username'], variables['password']) url = "/comments?postId=%s" % variables['postId'] self.logger.error("Get Post Comments %s" % (url)) response = httpRequest.get(url, contentType='application/json') jsonData = response.getResponse() data = json.loads( jsonData ) listData = [] for recordData in data: self.logger.error( recordData['body'] ) listData.append( recordData['body'] ) returnData = {"responseJson": jsonData, "comments": listData } return returnData
class RedhatSatelliteClient(object): def __init__(self, httpConnection, username=None, password=None): self.headers = {} self.query_params = "" self.httpConnection = httpConnection if username is not None: self.httpConnection['username'] = username if password is not None: self.httpConnection['password'] = password self.httpRequest = HttpRequest(self.httpConnection, username, password) @staticmethod def create_client(httpConnection, username=None, password=None): return RedhatSatelliteClient(httpConnection, username, password) def ping(self): api_url = '/katello/api/v2/ping' print "RedHat Satellite URL = %s " % (api_url) response = self.httpRequest.get(api_url, contentType='application/json', headers=self.headers) if response.getStatus() == SUCCES_RESULT_STATUS: data = json.loads(response.getResponse()) return data else: print "find_record error %s" % (response) self.throw_error(response) # End if # End find_record def throw_error(self, response): print "Error from RedhatSatelliteClient, HTTP Return: %s\n" % ( response.getStatus()) print "Detailed error: %s\n" % response.response sys.exit(1) def EmptyToNone(self, value): if value is None: return None elif value.strip() == '': return None else: return value
def hasPermission(task, is610andAbove, configs=None): de = getProperty(t, is610andAbove, "environment", "deploymentEnvironment") if de != None: u = getProperty(t, is610andAbove, "username") p = getProperty(t, is610andAbove, "password", isPassword=True) dp = getProperty(t, is610andAbove, "deploymentPackage") if is610andAbove: s = getProperty(t, is610andAbove, "server") if u == None or u == "": u = s.username if p == None or p == "": p = s.password url = s.url else: s = findServerData(getProperty(t, is610andAbove, "server"), configs)[0] if u == None or u == "": u = s["username"] if p == None or p == "": p = s["password"] p = "admin" url = s["url"] http_request = HttpRequest( { "url": url, "username": str(u), "password": str(p) }, "", "") response = http_request.get( "/deployit/security/check/deploy%23initial/Environments/" + de, contentType="application/xml") if response.status == 200: res_text = response.getResponse() if res_text.find("false") > -1: return False else: return True else: return False else: return False
class NuGetClient(object): def __init__(self, httpConnection, apiKey, username="", password=""): self.headers = {"X-NuGet-ApiKey": apiKey} self.query_params = "" self.httpConnection = httpConnection self.httpConnection['username'] = username self.httpConnection['password'] = password self.httpRequest = HttpRequest(self.httpConnection, username, password) @staticmethod def create_client(httpConnection, apiKey, username="", password=""): return NuGetClient(httpConnection, apiKey, username, password) def get_latest_version(self, package_id): api_url = '/api/v2/package-versions/%s?semVerLevel=2.0.0&includePrerelease=false' % (package_id) response = self.httpRequest.get(api_url, contentType='application/json', headers = self.headers) if response.getStatus() == SUCCES_RESULT_STATUS: versions_list = json.loads(response.getResponse()) #print("Versions founds: %s" % str(versions_list)) # there may be a 'latest' but that's not helpful to us to see if there's a new version if "latest" in versions_list: versions_list.remove("latest") # End if try: versions_list.sort(key=LooseVersion) #print("Tags sorted %s" % str(versions_list)) except Exception, e: print("Failed to sort, ignoring: %s " % str(e)) # End try if len(versions_list) > 0: return versions_list[-1] else: return None else:
class SamsonClient(object): def __init__(self, httpConnection, webhookToken, maxChecksPerDeploymentId=30, timeout=5): self.httpConnection = httpConnection self.httpRequest = HttpRequest(httpConnection) self.webhookToken = webhookToken self.headers = self._get_headers() self.maxChecksPerDeploymentId = maxChecksPerDeploymentId self.timeout = timeout @staticmethod def create_client(httpConnection, webhookToken): return SamsonClient(httpConnection, webhookToken) def _get_headers(self): return { "Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer %s" % self.webhookToken } def ping(self, project_name): # random valid endpoint that verifies we're logged in / have a valid token url = '/projects/%s' % project_name response = self.httpRequest.get(url, headers=self.headers) if response.getStatus() in HTTP_SUCCESS: data = json.loads(response.getResponse()) print json.dumps(data) else: self.throw_error(response) def start_deploy(self, webhook_id, commit_sha, message, branch="master"): url = "/integrations/generic/%s" % webhook_id body = { "deploy": { "branch": branch, "commit": { "sha": commit_sha, "message": message } } } print "body = %s" % json.dumps(body) # example response: {"deploy_ids":[],"messages":"INFO: Branch master is release branch: true\nINFO: Deploying to 0 stages\n"} response = self.httpRequest.post(url, headers=self.headers, body=json.dumps(body)) if response.getStatus() in HTTP_SUCCESS: data = json.loads(response.getResponse()) print json.dumps(data["deploy_ids"]) print json.dumps(data["messages"]) return data else: self.throw_error(response) def wait_for_deploy(self, project_name, deploy_id): # /projects/gcr-watcher/deploys/44.json url = "/projects/%s/deploys/%s.json" % (project_name, deploy_id) status = "" number_of_checks = 0 while status not in ["succeeded", "failed"]: response = self.httpRequest.get(url, headers=self.headers) if response.getStatus() in HTTP_SUCCESS: depData = json.loads(response.getResponse()) status = depData["status"] depReportUrl = depData["url"] number_of_checks += 1 if number_of_checks > self.maxChecksPerDeploymentId: sys.exit("Fail: project %s deployment %s failed" % (project_name, deploy_id)) time.sleep(self.timeout) else: self.throw_error(response) if status == "failed": sys.exit("Fail: project %s deployment %s failed" % (project_name, deploy_id)) else: print "Success: project %s deployment %s succeeded" % ( project_name, deploy_id) def throw_error(self, response): msg = "Error from server, HTTP Return: %s, content %s\n" % ( response.getStatus(), response.getResponse()) print msg sys.exit(msg)
class SauceLabsClient(object): def __init__(self, buildId, testName, testNameWildCard, hourRange, limit, http_connection, acctUsername, accessKey): self.configUsername = acctUsername self.configAccessKey = accessKey self.http_connection = http_connection # If not username and accessKey not configured in the getJobs task, use the info from the # SauceLabs server configuration if not self.configUsername: self.configUsername = http_connection.get("username") if not self.configAccessKey: self.configAccessKey = http_connection.get("password") self.http_request = HttpRequest(http_connection, self.configUsername, self.configAccessKey) self.acctUsername = acctUsername self.buildId = buildId self.testName = testName self.testNameWildCard = testNameWildCard self.beginRange = None self.endRange = None self.limit = limit if hourRange and hourRange > 0: self.endRange = str(int(time.time())) self.beginRange = str(int(time.time()) - (int(hourRange)*3600)) @staticmethod def create_client(buildId, testName, testNameWildCard, hourRange, limit, http_connection, acctUsername, accessKey): return SauceLabsClient(buildId, testName, testNameWildCard, hourRange, limit, http_connection, acctUsername, accessKey) def filterList(self, data): filteredJobs = [] for testJob in data: passedName = True passedBuild = True testJobName = testJob["name"] if testJob["name"] else "" testJobBuild = testJob["build"] if testJob['build'] else "" # Note: hour and limit are filtered in the intial http request if self.testName: if self.testNameWildCard: if self.testName not in testJobName: passedName = False else: if self.testName != testJobName: passedName = False if self.buildId: if self.buildId != testJobBuild: passedBuild = False if passedName and passedBuild: filteredJobs.append(testJob) return filteredJobs def getAdditionalParams(self): theLimit = "" theHourRange = "" if self.limit: theLimit = "&limit="+str(self.limit) if self.beginRange and self.endRange: theHourRange = "&from="+self.beginRange+"&to="+self.endRange paramsString = theLimit+theHourRange return paramsString def get_jobs(self,): addParams = self.getAdditionalParams() saucelabs_api_url = "/rest/v1/%s/jobs?full=true%s" % (self.configUsername, addParams) jobs_response = self.http_request.get(saucelabs_api_url, contentType='application/json') if not jobs_response.isSuccessful(): raise Exception("Failed to get jobs. Server return [%s], with content [%s] when calling [%s]" % (jobs_response.status, jobs_response.response, saucelabs_api_url)) data = json.loads(jobs_response.getResponse()) filteredJobs = self.filterList(data) jobs = {} nothingFound = "No jobs matching the search criteria were found. Search URL - "+saucelabs_api_url if len(filteredJobs) > 0: print 'Description | Start Time | Build Id | Name | Passed | Link' print ':---: | :---: | :---: | :---: | :---: | :---:' else: print nothingFound jobs["0"] = nothingFound counter = 0 for job in filteredJobs: counter += 1 jobName = job["name"] if job["name"] else " " jobBuildId = job["build"] if job["build"] else " " description = job["os"]+"/"+job["browser"]+"-"+job["browser_short_version"] jobPassed = job["passed"] if job["passed"] else " " jobPassedConverted =" " if jobPassed != " ": if job["passed"]: jobPassedConverted = "Passed" else: jobPassedConverted = "Failed" ts = int(job["start_time"]) dateAndTime = datetime.utcfromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') link = "[View]("+self.http_connection.get("url")+"/jobs/"+job["id"]+")" print '%s|%s|%s|%s|%s|%s' % (description, dateAndTime, jobBuildId, jobName, jobPassed,link) jobs[str(job["id"])] = jobPassedConverted filteredJobsStr = json.dumps(filteredJobs) return filteredJobsStr, jobs
# # Copyright (c) 2018. All rights reserved. # # This software and all trademarks, trade names, and logos included herein are the property of XebiaLabs, Inc. and its affiliates, subsidiaries, and licensors. # from xlrelease.HttpRequest import HttpRequest import json params = {'url': 'http://api.openweathermap.org'} http_request = HttpRequest(params) weather_response = http_request.get( '/data/2.5/weather?zip={},us&appid=926183652fba05ab14691aa5b6ed1faa'. format(zipcode)) if weather_response.isSuccessful(): json_data = json.loads(weather_response.getResponse()) temperature = json_data["main"]["temp"] else: sys.exit(1)
class SauceLabsClient(object): def __init__(self, buildId, testName, testNameWildCard, hourRange, limit, http_connection, acctUsername, accessKey): self.configUsername = acctUsername self.configAccessKey = accessKey self.http_connection = http_connection # If not username and accessKey not configured in the getJobs task, use the info from the # SauceLabs server configuration if not self.configUsername: self.configUsername = http_connection.get("username") if not self.configAccessKey: self.configAccessKey = http_connection.get("password") self.http_request = HttpRequest(http_connection, self.configUsername, self.configAccessKey) self.acctUsername = acctUsername self.buildId = buildId self.testName = testName self.testNameWildCard = testNameWildCard self.beginRange = None self.endRange = None self.limit = limit if hourRange and hourRange > 0: self.endRange = str(int(time.time())) self.beginRange = str(int(time.time()) - (int(hourRange) * 3600)) @staticmethod def create_client(buildId, testName, testNameWildCard, hourRange, limit, http_connection, acctUsername, accessKey): return SauceLabsClient(buildId, testName, testNameWildCard, hourRange, limit, http_connection, acctUsername, accessKey) def filterList(self, data): filteredJobs = [] for testJob in data: passedName = True passedBuild = True testJobName = testJob["name"] if testJob["name"] else "" testJobBuild = testJob["build"] if testJob['build'] else "" # Note: hour and limit are filtered in the intial http request if self.testName: if self.testNameWildCard: if self.testName not in testJobName: passedName = False else: if self.testName != testJobName: passedName = False if self.buildId: if self.buildId != testJobBuild: passedBuild = False if passedName and passedBuild: filteredJobs.append(testJob) return filteredJobs def getAdditionalParams(self): theLimit = "" theHourRange = "" if self.limit: theLimit = "&limit=" + str(self.limit) if self.beginRange and self.endRange: theHourRange = "&from=" + self.beginRange + "&to=" + self.endRange paramsString = theLimit + theHourRange return paramsString def get_jobs(self, ): addParams = self.getAdditionalParams() saucelabs_api_url = "/rest/v1/%s/jobs?full=true%s" % ( self.configUsername, addParams) jobs_response = self.http_request.get(saucelabs_api_url, contentType='application/json') if not jobs_response.isSuccessful(): raise Exception( "Failed to get jobs. Server return [%s], with content [%s] when calling [%s]" % (jobs_response.status, jobs_response.response, saucelabs_api_url)) data = json.loads(jobs_response.getResponse()) filteredJobs = self.filterList(data) jobs = {} nothingFound = "No jobs matching the search criteria were found. Search URL - " + saucelabs_api_url if len(filteredJobs) > 0: print 'Description | Start Time | Build Id | Name | Passed | Link' print ':---: | :---: | :---: | :---: | :---: | :---:' else: print nothingFound jobs["0"] = nothingFound counter = 0 for job in filteredJobs: counter += 1 jobName = job["name"] if job["name"] else " " jobBuildId = job["build"] if job["build"] else " " description = job["os"] + "/" + job["browser"] + "-" + job[ "browser_short_version"] jobPassed = job["passed"] if job["passed"] else " " jobPassedConverted = " " if jobPassed != " ": if job["passed"]: jobPassedConverted = "Passed" else: jobPassedConverted = "Failed" ts = int(job["start_time"]) dateAndTime = datetime.utcfromtimestamp(ts).strftime( '%Y-%m-%d %H:%M:%S') link = "[View](" + self.http_connection.get( "url") + "/jobs/" + job["id"] + ")" print '%s|%s|%s|%s|%s|%s' % (description, dateAndTime, jobBuildId, jobName, jobPassed, link) jobs[str(job["id"])] = jobPassedConverted filteredJobsStr = json.dumps(filteredJobs) return filteredJobsStr, jobs
# from jenkinsci import JenkinsciScript from xlrelease.HttpRequest import HttpRequest import json, urllib jenkins_server = securityApi.decrypt( configurationApi.getConfiguration(request.query['serverId'])) params = { 'url': jenkins_server.url, 'username': jenkins_server.username, 'password': jenkins_server.password, 'proxyHost': jenkins_server.proxyHost, 'proxyPort': jenkins_server.proxyPort, 'proxyUsername': jenkins_server.proxyUsername, 'proxyPassword': jenkins_server.proxyPassword } buildId = request.query['buildId'] jobId = request.query['jobid'] http_request = HttpRequest(params) jenkins_response = http_request.get('/job/' + jobId + '/' + buildId + '/testReport/api/json') if jenkins_response.isSuccessful(): json_data = json.loads(jenkins_response.getResponse()) response.entity = json_data else: error = json.loads(jenkins_response.getResponse()) sys.exit(1)
class ServiceNowClient(object): def __init__(self, httpConnection, username=None, password=None): self.httpConnection = httpConnection 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 get_change_request(self, table_name,sysId): servicenow_api_url = '/api/now/v1/table/%s/%s' % (table_name, sysId) 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 create_record(self, table_name, content): servicenow_api_url = '/api/now/v1/table/%s' % (table_name) response = self.httpRequest.post(servicenow_api_url, body = content, contentType = 'application/json') if response.getStatus() == RECORD_CREATED_STATUS: data = json.loads(response.getResponse()) return data['result'] else: self.throw_error(response) # End if #End create_record def update_record(self, table_name, sysId, content): servicenow_api_url = '/api/now/v1/table/%s/%s' % (table_name, sysId) response = self.httpRequest.put(servicenow_api_url, body = content, contentType = 'application/json') if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] else: self.throw_error(response) # End if #End create_record def find_record( self, table_name, query ): servicenow_api_url = '/api/now/v1/table/%s?%s' % (table_name, query) print "Servic Now URL = %s " % ( servicenow_api_url ) response = self.httpRequest.get( servicenow_api_url, contentType = 'application/json' ) if response.getStatus() == SN_RESULT_STATUS: data = json.loads( response.getResponse() ) return data['result'] else: print "find_record error %s" % ( response ) self.throw_error(response) # End if #End find_record def print_error(self, response): if type(response) is dict: outStr = "| Status | %s |\n" % ( response["status"] ) outStr = "%s| Message | %s |\n" % ( outStr, response["error"]["message"] ) outStr = "%s| Detail | %s |\n" % ( outStr, response["error"]["detail"] ) return outStr # End if return response #End print_error def print_table(self, headers, rows): print "\n|", "|".join(headers), "|" print "|", " ------ |" * len(headers) for r in rows: print "| ", " |".join(r), " |" print "\n" def print_record( self, myObj, outStr = "", prefix="", header=True ): if header: outStr = "%s| Key | Value |\n" % (outStr) outStr = "%s| --- | --- |\n" % (outStr) if type(myObj) is dict: for key in myObj.iterkeys(): value = myObj[key] if type(value) is dict or type(value) is list: p = "%s%s." % (prefix, key) outStr = "%s| %s%s |\n%s" % (outStr, prefix, key, self.print_record( value, "", p, False ) ) else: p = "%s%s" % (prefix, key) outStr = "%s| %s%s |%s |\n" % (outStr, prefix, key, value ) elif type(myObj) is list: for value in myObj: outStr = "%s| | %s\n" % (outStr, value) else: outStr = "%s%s" % (outStr, myObj) # End if return outStr def throw_error(self, response): print "Error from ServiceNow, HTTP Return: %s\n" % (response.getStatus()) sys.exit(1)
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # import json import urllib from xlrelease.HttpRequest import HttpRequest job_context = "/job/" + urllib.quote(jobName) + "/" + buildNumber + "/" request = HttpRequest(server, username, password) response = request.get(job_context + "api/json", contentType="application/json") if not response.isSuccessful(): raise Exception( "Failed to get build information. Server return [%s], with content [%s]" % (response.status, response.response)) result = json.loads(response.response)["result"] if result is None: task.setStatusLine("Waiting for build completion...") task.schedule("jenkins/WaitForCompletion.py", 3) else: if result != "SUCCESS": raise Exception("[Build %s](%s) was not successful - status is %s" % ( buildNumber,
class ServiceNowClient(object): def __init__(self, httpConnection, username=None, password=None): self.headers = {'Content-type': 'application/json; charset=UTF-8'} self.accessToken = None self.refreshToken = None self.httpConnection = httpConnection self.useServicenowApp = httpConnection['useServicenowApp'] self.useOAuth = httpConnection['useOAuth'] self.service_now_url = httpConnection['url'].rstrip("/") if username: self.httpConnection['username'] = username if password: self.httpConnection['password'] = password self.httpRequest = HttpRequest(self.httpConnection, username, password) self.sysparms = 'sysparm_display_value=%s&sysparm_input_display_value=%s' % ( self.httpConnection['sysparmDisplayValue'], self.httpConnection['sysparmInputDisplayValue']) @staticmethod def create_client(httpConnection, username=None, password=None): return ServiceNowClient(httpConnection, username, password) def issue_token(self): tokenData = self.create_token(self.httpConnection) self.accessToken = tokenData['access_token'] self.refreshToken = tokenData['refresh_token'] self.headers['Authorization'] = "Bearer %s" % (self.accessToken) def create_token(self, httpConnection): servicenow_oauth_url = "/oauth_token.do" content = { 'grant_type': 'password', 'client_id': httpConnection['clientId'], 'client_secret': httpConnection['clientSecret'], 'username': httpConnection['oauthUsername'], 'password': httpConnection['oauthPassword'] } httpRequest = HttpRequest(httpConnection, None, None) response = httpRequest.post( servicenow_oauth_url, body=urllib.urlencode(content), contentType='application/x-www-form-urlencoded') if response.getStatus() == SUCCESS_STATUS_CODE: data = json.loads(response.getResponse()) return data print 'Could not get access token' self.throw_error(response) def revoke_token(self): httpRequest = HttpRequest(self.httpConnection, None, None) servicenowApiUrl = "/oauth_revoke_token.do?token=%s" % self.accessToken response = httpRequest.get(servicenowApiUrl) servicenowApiUrl = "/oauth_revoke_token.do?token=%s" % self.refreshToken response = httpRequest.get(servicenowApiUrl) def print_table(self, headers, rows): print "\n|", "|".join(headers), "|" print "|", " ------ |" * len(headers) for r in rows: print "| ", " |".join(r), " |" print "\n" def print_error(self, response): if type(response) is dict: outStr = "| Status | %s |\n" % (response["status"]) outStr = "%s| Message | %s |\n" % (outStr, response["error"]["message"]) outStr = "%s| Detail | %s |\n" % (outStr, response["error"]["detail"]) return outStr return response def create_payload_header(self, table_name, action, identifier, xlr_task_id): return { "table": table_name, "action": action, "identifier": identifier, "xlrTaskId": xlr_task_id } def create_payload(self, header, data): return json.dumps( {"payload": json.dumps({ 'header': header, 'data': data })}) def create_record(self, table_name, content, xlr_task_id): if self.useServicenowApp: payload_header = self.create_payload_header( table_name=table_name, action="create", identifier="", xlr_task_id=xlr_task_id) payload = self.create_payload(header=payload_header, data=content) data = self.request(method='POST', url=SERVICE_NOW_CREATE_URL, body=payload.encode('utf-8'), headers=self.headers)[0] if data["sys_row_error"] != "": raise RuntimeError(data["sys_row_error"]) return data else: servicenow_api_url = '/api/now/table/%s?%s' % (table_name, self.sysparms) body = json.dumps(content) data = self.request(method='POST', url=servicenow_api_url, body=body.encode('utf-8'), headers=self.headers) if 'sys_id' in data: data['target_sys_id'] = data['sys_id'] if 'number' in data: data['target_record_number'] = data['number'] return data def get_record_with_fields(self, table_name, sys_id, fields): servicenow_api_url = '/api/now/table/%s?number=%s&sysparm_fields=%s&%s' % ( table_name, sys_id, ",".join(fields), self.sysparms) response = self.httpRequest.get(servicenow_api_url, contentType='application/json', headers=self.headers) if self.useOAuth: self.revoke_token() if response.getStatus() == SUCCESS_STATUS_CODE: data = json.loads(response.getResponse()) if len(data['result']) == 1: return data['result'][0] self.throw_error(response) def find_record(self, table_name, query): servicenow_api_url = '/api/now/table/%s?sysparm_query=%s&%s' % ( table_name, query, self.sysparms) return self.request(method='GET', url=servicenow_api_url, headers=self.headers) def query(self, table_name, query, fail_on_not_found=False): result = self.find_record(table_name, query) size = len(result) if size == 1: return result[0] elif size > 1: raise Exception( "Expected to find only 1 entry with query '%s' but found %s" % (query, size)) if fail_on_not_found: raise Exception("No results found for query '%s'." % query) return None def get_record(self, table_name, sys_id, fail_on_not_found=False): query = "sys_id=%s" % sys_id return self.query(table_name, query, fail_on_not_found) def find_by_name(self, name, table_name, fail_on_not_found=False): query = "name=%s" % name return self.query(table_name, query, fail_on_not_found) def create_link(self, table_name, sys_id): return "%s/nav_to.do?uri=%s.do?sys_id=%s" % (self.service_now_url, table_name, sys_id) def update_record(self, table_name, sys_id, content, xlr_task_id): if self.useServicenowApp: payload_header = self.create_payload_header( table_name=table_name, action="update", identifier=sys_id, xlr_task_id=xlr_task_id) payload = self.create_payload(header=payload_header, data=content) data = self.request(method='POST', url=SERVICE_NOW_CREATE_URL, body=payload.encode('utf-8'), headers=self.headers)[0] if data["sys_row_error"] != "": raise RuntimeError(data["sys_row_error"]) return data else: servicenow_api_url = '/api/now/table/%s/%s?%s' % ( table_name, sys_id, self.sysparms) body = json.dumps(content) data = self.request(method='PUT', url=servicenow_api_url, body=body.encode('utf-8'), headers=self.headers) if 'sys_id' in data: data['target_sys_id'] = data['sys_id'] if 'number' in data: data['target_record_number'] = data['number'] return data def check_connection(self): """ Currently, there is no direct way to check if connection is successful or not for ServiceNow. As a solution, we are fetching single record from change_request table. :return: First record from change_request table if connection is successful, else throw error. """ servicenow_api_url = '/api/now/table/{}?{}&sysparm_limit={}'.format( 'change_request', self.sysparms, 1) return self.request(method='GET', url=servicenow_api_url, headers=self.headers) def request(self, method, url, headers, content_type='application/json', body=None): if self.useOAuth: self.issue_token() if method == 'GET': response = self.httpRequest.get(url, contentType=content_type, headers=headers) elif method == 'PUT': response = self.httpRequest.put(url, body=body, contentType=content_type, headers=headers) else: response = self.httpRequest.post(url, body=body, contentType=content_type, headers=headers) if self.useOAuth: self.revoke_token() if response.getStatus() == SUCCESS_STATUS_CODE or response.getStatus( ) == RECORD_CREATED_STATUS: try: data = json.loads(response.getResponse()) return data['result'] if 'result' in data else data['records'] except: print response.getResponse() raise RuntimeError("Cannot convert to json") else: print response.getResponse() self.throw_error(response) def throw_error(self, response): print "Error from ServiceNow, HTTP Return: %s\n" % ( response.getStatus()) print "Detailed error: %s\n" % response.response if self.useOAuth: self.revoke_token() sys.exit(1) def EmptyToNone(self, value): if value is None or value.strip() == '': return None else: return value
# configure HttpRequest of XLD # xldeployServer: [u'scriptLocation', u'proxyUsername', u'proxyPassword', u'title', u'proxyHost', u'folderId', u'url', u'proxyPort', u'password', u'authenticationMethod', u'domain', u'verifySSL', u'id', u'username'] if not xldeployServer: raise Exception('Add your XL Deploy server in Tile configuration') if not username: username = xldeployServer.get('username') if not password: password = xldeployServer.get('password') request = HttpRequest({"url": xldeployServer.get('url')}, username=username, password=password) # get license info --- response = request.get('/deployit/internal/configuration/license-info', accept='application/json', contentType='application/json') if response.status != 200: msg = 'ERROR: Unable to get license info. Status %s' % response.status logging.error(msg) raise Exception(msg) lic = json.loads(response.response) #logging.debug("license-info --------------") #logging.debug(lic) # get role info ---- response = request.get('/deployit/security/role/principals', accept='application/json',
fromRegion, toRegion = increment_time_windows(fromDate, dateAggregation) dates = [] deployments = [] change_failure = [] period_covered = False while fromRegion < toDate: deployment_count = 0 rollback_count = 0 results_remain = True page = 1 while results_remain: endpoint = '/deployit/tasks/v2/query?begindate={0}&enddate={1}&page={2}&resultsPerPage={3}'.format( fromRegion, toRegion, page, PAGESIZE) response = request.get(endpoint, contentType='application/json') if not response.isSuccessful(): raise Exception( "Failed to get deployment data from XL Deploy. Server return [%s], with content [%s]" % (response.status, response.response)) results = json.loads(response.response) if results == []: results_remain = False else: for result in results: if result["metadata"]["taskType"] in [ "INITIAL", "UPGRADE", "UNDEPLOY" ]: deployment_count += 1 elif result["metadata"]["taskType"] == "ROLLBACK": rollback_count += 1
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # import json from xlrelease.HttpRequest import HttpRequest if not sonarServer: raise Exception("Sonar server ID must be provided") sonar_url = sonarServer['url'] sonar_server_api_url = '/api/measures/component?componentKey=%s&metricKeys=%s' % (resource, ','.join(metrics.keys())) http_request = HttpRequest(sonarServer, username, password) sonar_response = http_request.get(sonar_server_api_url) if sonar_response.isSuccessful(): json_data = json.loads(sonar_response.getResponse()) data1 = {} data1['id'] = json_data['component']['id'] data1['key'] = json_data['component']['key'] data1['name'] = json_data['component']['name'] data1['sonarUrl'] = sonar_url for item in json_data['component']['measures']: data1[item['metric']] = item['value'] data = data1 else: error = json.loads(sonar_response.getResponse()) if 'Invalid table' in error['error']['message']: print "Invalid Table Name" data = {"Invalid table name"}
class VersionOneClient(object): def __init__(self, v1CI): self.Token = v1CI['accessToken'] self.uriBase = v1CI['uriBase'] self.storyStatus = v1CI['StoryStatus'] self.httpConnection = v1CI self.httpRequest = HttpRequest(v1CI) self.optionHeader = { "Accept": "application/json", "Authorization": "Bearer %s" % self.Token } # End def @staticmethod def create_v1Client(v1CI): return VersionOneClient(v1CI) # End def def getStories(self, whereClause=None): uri = "%s/rest-1.v1/Data/Story" % self.uriBase if whereClause is not None: uri = "%s?where=%s" % (uri, whereClause) # End if print("getStories uri = %s" % uri) print("Headers = %s" % self.optionHeader) response = self.httpRequest.get(uri, headers=self.optionHeader) reqStatus = response.getStatus() print("Request Status %s" % reqStatus) if reqStatus == STATUS_OK: return json.loads(response.getResponse()) # End if raise ValueError('Error getting stories', reqStatus) # End def def updateStoryStatus(self, ticket, status): whereClause = "Number='%s'" % ticket data = self.getStories(whereClause) uri = data['Assets'][0]['href'] xml = "<Asset> <Relation name=\"Status\" act=\"set\"> <Asset idref=\"StoryStatus:%s\" /> </Relation> </Asset>" % self.storyStatus[ status] print("Update Status uri = %s" % uri) print("Update Status XML ~%s~" % xml) print("Update Status Headers = %s" % self.optionHeader) response = self.httpRequest.post(uri, xml, headers=self.optionHeader) reqStatus = response.getStatus() print("Request Status %s" % reqStatus) if reqStatus == STATUS_OK: return # End if raise ValueError('Error getting stories', reqStatus) # End def def get_story_status_list(self): uri = "%s/rest-1.v1/Data/StoryStatus" % self.uriBase print("getStoryStatus uri = %s" % uri) print("Headers = %s" % self.optionHeader) response = self.httpRequest.get(uri, headers=self.optionHeader) req_status = response.getStatus() print("Request Status %s" % req_status) if req_status == STATUS_OK: return json.loads(response.getResponse()) # End if raise ValueError('Error getting stories', req_status)
class XLDeployClient(object): def __init__(self, httpConnection, username=None, password=None): self.http_request = 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('state2="') state_offset = len('state2="') 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.http_request.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.http_request.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.http_request.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, fail_on_pause=True): 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.http_request.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.http_request.get( get_task_status_url, contentType='application/xml') task_state_xml = task_state_response.getResponse() # print 'DEBUG task_state_xml is ' + task_state_xml status = self.extract_state(task_state_xml) print 'Task', task_id, 'now in state', status, '\n' if fail_on_pause: if status in ( 'FAILED', 'ABORTED', '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', 'ABORTED', 'STOPPED', 'CANCELLED', 'DONE', 'EXECUTED'): break else: if status in ( 'FAILED', 'ABORTED' ) 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', 'ABORTED', 'CANCELLED', 'DONE', 'EXECUTED'): break time.sleep(polling_interval) return status def get_deployment_package(self, deployed_application_id): ci = self.get_ci(deployed_application_id, 'json') data = json.loads(ci) return data['version'] def deployment_exists(self, deployment_package, environment): deployment_exists_url = "/deployit/deployment/exists?application=%s&environment=%s" % ( deployment_package.rsplit('/', 1)[0], environment) # print 'DEBUG: checking deployment exists with url %s \n' % deployment_exists_url deployment_exists_response = self.http_request.get( deployment_exists_url, contentType='application/xml') response = deployment_exists_response.getResponse() return 'true' in response def deployment_prepare_undeploy(self, deployed_application_id): deployment_prepare_undeploy_url = "/deployit/deployment/prepare/undeploy?deployedApplication=%s" % ( deployed_application_id) deployment_prepare_undeploy_url_response = self.http_request.get( deployment_prepare_undeploy_url, contentType='application/xml') return deployment_prepare_undeploy_url_response.getResponse() 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.http_request.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.http_request.get( deploymentPrepareInitialUrl, contentType='application/xml') return deploymentPrepareInitial_response.getResponse() def add_orchestrators(self, deployment_xml, orchestrators): root = ET.fromstring(deployment_xml) if orchestrators: params = root.find(".//orchestrator") params.clear() orchs = orchestrators.split(",") for orch in orchs: orchestrator = ET.SubElement(params, 'value') orchestrator.text = orch.strip() return ET.tostring(root) def set_deployed_application_properties(self, deployment_xml, deployed_application_properties): root = ET.fromstring(deployment_xml) if deployed_application_properties: deployeds_application_properties_dict = dict( ast.literal_eval(deployed_application_properties)) # print 'DEBUG: deployed application properties dict is %s \n' % deployeds_application_properties_dict # print 'DEBUG: Deployment object is now: %s \n' % ET.tostring(root) for key in deployeds_application_properties_dict: # print "DEBUG: Key is %s" % key pkey_xml = root.find(key) if not pkey_xml: application = root.find("application") for child in application: # print "DEBUG: Going to add key: %s" % key # print "DEBUG: Searching for deployed application: %s" % child pkey_xml = ET.SubElement(child, key) pkey_xml.text = deployeds_application_properties_dict[key] return ET.tostring(root) def set_deployed_properties(self, deployment_xml, deployed_properties): root = ET.fromstring(deployment_xml) 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] return ET.tostring(root) 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.http_request.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() # print 'DEBUG: deployment_xml is ' + deployment_xml deployment_xml = self.add_orchestrators(deployment_xml, orchestrators) deployment_xml = self.set_deployed_application_properties( deployment_xml, deployed_application_properties) # print 'DEBUG: Deployment object after updating orchestrators: %s \n' % ET.tostring(root) deployment_xml = self.set_deployed_properties(deployment_xml, deployed_properties) return deployment_xml def get_deployment_task_id(self, deployment): getDeploymentTaskId = "/deployit/deployment" # print 'DEBUG: creating task id for deployment object %s \n' % deployment deploymentTaskId_response = self.http_request.post( getDeploymentTaskId, deployment, contentType='application/xml') # print 'DEBUG: getDeploymentTaskId response is %s \n' % (deploymentTaskId_response.getResponse()) return deploymentTaskId_response.getResponse() def deployment_rollback(self, taskId): deploymentRollback = "/deployit/deployment/rollback/%s" % taskId # print 'DEBUG: calling rollback for taskId %s \n' % taskId deploymentRollback_response = self.http_request.post( deploymentRollback, '', contentType='application/xml') # print 'DEBUG: received rollback taskId %s \n' % deploymentRollback_response.getResponse() return deploymentRollback_response.getResponse() def archive_task(self, task_id): archive_task = "/deployit/task/%s/archive" % task_id self.http_request.post(archive_task, '', contentType='application/xml') def cancel_task(self, taskId): cancelTask = "/deployit/task/%s" % taskId self.http_request.delete(cancelTask, contentType='application/xml') def stop_task(self, taskId): stopTask = "/deployit/task/%s/stop" % taskId self.http_request.post(stopTask, '', contentType='application/xml') def get_download_uuid(self, deploymentPackage): exportTask = "/deployit/export/deploymentpackage/%s" % deploymentPackage exportTask_response = self.http_request.get( exportTask, contentType='application/xml') return exportTask_response.getResponse() def fetch_package(self, fetchURL): fetchTask = "/deployit/package/fetch" self.http_request.post(fetchTask, fetchURL, contentType='application/xml') def get_latest_package_version(self, application_id): query_task = "/deployit/repository/query?parent=%s&resultsPerPage=-1" % application_id query_task_response = self.http_request.get( query_task, contentType='application/xml') root = ET.fromstring(query_task_response.getResponse()) items = root.findall('ci') latest_package = '' if len(items) > 0: latest_package = items[-1].attrib['ref'] return latest_package def get_latest_deployed_version(self, environment_id, application_name): query_task_response = self.get_ci( self, "%s/%s" % (environment_id, application_name), 'xml') root = ET.fromstring(query_task_response) items = root.findall('version') latest_package = '' for item in items: latest_package = item.attrib['ref'] # End for return latest_package def check_CI_exist(self, ci_id): queryTask = "/deployit/repository/exists/%s" % ci_id queryTask_response = self.http_request.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.http_request.post(createTask, xml, contentType='application/xml') def create_application(self, appId): createTask = "/deployit/repository/ci/%s" % appId xml = '<udm.Application id="' + appId + '" />' self.http_request.post(createTask, xml, contentType='application/xml') def createCI(self, id, ciType, xmlDescriptor): xml = '<' + ciType + ' id="' + id + '">' + xmlDescriptor + '</' + ciType + '>' createTask = '/deployit/repository/ci/' + id self.http_request.post(createTask, xml, contentType='application/xml') def update_ci_property(self, ci_id, ci_property, property_value): if self.check_CI_exist(ci_id): ci = self.get_ci(ci_id, 'json') data = json.loads(ci) data[ci_property] = property_value self.update_ci(ci_id, json.dumps(data), 'json') else: raise Exception("Did not find ci with id [%s]" % ci_id) def add_ci_to_environment(self, env_id, ci_id): get_env_response = self.get_ci(self, env_id, 'xml') items = get_env_response.partition('</members>') xml = items[0] + '<ci ref="' + ci_id + '"/>' + items[1] + items[2] print(xml) self.update_ci(env_id, xml, 'xml') def remove_ci_from_environment(self, env_id, ci_id): get_env_response = self.get_ci(self, env_id, 'xml') print get_env_response env_root = ET.fromstring(get_env_response) member_to_remove = None for child in env_root: if child.tag == 'members': for member in child: if member.attrib['ref'] == ci_id: print 'Found ' + ci_id + ' in ' + env_id env_members = child member_to_remove = member if member_to_remove is not None: print 'Removing ' + ci_id + ' from ' + env_id env_members.remove(member_to_remove) self.update_ci(env_id, ET.tostring(env_root), 'xml') def get_ci(self, ci_id, accept): get_ci = "/deployit/repository/ci/%s" % (ci_id) headers = {'Accept': 'application/%s' % accept} return self.http_request.get(get_ci, headers=headers).getResponse() def update_ci(self, ci_id, data, content_type): update_ci = "/deployit/repository/ci/%s" % ci_id content_type_header = "application/%s" % content_type response = self.http_request.put(update_ci, data, contentType=content_type_header) if not response.isSuccessful(): raise Exception( "Failed to update ci [%s]. Server return [%s], with content [%s]" % (ci_id, response.status, response.response)) def delete_ci(self, ci_id): delete_task = '/deployit/repository/ci/' + ci_id self.http_request.delete(delete_task) def display_step_logs(self, task_id): get_task_steps = '/deployit/task/' + task_id + '/step' get_task_steps_response = self.http_request.get( get_task_steps, contentType='application/xml') task_steps_root = ET.fromstring(get_task_steps_response.getResponse()) for child in task_steps_root: if child.tag == 'steps': step_counter = 0 for grandchild in child: if grandchild.tag == 'step': step_counter = step_counter + 1 print 'DEPLOYMENT STEP %d: Failures=%s State=%s\n' % ( step_counter, str(grandchild.attrib['failures']), str(grandchild.attrib['state'])) for item in grandchild: if item.tag in ('description', 'startDate', 'completionDate'): print '%s %s\n' % (str(item.tag), str( item.text)) else: print str(item.tag) + '\n' print str(item.text) + '\n'
class XLTestViewClient(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 XLTestViewClient(http_connection, username, password) def cmp_version(self, version1, version2): def normalize(v): return [int(x) for x in re.sub(r'(\.0+)*$','', v).split(".")] return cmp(normalize(version1), normalize(version2)) def check_xltestview_version(self): xltestview_api_url = "/api/v1/info" info_response = self.http_request.get(xltestview_api_url, contentType='application/json') result = json.loads(info_response.getResponse()) if self.cmp_version(result['version'],'1.4.0') < 0: print "Version %s not supported." % result['version'] sys.exit(1) else: print "Version %s supported." % result['version'] def get_test_specification_id(self, test_specification_name): # Fetch test specification information xltestview_api_url = "/api/internal/testspecifications" test_specifications_response = self.http_request.get(xltestview_api_url, contentType='application/json') data = json.loads(test_specifications_response.getResponse()) if data is not None: for test_spec in data: if test_spec is not None and test_spec['title'].startswith(test_specification_name): return test_spec['name'] return None def get_test_specification_qualification(self, test_specification_name): test_specification_id = self.get_test_specification_id(test_specification_name) xltestview_api_url = "/api/v1/qualifications?testSpecification=%s" % test_specification_id test_specification_response = self.http_request.get(xltestview_api_url, contentType='application/json') result = json.loads(test_specification_response.getResponse()) if result['result']: print 'TestSpec %s qualified as PASSED' % test_specification_name return True else: print 'TestSpec %s qualified as FAILED' % test_specification_name print 'Reason: *%s*' % result['message'] return False def is_test_specification_running(self, test_specification_name): # Checking and waiting until test is finished test_specification_id = self.get_test_specification_id(test_specification_name) xltestview_api_url = "/api/internal/projects/%s/status" % test_specification_id headers = {'Accept': 'text/event-stream', 'Content-Type': ''} test_specification_response = self.http_request.get(xltestview_api_url, headers = headers) if not test_specification_response.isSuccessful(): raise Exception("Failed to get test specification state. Server return [%s], with content [%s]" % (test_specification_response.status, test_specification_response.response)) if 'running' in test_specification_response.getResponse(): print "Test Specification is running" return True else: print "Test Specification is not running" return False def execute_test_specification(self, test_specification_name): test_specification_id = self.get_test_specification_id(test_specification_name) xltestview_api_url = "/api/internal/execute/%s" % test_specification_id content = '{"id":"%s"}' % test_specification_id test_specification_response = self.http_request.post(xltestview_api_url, content, contentType='application/json') result = json.loads(test_specification_response.getResponse()) return result['taskId']
import json from xlrelease.HttpRequest import HttpRequest if accessToken is not None and accessToken.strip() == "": accessToken = None url = "/repos/%s/commits?sha=%s%s" % \ (repositoryId, branch, "&access_token=" + accessToken if accessToken else "") print "Querying commits from GitHub API by URL %s" % url request = HttpRequest({"url": "https://api.github.com"}) response = request.get(url, contentType='application/json') if response.status != 200: raise Exception("Request to GitHub failed with status %s, response %s" % (response.status, response.response)) commits = json.loads(response.response) data = {"commits": commits}
class XLDeployClient(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 XLDeployClient(http_connection, username, password) def extract_state(self, task_state_xml): state_pos = task_state_xml.find('state2="') state_offset = len('state2="') 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.http_request.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.http_request.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.http_request.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, fail_on_pause=True): 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.http_request.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.http_request.get(get_task_status_url, contentType='application/xml') task_state_xml = task_state_response.getResponse() # print 'DEBUG task_state_xml is ' + task_state_xml status = self.extract_state(task_state_xml) print 'Task', task_id, 'now in state', status, '\n' if fail_on_pause: if status in ('FAILED', 'ABORTED', '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', 'ABORTED', 'STOPPED', 'CANCELLED', 'DONE', 'EXECUTED'): break else: if status in ('FAILED', 'ABORTED') 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', 'ABORTED', 'CANCELLED', 'DONE', 'EXECUTED'): break time.sleep(polling_interval) return status def get_deployment_package(self, deployed_application_id): ci = self.get_ci(deployed_application_id, 'json') data = json.loads(ci) return data['version'] def deployment_exists(self, deployment_package, environment): deployment_exists_url = "/deployit/deployment/exists?application=%s&environment=%s" % (deployment_package.rsplit('/', 1)[0], environment) # print 'DEBUG: checking deployment exists with url %s \n' % deployment_exists_url deployment_exists_response = self.http_request.get(deployment_exists_url, contentType='application/xml') response = deployment_exists_response.getResponse() return 'true' in response def deployment_prepare_undeploy(self, deployed_application_id): deployment_prepare_undeploy_url = "/deployit/deployment/prepare/undeploy?deployedApplication=%s" % (deployed_application_id) deployment_prepare_undeploy_url_response = self.http_request.get(deployment_prepare_undeploy_url, contentType='application/xml') return deployment_prepare_undeploy_url_response.getResponse() 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.http_request.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.http_request.get(deploymentPrepareInitialUrl, contentType='application/xml') return deploymentPrepareInitial_response.getResponse() def add_orchestrators(self, deployment_xml, orchestrators): root = ET.fromstring(deployment_xml) if orchestrators: params = root.find(".//orchestrator") params.clear() orchs = orchestrators.split(",") for orch in orchs: orchestrator = ET.SubElement(params, 'value') orchestrator.text = orch.strip() return ET.tostring(root) def set_deployed_application_properties(self, deployment_xml, deployed_application_properties): root = ET.fromstring(deployment_xml) if deployed_application_properties: deployeds_application_properties_dict = dict(ast.literal_eval(deployed_application_properties)) # print 'DEBUG: deployed application properties dict is %s \n' % deployeds_application_properties_dict # print 'DEBUG: Deployment object is now: %s \n' % ET.tostring(root) for key in deployeds_application_properties_dict: # print "DEBUG: Key is %s" % key pkey_xml = root.find(key) if not pkey_xml: application = root.find("application") for child in application: # print "DEBUG: Going to add key: %s" % key # print "DEBUG: Searching for deployed application: %s" % child pkey_xml = ET.SubElement(child, key) pkey_xml.text = deployeds_application_properties_dict[key] return ET.tostring(root) def set_deployed_properties(self, deployment_xml, deployed_properties): root = ET.fromstring(deployment_xml) 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] return ET.tostring(root) 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.http_request.post(deployment_prepare_deployeds, deployment, contentType='application/xml') if not deployment_prepare_deployeds_response.isSuccessful(): raise Exception("Failed to prepare deployeds. Server return [%s], with content [%s]" % (deployment_prepare_deployeds_response.status, deployment_prepare_deployeds_response.response)) deployment_xml = deployment_prepare_deployeds_response.getResponse() # print 'DEBUG: deployment_xml is ' + deployment_xml deployment_xml = self.add_orchestrators(deployment_xml, orchestrators) deployment_xml = self.set_deployed_application_properties(deployment_xml, deployed_application_properties) # print 'DEBUG: Deployment object after updating orchestrators: %s \n' % ET.tostring(root) deployment_xml = self.set_deployed_properties(deployment_xml, deployed_properties) return deployment_xml def validate(self, deployment): getDeploymentTaskId = "/deployit/deployment/validate" # print 'DEBUG: validate for deployment object %s \n' % deployment deploymentWithValidation_response = self.http_request.post(getDeploymentTaskId, deployment, contentType='application/xml') # print 'DEBUG: deploymentWithValidation response is %s \n' % (deploymentWithValidation_response.getResponse()) deployment = deploymentWithValidation_response.getResponse() root = ET.fromstring(deployment) return map(lambda vm: "CI: %s Message: %s" % (vm.attrib['ci'], vm.text), root.iter('validation-message')) def get_deployment_task_id(self, deployment): getDeploymentTaskId = "/deployit/deployment" # print 'DEBUG: creating task id for deployment object %s \n' % deployment deploymentTaskId_response = self.http_request.post(getDeploymentTaskId, deployment, contentType='application/xml') # print 'DEBUG: getDeploymentTaskId response is %s \n' % (deploymentTaskId_response.getResponse()) return deploymentTaskId_response.getResponse() def deployment_rollback(self, taskId): deploymentRollback = "/deployit/deployment/rollback/%s" % taskId # print 'DEBUG: calling rollback for taskId %s \n' % taskId deploymentRollback_response = self.http_request.post(deploymentRollback, '', contentType='application/xml') # print 'DEBUG: received rollback taskId %s \n' % deploymentRollback_response.getResponse() return deploymentRollback_response.getResponse() def archive_task(self, task_id): archive_task = "/deployit/task/%s/archive" % task_id self.http_request.post(archive_task, '', contentType='application/xml') def cancel_task(self, taskId): cancelTask = "/deployit/task/%s" % taskId self.http_request.delete(cancelTask, contentType='application/xml') def stop_task(self, taskId): stopTask = "/deployit/task/%s/stop" % taskId self.http_request.post(stopTask, '', contentType='application/xml') def get_download_uuid(self, deploymentPackage): exportTask = "/deployit/export/deploymentpackage/%s" % deploymentPackage exportTask_response = self.http_request.get(exportTask, contentType='application/xml') return exportTask_response.getResponse() def fetch_package(self, fetchURL): fetchTask = "/deployit/package/fetch" self.http_request.post(fetchTask, fetchURL, contentType='application/xml') def get_latest_package_version(self, application_id): query_task = "/deployit/repository/query?parent=%s&resultsPerPage=-1" % application_id query_task_response = self.http_request.get(query_task, contentType='application/xml') root = ET.fromstring(query_task_response.getResponse()) items = root.findall('ci') latest_package = '' if len(items) > 0: latest_package = items[-1].attrib['ref'] return latest_package def get_latest_deployed_version(self, environment_id, application_name): query_task_response = self.get_ci("%s/%s" % (environment_id, application_name), 'xml') root = ET.fromstring(query_task_response) items = root.findall('version') latest_package = '' for item in items: latest_package = item.attrib['ref'] # End for return latest_package def check_CI_exist(self, ci_id): query_task = "/deployit/repository/exists/%s" % ci_id query_task_response = self.http_request.get(query_task, contentType='application/xml') if not query_task_response.isSuccessful(): raise Exception("Failed to check ci [%s]. Server return [%s], with content [%s]" % (ci_id, query_task_response.status, query_task_response.response)) return query_task_response.getResponse().find('true') > 0 def create_directory(self, ciId): createTask = "/deployit/repository/ci/%s" % ciId xml = '<core.Directory id="' + ciId + '" />' self.http_request.post(createTask, xml, contentType='application/xml') def create_application(self, appId): createTask = "/deployit/repository/ci/%s" % appId xml = '<udm.Application id="' + appId + '" />' self.http_request.post(createTask, xml, contentType='application/xml') def createCI(self, id, ciType, xmlDescriptor): xml = '<' + ciType + ' id="' + id + '">' + xmlDescriptor + '</' + ciType + '>' createTask = '/deployit/repository/ci/' + id self.http_request.post(createTask, xml, contentType='application/xml') def update_ci_property(self, ci_id, ci_property, property_value): if self.check_CI_exist(ci_id): ci = self.get_ci(ci_id, 'json') data = json.loads(ci) data[ci_property] = property_value self.update_ci(ci_id, json.dumps(data), 'json') else: raise Exception("Did not find ci with id [%s]" % ci_id) def add_ci_to_environment(self, env_id, ci_id): get_env_response = self.get_ci(env_id, 'xml') items = get_env_response.partition('</members>') xml = items[0] + '<ci ref="' + ci_id + '"/>' + items[1] + items[2] print(xml) self.update_ci(env_id, xml, 'xml') def remove_ci_from_environment(self, env_id, ci_id): get_env_response = self.get_ci(env_id, 'xml') print get_env_response env_root = ET.fromstring(get_env_response) member_to_remove = None for child in env_root: if child.tag == 'members': for member in child: if member.attrib['ref'] == ci_id: print 'Found ' + ci_id + ' in ' + env_id env_members = child member_to_remove = member if member_to_remove is not None: print 'Removing ' + ci_id + ' from ' + env_id env_members.remove(member_to_remove) self.update_ci(env_id, ET.tostring(env_root), 'xml') def get_ci(self, ci_id, accept): get_ci = "/deployit/repository/ci/%s" % ci_id headers = {'Accept': 'application/%s' % accept} response = self.http_request.get(get_ci, headers=headers) if not response.isSuccessful(): raise Exception("Failed to get ci [%s]. Server return [%s], with content [%s]" % (ci_id, response.status, response.response)) return response.getResponse() def update_ci(self, ci_id, data, content_type): update_ci = "/deployit/repository/ci/%s" % ci_id content_type_header = "application/%s" % content_type response = self.http_request.put(update_ci, data, contentType=content_type_header) if not response.isSuccessful(): raise Exception("Failed to update ci [%s]. Server return [%s], with content [%s]" % (ci_id, response.status, response.response)) def delete_ci(self, ci_id): delete_task = '/deployit/repository/ci/' + ci_id self.http_request.delete(delete_task) def display_step_logs(self, task_id): get_task_steps = '/deployit/task/' + task_id + '/step' get_task_steps_response = self.http_request.get(get_task_steps, contentType='application/xml') task_steps_root = ET.fromstring(get_task_steps_response.getResponse()) for child in task_steps_root: if child.tag == 'steps': step_counter = 0 for grandchild in child: if grandchild.tag == 'step': step_counter = step_counter + 1 print 'DEPLOYMENT STEP %d: Failures=%s State=%s\n' % (step_counter, str(grandchild.attrib['failures']), str(grandchild.attrib['state'])) for item in grandchild: if item.tag in ('description', 'startDate', 'completionDate'): print '%s %s\n' % (item.tag, item.text) else: print "%s\n" % item.tag print "%s\n" % item.text
class ServiceNowClient(object): def __init__(self, httpConnection, username=None, password=None): self.headers = {} self.accessToken = None self.refreshToken = None self.httpConnection = httpConnection self.useOAuth = httpConnection['useOAuth'] if username: self.httpConnection['username'] = username if password: self.httpConnection['password'] = password self.httpRequest = HttpRequest(self.httpConnection, username, password) self.sysparms = 'sysparm_display_value=%s&sysparm_input_display_value=%s' % (self.httpConnection['sysparmDisplayValue'], self.httpConnection['sysparmInputDisplayValue']) @staticmethod def create_client(httpConnection, username=None, password=None): return ServiceNowClient(httpConnection, username, password) def get_change_request_states(self): if self.useOAuth : self.issue_token() servicenow_api_url = '/api/now/v1/table/%s?element=state&name=task&sysparm_fields=%s&%s' % ('sys_choice', 'value,label', self.sysparms) response = self.httpRequest.get(servicenow_api_url, contentType='application/json', headers = self.headers) if self.useOAuth :self.revoke_token() if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] self.throw_error(response) def get_scorecards(self): if self.useOAuth :self.issue_token() servicenow_api_url = '/api/now/v1/pa/scorecards' response = self.httpRequest.get(servicenow_api_url, contentType='application/json', headers = self.headers) if self.useOAuth :self.revoke_token() if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] self.throw_error(response) def get_change_request_with_fields(self, table_name, number, fields): if self.useOAuth :self.issue_token() servicenow_api_url = '/api/now/v1/table/%s?number=%s&sysparm_fields=%s&%s' % (table_name, number, ",".join(fields), self.sysparms) response = self.httpRequest.get(servicenow_api_url, contentType='application/json', headers = self.headers) if self.useOAuth :self.revoke_token() 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 get_change_request(self, table_name, sys_id): if self.useOAuth :self.issue_token() servicenow_api_url = '/api/now/v1/table/%s/%s?%s' % (table_name, sys_id, self.sysparms) response = self.httpRequest.get(servicenow_api_url, contentType='application/json', headers = self.headers) if self.useOAuth :self.revoke_token() if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] self.throw_error(response) def create_record(self, table_name, content): if self.useOAuth :self.issue_token() servicenow_api_url = '/api/now/v1/table/%s?%s' % (table_name, self.sysparms) response = self.httpRequest.post(servicenow_api_url, body=content, contentType='application/json', headers = self.headers) if self.useOAuth :self.revoke_token() if response.getStatus() == RECORD_CREATED_STATUS: data = json.loads(response.getResponse()) return data['result'] else: self.throw_error(response) # End if # End create_record def update_record(self, table_name, sysId, content): if self.useOAuth :self.issue_token() servicenow_api_url = '/api/now/v1/table/%s/%s?%s' % (table_name, sysId, self.sysparms) response = self.httpRequest.put(servicenow_api_url, body=content, contentType='application/json', headers = self.headers) if self.useOAuth :self.revoke_token() if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] else: self.throw_error(response) # End if # End create_record def find_record(self, table_name, query): if self.useOAuth :self.issue_token() servicenow_api_url = '/api/now/v1/table/%s?%s&%s' % (table_name, query, self.sysparms) print "Service Now URL = %s " % (servicenow_api_url) response = self.httpRequest.get(servicenow_api_url, contentType='application/json', headers = self.headers) if self.useOAuth :self.revoke_token() if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] else: print "find_record error %s" % (response) self.throw_error(response) # End if # End find_record def print_error(self, response): if type(response) is dict: outStr = "| Status | %s |\n" % ( response["status"] ) outStr = "%s| Message | %s |\n" % ( outStr, response["error"]["message"] ) outStr = "%s| Detail | %s |\n" % ( outStr, response["error"]["detail"] ) return outStr # End if return response #End print_error def print_table(self, headers, rows): print "\n|", "|".join(headers), "|" print "|", " ------ |" * len(headers) for r in rows: print "| ", " |".join(r), " |" print "\n" def print_record(self, myObj, outStr="", prefix="", header=True): if header: outStr = "%s| Key | Value |\n" % (outStr) outStr = "%s| --- | --- |\n" % (outStr) if type(myObj) is dict: for key in myObj.iterkeys(): value = myObj[key] if type(value) is dict or type(value) is list: p = "%s%s." % (prefix, key) outStr = "%s| %s%s |\n%s" % (outStr, prefix, key, self.print_record(value, "", p, False)) else: p = "%s%s" % (prefix, key) outStr = "%s| %s%s |%s |\n" % (outStr, prefix, key, value) elif type(myObj) is list: for value in myObj: outStr = "%s| | %s\n" % (outStr, value) else: outStr = "%s%s" % (outStr, myObj) # End if return outStr def throw_error(self, response): print "Error from ServiceNow, HTTP Return: %s\n" % (response.getStatus()) print "Detailed error: %s\n" % response.response if self.useOAuth :self.revoke_token() sys.exit(1) def EmptyToNone(self,value): if value is None: return None elif value.strip() == '': return None else: return value def issue_token(self): print "Issuing a new token" tokenData = self.create_token(self.httpConnection) self.set_token_header(tokenData) def create_token(self, httpConnection): servicenow_oauth_url = "/oauth_token.do" content = {} content['grant_type'] = 'password' content['client_id'] = httpConnection['clientId'] content['client_secret'] = httpConnection['clientSecret'] content['username'] = httpConnection['oauthUsername'] content['password'] = httpConnection['oauthPassword'] httpRequest = HttpRequest(httpConnection, None, None) response = httpRequest.post(servicenow_oauth_url, body=urllib.urlencode(content), contentType='application/x-www-form-urlencoded') if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data print 'Could not get access token' self.throw_error(response) def refresh_token(self, httpConnection, refreshToken): servicenowUrl = "/oauth_token.do" content = {} content['grant_type'] = 'refresh_token' content['client_id'] = httpConnection['clientId'] content['client_secret'] = httpConnection['clientSecret'] content['refresh_token'] = refreshToken httpRequest = HttpRequest(httpConnection, None, None) response = httpRequest.post(servicenowUrl, body=urllib.urlencode(content), contentType='application/x-www-form-urlencoded') if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data print "Unable to refresh token using %s" % refreshToken self.throw_error(response) def set_token_header(self, tokenData): self.accessToken = tokenData['access_token'] self.refreshToken = tokenData['refresh_token'] self.headers['Authorization'] = "Bearer %s" % (self.accessToken) def revoke_token(self): print "Revoking token" httpRequest = HttpRequest(self.httpConnection, None, None) servicenowApiUrl = "/oauth_revoke_token.do?token=%s" % self.accessToken response = httpRequest.get(servicenowApiUrl) servicenowApiUrl = "/oauth_revoke_token.do?token=%s" % self.refreshToken response = httpRequest.get(servicenowApiUrl)
class ServiceNowClient(object): def __init__(self, httpConnection, username=None, password=None): self.headers = {} self.accessToken = None self.refreshToken = None self.httpConnection = httpConnection self.useOAuth = httpConnection['useOAuth'] if username is not None: self.httpConnection['username'] = username if password is not None: self.httpConnection['password'] = password self.httpRequest = HttpRequest(self.httpConnection, username, password) self.sysparms = 'sysparm_display_value=%s&sysparm_input_display_value=%s' % ( self.httpConnection['sysparmDisplayValue'], self.httpConnection['sysparmInputDisplayValue']) @staticmethod def create_client(httpConnection, username=None, password=None): return ServiceNowClient(httpConnection, username, password) def get_change_request_states(self): if self.useOAuth: self.issue_token() servicenow_api_url = '/api/now/v1/table/%s?element=state&name=task&sysparm_fields=%s&%s' % ( 'sys_choice', 'value,label', self.sysparms) response = self.httpRequest.get(servicenow_api_url, contentType='application/json', headers=self.headers) if self.useOAuth: self.revoke_token() if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] self.throw_error(response) def get_scorecards(self): if self.useOAuth: self.issue_token() servicenow_api_url = '/api/now/v1/pa/scorecards' response = self.httpRequest.get(servicenow_api_url, contentType='application/json', headers=self.headers) if self.useOAuth: self.revoke_token() if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] self.throw_error(response) def get_change_request_with_fields(self, table_name, number, fields): if self.useOAuth: self.issue_token() servicenow_api_url = '/api/now/v1/table/%s?number=%s&sysparm_fields=%s&%s' % ( table_name, number, ",".join(fields), self.sysparms) response = self.httpRequest.get(servicenow_api_url, contentType='application/json', headers=self.headers) if self.useOAuth: self.revoke_token() 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 get_change_request(self, table_name, sysId): if self.useOAuth: self.issue_token() servicenow_api_url = '/api/now/v1/table/%s/%s?%s' % (table_name, sysId, self.sysparms) response = self.httpRequest.get(servicenow_api_url, contentType='application/json', headers=self.headers) if self.useOAuth: self.revoke_token() if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] self.throw_error(response) def create_record(self, table_name, content): if self.useOAuth: self.issue_token() servicenow_api_url = '/api/now/v1/table/%s?%s' % (table_name, self.sysparms) response = self.httpRequest.post(servicenow_api_url, body=content, contentType='application/json', headers=self.headers) if self.useOAuth: self.revoke_token() if response.getStatus() == RECORD_CREATED_STATUS: data = json.loads(response.getResponse()) return data['result'] else: self.throw_error(response) # End if # End create_record def update_record(self, table_name, sysId, content): if self.useOAuth: self.issue_token() servicenow_api_url = '/api/now/v1/table/%s/%s?%s' % (table_name, sysId, self.sysparms) response = self.httpRequest.put(servicenow_api_url, body=content, contentType='application/json', headers=self.headers) if self.useOAuth: self.revoke_token() if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] else: self.throw_error(response) # End if # End create_record def find_record(self, table_name, query): if self.useOAuth: self.issue_token() servicenow_api_url = '/api/now/v1/table/%s?%s&%s' % (table_name, query, self.sysparms) print "Servic Now URL = %s " % (servicenow_api_url) response = self.httpRequest.get(servicenow_api_url, contentType='application/json', headers=self.headers) if self.useOAuth: self.revoke_token() if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] else: print "find_record error %s" % (response) self.throw_error(response) # End if # End find_record def print_error(self, response): if type(response) is dict: outStr = "| Status | %s |\n" % (response["status"]) outStr = "%s| Message | %s |\n" % (outStr, response["error"]["message"]) outStr = "%s| Detail | %s |\n" % (outStr, response["error"]["detail"]) return outStr # End if return response #End print_error def print_table(self, headers, rows): print "\n|", "|".join(headers), "|" print "|", " ------ |" * len(headers) for r in rows: print "| ", " |".join(r), " |" print "\n" def print_record(self, myObj, outStr="", prefix="", header=True): if header: outStr = "%s| Key | Value |\n" % (outStr) outStr = "%s| --- | --- |\n" % (outStr) if type(myObj) is dict: for key in myObj.iterkeys(): value = myObj[key] if type(value) is dict or type(value) is list: p = "%s%s." % (prefix, key) outStr = "%s| %s%s |\n%s" % (outStr, prefix, key, self.print_record( value, "", p, False)) else: p = "%s%s" % (prefix, key) outStr = "%s| %s%s |%s |\n" % (outStr, prefix, key, value) elif type(myObj) is list: for value in myObj: outStr = "%s| | %s\n" % (outStr, value) else: outStr = "%s%s" % (outStr, myObj) # End if return outStr def throw_error(self, response): print "Error from ServiceNow, HTTP Return: %s\n" % ( response.getStatus()) if self.useOAuth: self.revoke_token() sys.exit(1) def EmptyToNone(self, value): if value is None: return None elif value.strip() == '': return None else: return value def issue_token(self): print "Issuing a new token" tokenData = self.create_token(self.httpConnection) self.set_token_header(tokenData) def create_token(self, httpConnection): servicenow_oauth_url = "/oauth_token.do" content = {} content['grant_type'] = 'password' content['client_id'] = httpConnection['clientId'] content['client_secret'] = httpConnection['clientSecret'] content['username'] = httpConnection['oauthUsername'] content['password'] = httpConnection['oauthPassword'] httpRequest = HttpRequest(httpConnection, None, None) response = httpRequest.post( servicenow_oauth_url, body=urllib.urlencode(content), contentType='application/x-www-form-urlencoded') if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data print 'Could not get access token' self.throw_error(response) def refresh_token(self, httpConnection, refreshToken): servicenowUrl = "/oauth_token.do" content = {} content['grant_type'] = 'refresh_token' content['client_id'] = httpConnection['clientId'] content['client_secret'] = httpConnection['clientSecret'] content['refresh_token'] = refreshToken httpRequest = HttpRequest(httpConnection, None, None) response = httpRequest.post( servicenowUrl, body=urllib.urlencode(content), contentType='application/x-www-form-urlencoded') if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data print "Unable to refresh token using %s" % refreshToken self.throw_error(response) def set_token_header(self, tokenData): self.accessToken = tokenData['access_token'] self.refreshToken = tokenData['refresh_token'] self.headers['Authorization'] = "Bearer %s" % (self.accessToken) def revoke_token(self): print "Revoking token" httpRequest = HttpRequest(self.httpConnection, None, None) servicenowApiUrl = "/oauth_revoke_token.do?token=%s" % self.accessToken response = httpRequest.get(servicenowApiUrl) servicenowApiUrl = "/oauth_revoke_token.do?token=%s" % self.refreshToken response = httpRequest.get(servicenowApiUrl)
class OctopusClient(object): def __init__(self, httpConnection, apiKey): self.httpConnection = httpConnection self.httpRequest = HttpRequest(httpConnection) self.apiKey = apiKey self.headers = self._get_headers() @staticmethod def create_client(httpConnection, apiKey): return OctopusClient(httpConnection, apiKey) def _get_headers(self): return {"Accept": "application/json", "Content-Type": "application/json", "X-Octopus-ApiKey": self.apiKey} def ping(self): url = '/api/serverstatus' response = self.httpRequest.get(url, headers=self.headers) if response.getStatus() in HTTP_SUCCESS: data = json.loads(response.getResponse()) print(json.dumps(data)) else: self.throw_error(response) def start_deploy(self, releaseId, environment): environmentId = self.getEnvironmentId(environment) url = '/api/deployments' data = { "ReleaseId":releaseId, "EnvironmentId":environmentId, "TenantId":None, "SkipActions":[], "QueueTime":None, "QueueTimeExpiry":None, "FormValues":{}, "ForcePackageDownload":False, "UseGuidedFailure":False, "SpecificMachineIds":[], "ExcludedMachineIds":[], "ForcePackageRedeployment":False } print("data = %s" % data) response = self.httpRequest.post(url, headers=self.headers, body=json.dumps(data)) if response.getStatus() in HTTP_SUCCESS: data = json.loads(response.getResponse()) print(json.dumps(data)) return data["Id"] self.throw_error(response) def createRelease(self, version, project, selectedPackages): projectId = self.getProjectId(project) url = '/api/releases' packages = json.loads(selectedPackages) data = { "Version": version, "ProjectId": projectId, "SelectedPackages": packages } response = self.httpRequest.post(url, headers=self.headers, body=json.dumps(data)) print("HTTP_STATUS = %s" % response.getStatus()) if response.getStatus() in HTTP_SUCCESS: data = json.loads(response.getResponse()) return data["Id"] self.throw_error(response) def getEnvironmentId(self, environment): url = '/api/environments/all' return self.getId( url, environment ) def getProjectId(self, project): url = '/api/projects/all' return self.getId( url, project ) def getId(self, url, objName): response = self.httpRequest.get(url, headers=self.headers) if response.getStatus() not in HTTP_SUCCESS: self.throw_error("Response Error %s" % response.getStatus()) data = json.loads(response.getResponse()) for obj in data: if obj["Name"] == objName: print "Found NAME = %s/%s ID = %s" % (obj["Name"], objName, obj["Id"]) return obj["Id"] sys.exit("Not Found") def wait_for_deploy(self, deploymentId): url = '/api/deployments/%s' % deploymentId response = self.httpRequest.get(url, headers=self.headers) if response.getStatus() not in HTTP_SUCCESS: self.throw_error(response) deployment_details = json.loads(response.getResponse()) taskUrl = deployment_details["Links"]["Task"] time.sleep(5) task_details = self.get_task_details(taskUrl) while not task_details["IsCompleted"]: task_details = self.get_task_details(taskUrl) time.sleep(5) if task_details["FinishedSuccessfully"]: print("Deployment finished successfully.") else: msg = "Deployment failed, errors: [%s]" % task_details["ErrorMessage"] print(msg) sys.exit(msg) def get_task_details(self, taskUrl): response = self.httpRequest.get(taskUrl, headers=self.headers) if response.getStatus() not in HTTP_SUCCESS: self.throw_error(response) else: return json.loads(response.getResponse()) def throw_error(self, response): msg = "Error from server, HTTP Return: %s, content %s\n" % (response.getStatus(), response.getResponse()) print msg sys.exit(msg)
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # import json from xlrelease.HttpRequest import HttpRequest if not sonarServer: raise Exception("Sonar server ID must be provided") sonar_url = sonarServer['url'] sonar_server_api_url = '/api/measures/component?componentKey=%s&metricKeys=%s' % ( resource, ','.join(metrics.keys())) http_request = HttpRequest(sonarServer, username, password) sonar_response = http_request.get(sonar_server_api_url) if sonar_response.isSuccessful(): json_data = json.loads(sonar_response.getResponse()) data1 = {} data1['id'] = json_data['component']['id'] data1['key'] = json_data['component']['key'] data1['name'] = json_data['component']['name'] data1['sonarUrl'] = sonar_url for item in json_data['component']['measures']: data1[item['metric']] = item['value'] data = data1 else: error = json.loads(sonar_response.getResponse()) if 'Invalid table' in error['error']['message']: print "Invalid Table Name" data = {"Invalid table name"}
logger.error("===============================================================") qb = QuickBuild.create_client(qbServer) logger.warn(">> configurationId = %s " % configurationId) logger.warn(">> respectBuildCondition = %s " % respectBuildCondition) #qb = QuickBuild.create_client( params ) logger.error("===============================================================") http_request = HttpRequest(qbServer) api_url = '/rest/latest_builds/%s' % configurationId #try: response = http_request.get(api_url) logger.error(response.getResponse()) data = response.getResponse() logger.error("Is Successful? %s" % response.isSuccessful()) if response.isSuccessful(): p = re.compile("<status>(.*)</status>") buildStatus = p.search(data).group(1) task.setStatusLine("[Build Status %s]" % buildStatus) p = re.compile('<id>(.*)</id>') buildId = p.search(data).group(1) logger.error("[Build ID %s]" % buildId) p = re.compile('<version>(.*)</version>') buildVersion = p.search(data).group(1) logger.error("[Build Status %s]" % buildStatus) if buildStatus != 'RUNNING': finishPolling(buildStatus)
class XLDeployClient(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 XLDeployClient(http_connection, username, password) def get_parameter_names(self, parameter_type_id): metadata_url = "/deployit/metadata/type/%s" % (parameter_type_id) metadata_response = self.http_request.get(metadata_url, contentType='application/xml') root = ET.fromstring(metadata_response.getResponse()) params = root.find("property-descriptors") parameter_names = [] if params: for child in params: parameter_names.append(child.get("name")) return parameter_names def prepare_control_task(self, control_task_name, target_ci_id, parameters=None): prepare_control_task_url = "/deployit/control/prepare/%s/%s" % (control_task_name, target_ci_id) prepare_response = self.http_request.get(prepare_control_task_url, contentType='application/xml') check_response(prepare_response, "Failed to prepare control task [%s]. Server return [%s], with content [%s]" % ( target_ci_id, prepare_response.status, prepare_response.response)) control_obj = prepare_response.getResponse() root = ET.fromstring(control_obj) if parameters: parameter_type_id = get_parameter_type_name(root) if parameter_type_id: parameter_names = self.get_parameter_names(parameter_type_id) for parameterName in parameter_names: add_parameter(root, parameter_type_id, parameterName, parameters) invoke_response = self.http_request.post('/deployit/control', ET.tostring(root), contentType='application/xml') check_response(invoke_response, "Failed to create control task [%s]. Server return [%s], with content [%s]" % ( target_ci_id, invoke_response.status, invoke_response.response)) task_id = invoke_response.getResponse() 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, fail_on_pause=True, display_step_logs = False): start_task_url = "/deployit/task/%s/start" % task_id self.http_request.post(start_task_url, '', contentType='application/xml') trial = 0 while not number_of_trials or trial < number_of_trials: trial += 1 get_task_status_url = "/deployit/task/%s" % task_id task_state_response = self.http_request.get(get_task_status_url, contentType='application/xml') check_response(task_state_response, "Failure to get task status") task_state_xml = task_state_response.getResponse() status = extract_state(task_state_xml) print 'Task [%s] now in state [%s] \n' % (task_id, status) if fail_on_pause: if status in ( 'FAILED', 'ABORTED', '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', 'ABORTED', 'STOPPED', 'CANCELLED', 'DONE', 'EXECUTED'): break else: if status in ('FAILED', 'ABORTED') 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', 'ABORTED', 'CANCELLED', 'DONE', 'EXECUTED'): break time.sleep(polling_interval) if display_step_logs: print "Display the step logs" self.display_step_logs(task_id) return status def get_deployment_package(self, deployed_application_id): ci = self.get_ci(deployed_application_id, 'json') data = json.loads(ci) return data['version'] def deployment_exists(self, deployment_package, environment): deployment_exists_url = "/deployit/deployment/exists?application=%s&environment=%s" % ( deployment_package.rsplit('/', 1)[0], environment) deployment_exists_response = self.http_request.get(deployment_exists_url, contentType='application/xml') response = deployment_exists_response.getResponse() return 'true' in response def deployment_exists2(self, deployed_application): deployment_exists_url = "/deployit/repository/exists/{0}".format(deployed_application) deployment_exists_response = self.http_request.get(deployment_exists_url, contentType='application/xml') response = deployment_exists_response.getResponse() return 'true' in response def deployment_prepare_undeploy(self, deployed_application_id, orchestrators=None, deployed_application_properties=None): deployment_prepare_undeploy_url = "/deployit/deployment/prepare/undeploy?deployedApplication=%s" % deployed_application_id deployment_prepare_undeploy_url_response = self.http_request.get(deployment_prepare_undeploy_url, contentType='application/xml') check_response(deployment_prepare_undeploy_url_response, "Failed to prepare undeploy. Server return [%s], with content [%s]" % ( deployment_prepare_undeploy_url_response.status, deployment_prepare_undeploy_url_response.response)) undeployment_xml = deployment_prepare_undeploy_url_response.getResponse() undeployment_xml = add_orchestrators(undeployment_xml, orchestrators) undeployment_xml = set_deployed_application_properties(undeployment_xml, deployed_application_properties) return undeployment_xml def deployment_prepare_update(self, deployment_package, environment): deployment_prepare_update_url = "/deployit/deployment/prepare/update?version=%s&deployedApplication=%s" % ( deployment_package, "%s/%s" % (environment, deployment_package.rsplit('/', 2)[1])) deployment_prepare_update_response = self.http_request.get(deployment_prepare_update_url, contentType='application/xml') check_response(deployment_prepare_update_response, "Failed to prepare update deploy. Server return [%s], with content [%s]" % ( deployment_prepare_update_response.status, deployment_prepare_update_response.response)) return deployment_prepare_update_response.getResponse() def deployment_prepare_initial(self, deployment_package, environment): deployment_prepare_initial_url = "/deployit/deployment/prepare/initial?version=%s&environment=%s" % ( deployment_package, environment) deployment_prepare_initial_response = self.http_request.get(deployment_prepare_initial_url, contentType='application/xml') check_response(deployment_prepare_initial_response, "Failed to prepare initial deploy. Server return [%s], with content [%s]" % ( deployment_prepare_initial_response.status, deployment_prepare_initial_response.response)) return deployment_prepare_initial_response.getResponse() def deployment_prepare_deployeds(self, deployment, orchestrators=None, deployed_application_properties=None, overrideDeployedProps=None, deployed_properties=None): deployment_prepare_deployeds = "/deployit/deployment/prepare/deployeds" deployment_prepare_deployeds_response = self.http_request.post(deployment_prepare_deployeds, deployment, contentType='application/xml') check_response(deployment_prepare_deployeds_response, "Failed to prepare deployeds. Server return [%s], with content [%s]" % ( deployment_prepare_deployeds_response.status, deployment_prepare_deployeds_response.response)) deployment_xml = deployment_prepare_deployeds_response.getResponse() deployment_xml = add_orchestrators(deployment_xml, orchestrators) deployment_xml = set_deployed_application_properties(deployment_xml, deployed_application_properties) deployment_xml = override_deployed_properties(deployment_xml, overrideDeployedProps) deployment_xml = set_deployed_properties(deployment_xml, deployed_properties) # Deprecated. Should be remove starting 3.0.0 return deployment_xml def validate(self, deployment): get_deployment_task_id = "/deployit/deployment/validate" deployment_with_validation_response = self.http_request.post(get_deployment_task_id, deployment, contentType='application/xml') deployment = deployment_with_validation_response.getResponse() root = ET.fromstring(deployment) return map(lambda vm: "CI: %s Message: %s" % (vm.attrib['ci'], vm.text), root.iter('validation-message')) def get_deployment_task_id(self, deployment): get_deployment_task_id = "/deployit/deployment" deployment_task_id_response = self.http_request.post(get_deployment_task_id, deployment, contentType='application/xml') return deployment_task_id_response.getResponse() def deployment_rollback(self, taskId): deployment_rollback = "/deployit/deployment/rollback/%s" % taskId deployment_rollback_response = self.http_request.post(deployment_rollback, '', contentType='application/xml') return deployment_rollback_response.getResponse() def archive_task(self, task_id): archive_task = "/deployit/task/%s/archive" % task_id self.http_request.post(archive_task, '', contentType='application/xml') def cancel_task(self, task_id): cancel_task = "/deployit/task/%s" % task_id self.http_request.delete(cancel_task, contentType='application/xml') def stop_task(self, task_id): stop_task = "/deployit/task/%s/stop" % task_id self.http_request.post(stop_task, '', contentType='application/xml') def get_download_uuid(self, deployment_package): export_task = "/deployit/export/deploymentpackage/%s" % deployment_package export_task_response = self.http_request.get(export_task, contentType='application/xml') return export_task_response.getResponse() def fetch_package2(self, url, user_name, password): fetch_task = "/deployit/package/fetch2" params = { "url": url, "user": user_name, "password": password } response = self.http_request.post(fetch_task, json.dumps(params), contentType='application/json') check_response(response, "Failed to import package. Server return [%s], with content [%s]" % ( response.status, response.response)) def get_latest_package_version(self, application_id): query_task = "/deployit/repository/query?parent=%s&resultsPerPage=-1" % application_id query_task_response = self.http_request.get(query_task, contentType='application/xml') root = ET.fromstring(query_task_response.getResponse()) items = root.findall('ci') latest_package = '' if len(items) > 0: latest_package = items[-1].attrib['ref'] return latest_package def get_all_package_version(self, application_id): query_task = "/deployit/repository/query?parent=%s&resultsPerPage=-1" % application_id query_task_response = self.http_request.get(query_task, contentType='application/xml') root = ET.fromstring(query_task_response.getResponse()) items = root.findall('ci') all_package = list() for item in items: all_package.append(item.attrib['ref']) return all_package def get_latest_deployed_version(self, environment_id, application_name): query_task_response = self.get_ci("%s/%s" % (environment_id, application_name), 'xml') root = ET.fromstring(query_task_response) items = root.findall('version') latest_package = '' for item in items: latest_package = item.attrib['ref'] return latest_package def check_ci_exist(self, ci_id, throw_on_fail=False): query_task = "/deployit/repository/exists/%s" % ci_id headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} query_task_response = self.http_request.get(query_task, headers=headers) check_response(query_task_response, "Failed to check ci [%s]. Server return [%s], with content [%s]" % ( ci_id, query_task_response.status, query_task_response.response)) if query_task_response.getResponse().find('true') > 0: return True if throw_on_fail: raise Exception("CI with id [%s] does not exist or you do not have the correct permissions to read it." % ci_id) return False def create_folder_tree(self, folder_id, folder_type): folders = folder_id.split("/") folder_create = '%s' % folder_type for folder in folders: folder_create += "/" + folder if self.check_ci_exist(folder_create): print "Folder [%s] already exists" % folder_create print "\n" else: self.create_directory(folder_create) print "\n" def create_directory(self, ci_id): self.create_ci(ci_id, 'core.Directory') def create_application(self, app_id): self.create_ci(app_id, 'udm.Application') def create_ci(self, id, ci_type, xml_descriptor=''): xml = '<' + ci_type + ' id="' + id + '">' + xml_descriptor.strip() + '</' + ci_type + '>' create_task = '/deployit/repository/ci/%s' % id response = self.http_request.post(create_task, xml, contentType='application/xml') check_response(response, "Failed to create ci [%s]. Server return [%s], with content [%s]" % ( id, response.status, response.response)) print "Created ci [%s] and received response [%s]" % (id, response.response) def update_ci_property(self, ci_id, ci_property, property_value): self.check_ci_exist(ci_id, throw_on_fail=True) ci = self.get_ci(ci_id, 'json') data = json.loads(ci) if ci_property in data and isinstance(data[ci_property], list): data[ci_property] = eval(property_value) else: data[ci_property] = property_value self.update_ci(ci_id, json.dumps(data), 'json') def add_ci_to_environment(self, env_id, ci_id, ci_type): self.check_ci_exist(env_id, throw_on_fail=True) ci = self.get_ci(env_id, 'json') data = json.loads(ci) if str(ci_type) == 'udm.Dictionary': data["dictionaries"].append(ci_id) else: data["members"].append(ci_id) self.update_ci(env_id, json.dumps(data), 'json') def remove_ci_from_environment(self, env_id, ci_id): get_env_response = self.get_ci(env_id, 'xml') print get_env_response env_root = ET.fromstring(get_env_response) member_to_remove = None for child in env_root: if child.tag in ('members','dictionaries'): for member in child: if member.attrib['ref'] == ci_id: print 'Found ' + ci_id + ' in ' + env_id env_members = child member_to_remove = member if member_to_remove is not None: print 'Removing ' + ci_id + ' from ' + env_id env_members.remove(member_to_remove) self.update_ci(env_id, ET.tostring(env_root), 'xml') def get_ci(self, ci_id, accept): get_ci = "/deployit/repository/ci/%s" % ci_id headers = {'Accept': 'application/%s' % accept, 'Content-Type': 'application/%s' % accept} response = self.http_request.get(get_ci, headers=headers) check_response(response, "Failed to get ci [%s]. Server return [%s], with content [%s]" % ( ci_id, response.status, response.response)) return response.getResponse() def update_ci(self, ci_id, data, content_type): update_ci = "/deployit/repository/ci/%s" % ci_id content_type_header = "application/%s" % content_type response = self.http_request.put(update_ci, data, contentType=content_type_header) check_response(response, "Failed to update ci [%s]. Server return [%s], with content [%s]" % ( ci_id, response.status, response.response)) def delete_ci(self, ci_id): delete_task = '/deployit/repository/ci/' + ci_id headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} response = self.http_request.delete(delete_task, headers=headers) check_response(response, "Failed to delete ci with id [%s]. Server return [%s], with content [%s]" % ( ci_id, response.status, response.response)) def get_ci_tree(self, ci_id): infrastructure_list = [ci_id] query = '/deployit/repository/query?parent=%s' % ci_id response = self.http_request.get(query, contentType='application/xml') check_response(response, "Unable to retrieve CI Tree from parent: %s" % ci_id) root = ET.fromstring(response.getResponse()) for ci in root.findall('ci'): infrastructure_list.extend(self.get_ci_tree(ci.get('ref'))) return infrastructure_list def display_step_logs(self, task_id): get_task_steps = '/deployit/task/' + task_id + '/step' get_task_steps_response = self.http_request.get(get_task_steps, contentType='application/xml') task_steps_root = ET.fromstring(get_task_steps_response.getResponse()) for child in task_steps_root: if child.tag == 'steps': step_counter = 0 for grandchild in child: if grandchild.tag == 'step': step_counter = step_counter + 1 print 'DEPLOYMENT STEP %d: Failures=%s State=%s\n' % ( step_counter, str(grandchild.attrib['failures']), str(grandchild.attrib['state'])) for item in grandchild: if item.tag in ('description', 'startDate', 'completionDate'): print '%s %s\n' % (item.tag, item.text) else: print "%s\n" % item.tag print "%s\n" % item.text def query_archived_tasks(self, end_date=None): get_tasks = '/deployit/tasks/v2/query' if end_date: get_tasks += '?begindate=2008-01-01&enddate=%s' % end_date headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} response = self.http_request.get(get_tasks, headers=headers) check_response(response, "Failed to get archived tasks. Server return [%s], with content [%s]" % ( response.status, response.response)) return response.getResponse() def get_deployed_applications_for_environment(self, environment, date=None): archived_tasks = self.query_archived_tasks(date) deployed_apps = {} if archived_tasks: tasks = json.loads(archived_tasks) for task in tasks: if task['state'] == 'DONE' and task['metadata']['taskType'] not in ( 'CONTROL', 'INSPECTION', 'DEFAULT') and task['metadata']['environment_id'] == environment: if task['metadata']['taskType'] in ('INITIAL', 'UPGRADE', 'ROLLBACK'): deployed_apps[task['metadata']['application']] = get_row_data(task) if task['metadata']['taskType'] in ('UNDEPLOY') and task['metadata'][ 'application'] in deployed_apps: del deployed_apps[task['metadata']['application']] return deployed_apps
class ServiceNowClient(object): def __init__(self, httpConnection, username=None, password=None): self.httpConnection = httpConnection 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_scorecards(self): servicenow_api_url = '/api/now/v1/pa/scorecards' 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_with_fields(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 get_change_request(self, table_name, sysId): servicenow_api_url = '/api/now/v1/table/%s/%s' % (table_name, sysId) 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 create_record(self, table_name, content): servicenow_api_url = '/api/now/v1/table/%s' % (table_name) response = self.httpRequest.post(servicenow_api_url, body=content, contentType='application/json') if response.getStatus() == RECORD_CREATED_STATUS: data = json.loads(response.getResponse()) return data['result'] else: self.throw_error(response) # End if # End create_record def update_record(self, table_name, sysId, content): servicenow_api_url = '/api/now/v1/table/%s/%s' % (table_name, sysId) response = self.httpRequest.put(servicenow_api_url, body=content, contentType='application/json') if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] else: self.throw_error(response) # End if # End create_record def find_record(self, table_name, query): servicenow_api_url = '/api/now/v1/table/%s?%s' % (table_name, query) print "Servic Now URL = %s " % (servicenow_api_url) response = self.httpRequest.get(servicenow_api_url, contentType='application/json') if response.getStatus() == SN_RESULT_STATUS: data = json.loads(response.getResponse()) return data['result'] else: print "find_record error %s" % (response) self.throw_error(response) # End if # End find_record def print_error(self, response): if type(response) is dict: outStr = "| Status | %s |\n" % ( response["status"] ) outStr = "%s| Message | %s |\n" % ( outStr, response["error"]["message"] ) outStr = "%s| Detail | %s |\n" % ( outStr, response["error"]["detail"] ) return outStr # End if return response #End print_error def print_table(self, headers, rows): print "\n|", "|".join(headers), "|" print "|", " ------ |" * len(headers) for r in rows: print "| ", " |".join(r), " |" print "\n" def print_record(self, myObj, outStr="", prefix="", header=True): if header: outStr = "%s| Key | Value |\n" % (outStr) outStr = "%s| --- | --- |\n" % (outStr) if type(myObj) is dict: for key in myObj.iterkeys(): value = myObj[key] if type(value) is dict or type(value) is list: p = "%s%s." % (prefix, key) outStr = "%s| %s%s |\n%s" % (outStr, prefix, key, self.print_record(value, "", p, False)) else: p = "%s%s" % (prefix, key) outStr = "%s| %s%s |%s |\n" % (outStr, prefix, key, value) elif type(myObj) is list: for value in myObj: outStr = "%s| | %s\n" % (outStr, value) else: outStr = "%s%s" % (outStr, myObj) # End if return outStr def throw_error(self, response): print "Error from ServiceNow, HTTP Return: %s\n" % (response.getStatus()) sys.exit(1)
class RemedyClient(object): def __init__(self, httpConnection, username=None, password=None): self.headers = {} self.accessToken = None self.httpConnection = httpConnection self.username = username if username else httpConnection['username'] self.password = password if password else httpConnection['password'] # clear username/password so underlying library doesn't try to do basic authentication del httpConnection['username'] del httpConnection['password'] self.httpRequest = HttpRequest(self.httpConnection) self.issue_token() @staticmethod def create_client(httpConnection, username=None, password=None): return RemedyClient(httpConnection, username, password) # see https://docs.bmc.com/docs/display/public/ars9000/Login+information def issue_token(self): api_url = '/api/jwt/login' form_data = urllib.urlencode({ 'username': self.username, 'password': self.password }) response = self.httpRequest.post( api_url, body=form_data, contentType='application/x-www-form-urlencoded', headers={'Accept': 'text/plain'}) if response.getStatus() != RESULT_STATUS: self.throw_error(response) token = response.getResponse() self.headers['Authorization'] = 'AR-JWT ' + token # task functions ----------------------------------------------------------- def verify_connection(self): ''' Remedy AR Common Forms HPD:IncidentInterface_Create - to create or submit new incident HPD:IncidentInterface - to perform SEARCH,READ,UPDATE/MODIFY on existing incident CHG:ChangeInterface - to create change request CHG:ChangeInterface_Create - update and modify change request CHG:CRQ:Worklog - for work Info/log HPD:INC:Worklog - for Incident work log ''' self.query_entrys('User', '') # https://docs.bmc.com/docs/pages/releaseview.action?pageId=517036472#id-/entry/{formName}-Createanentry def create_entry(self, form_name, form_data): remedy_api_url = '%s/%s' % (URI_PREFIX, form_name) entry_str = '''{ "values": %s }''' % form_data response = self.httpRequest.post( remedy_api_url, body=entry_str.encode('utf-8'), contentType='application/json; charset=utf-8', headers=self.headers) if response.getStatus() in [ RECORD_CREATED_STATUS, RECORD_UPDATED_STATUS ]: # both can be returned according to the api docs location = response.getHeaders()["Location"] print "Entry created, url [%s]" % location return location.split('/')[-1] else: print "create_entry error %s" % (response) self.throw_error(response) # https://docs.bmc.com/docs/pages/releaseview.action?pageId=517036478#id-/entry/{formName}/{entryId}-Updateanentry def update_entry(self, form_name, entry_id, form_data): remedy_api_url = '%s/%s/%s' % (URI_PREFIX, form_name, entry_id) entry_str = '''{ "values": %s }''' % form_data response = self.httpRequest.put( remedy_api_url, body=entry_str.encode('utf-8'), contentType='application/json; charset=utf-8', headers=self.headers) if response.getStatus() == RECORD_UPDATED_STATUS: return self.get_entry(form_name, entry_id) else: print "update_entry error %s" % (response) self.throw_error(response) # https://docs.bmc.com/docs/pages/releaseview.action?pageId=517036478#id-/entry/{formName}/{entryId}-Getsingleentry def get_entry(self, form_name, entry_id): # example: /api/arsys/v1/entry/SimpleForm/000000000000103 remedy_api_url = '%s/%s/%s' % (URI_PREFIX, form_name, entry_id) response = self.httpRequest.get( remedy_api_url, contentType='application/json; charset=utf-8', headers=self.headers) if response.getStatus() == RESULT_STATUS: data = json.loads(response.getResponse()) return data['values'] else: print "get_entry error %s" % (response) self.throw_error(response) # https://docs.bmc.com/docs/pages/releaseview.action?pageId=517036478#id-/entry/{formName}/{entryId}-Getsingleentry def get_change_request(self, form_name, change_id): # example: /api/arsys/v1/entry/CHG:ChangeInterface?q=%27Infrastructure%20Change%20ID%27%3d%22CRQ000000152848%22 remedy_api_url = '%s/%s?q=%27Infrastructure%20Change%20ID%27%3d%22%s%22' % ( URI_PREFIX, form_name, change_id) print 'Remedy CR API is: %s' % remedy_api_url response = self.httpRequest.get( remedy_api_url, contentType='application/json; charset=utf-8', headers=self.headers) if response.getStatus() == RESULT_STATUS: data = json.loads(response.getResponse()) return data['values'] else: print "get_entry error %s" % (response) self.throw_error(response) # https://docs.bmc.com/docs/pages/releaseview.action?pageId=517036472#id-/entry/{formName}-GETmultipleentries def query_entrys(self, form_name, query): remedy_api_url = '%s/%s?q=%s' % (URI_PREFIX, form_name, urllib.quote_plus(query)) response = self.httpRequest.get( remedy_api_url, contentType='application/json; charset=utf-8', headers=self.headers) if response.getStatus() == RESULT_STATUS: data = json.loads(response.getResponse())['entries'] return map(operator.itemgetter('values'), data) else: print "query_entrys error %s" % (response) self.throw_error(response) # Utility functions ======================================================== def throw_error(self, response): print "Error from Remedy, HTTP Return: %s\n" % (response.getStatus()) print "Detailed error: %s\n" % response.getResponse() sys.exit([response.getStatus(), response.getResponse()])
class AnsibleTowerClient(object): def __init__(self, httpConnection, username=None, password=None): self.headers = {"Accept": "application/json"} self.accessToken = None self.refreshToken = None self.httpConnection = httpConnection if username: self.httpConnection['username'] = username if password: self.httpConnection['password'] = password self.httpRequest = HttpRequest(self.httpConnection, username, password) @staticmethod def create_client(httpConnection, username=None, password=None): return AnsibleTowerClient(httpConnection, username, password) def launch(self, jobTemplate, content, ansiblePluginRetryCounter, ansiblePluginAuthErrorRetryInterval): tower_api_url = '/api/v2/job_templates/%s/launch/' % jobTemplate retryCounter = 0 success = False while (retryCounter < ansiblePluginRetryCounter and not success): response = self.httpRequest.post(tower_api_url, body=content, contentType='application/json', headers=self.headers) if response.getStatus() == RECORD_CREATED_STATUS: success = True return response.getResponse() break elif response.getStatus() == AUTH_ERROR_STATUS: print "Auth Error for Tower in the launch call. will retry" print "Detailed error: %s\n" % response.response retryCounter += 1 time.sleep(ansiblePluginAuthErrorRetryInterval) else: self.throw_error(response) # End if # End launch def status(self, jobId, ansiblePluginRetryCounter, ansiblePluginAuthErrorRetryInterval): tower_api_url = '/api/v2/jobs/%s/' % jobId retryCounter = 0 success = False print "Tower API URL for status call is = %s%s " % ( self.httpConnection['url'], tower_api_url) print "" while (retryCounter < ansiblePluginRetryCounter and not success): response = self.httpRequest.get(tower_api_url, contentType='application/json', headers=self.headers) if response.getStatus() == RECORD_FOUND_STATUS: success = True return response break elif response.getStatus() == AUTH_ERROR_STATUS: print "Auth Error for Tower in the status call. will retry" print "Detailed error: %s\n" % response.response retryCounter += 1 time.sleep(ansiblePluginAuthErrorRetryInterval) else: print "find_record error %s" % (response) self.throw_error(response) # End if # End status def stdout(self, jobId, ansiblePluginRetryCounter, ansiblePluginAuthErrorRetryInterval): tower_api_url = '/api/v2/jobs/%s/stdout?format=json' % jobId retryCounter = 0 success = False print "Tower API URL for stdout call is = %s%s " % ( self.httpConnection['url'], tower_api_url) while (retryCounter < ansiblePluginRetryCounter and not success): response = self.httpRequest.get(tower_api_url, contentType='application/json', headers=self.headers) if response.getStatus() == RECORD_FOUND_STATUS: success = True return response break elif response.getStatus() == AUTH_ERROR_STATUS: print "Auth Error for Tower in the stdout call. will retry" print "Detailed error: %s\n" % response.response retryCounter += 1 time.sleep(ansiblePluginAuthErrorRetryInterval) else: print "find_record error %s" % (response) self.throw_error(response) # End if # End status def throw_error(self, response): print "Error from Tower, HTTP Return: %s\n" % (response.getStatus()) print "Detailed error: %s\n" % response.response sys.exit(1) # End throw_error def print_error(self, response): if type(response) is dict: outStr = "| Status | %s |\n" % (response["status"]) outStr = "%s| Message | %s |\n" % (outStr, response["error"]["message"]) outStr = "%s| Detail | %s |\n" % (outStr, response["error"]["detail"]) return outStr # End if return response