|
@@ -1,6 +1,5 @@
|
|
|
import base64
|
|
|
import os
|
|
|
-import time
|
|
|
import requests
|
|
|
from requests_toolbelt.multipart import decoder
|
|
|
import jinja2
|
|
@@ -8,6 +7,7 @@ import json
|
|
|
import re
|
|
|
from bs4 import BeautifulSoup
|
|
|
from xml_prettify import prettify_xml
|
|
|
+import logging
|
|
|
|
|
|
|
|
|
class c11_api:
|
|
@@ -19,7 +19,9 @@ class c11_api:
|
|
|
headers = {}
|
|
|
caf = ""
|
|
|
cam = ""
|
|
|
- reports = None
|
|
|
+ reports = []
|
|
|
+ folders = []
|
|
|
+ jobs = []
|
|
|
|
|
|
def __init__(self, webservice="http://localhost:9300/bi/"):
|
|
|
self.webservice = webservice
|
|
@@ -63,30 +65,73 @@ class c11_api:
|
|
|
self.cam = self.generate_token(r.cookies["usersessionid"])
|
|
|
return r.status_code
|
|
|
|
|
|
- def report_list(self):
|
|
|
- # "v1/objects/_dot_public_folders/items"
|
|
|
- fields = "defaultName|id|ancestors"
|
|
|
- filter = "type|analysis|interactiveReport|powerPlayReport|powerPlay8Report|powerPlay8ReportView|query|report|reportTemplate"
|
|
|
+ def get_folders(self):
|
|
|
+ if len(self.folders) == 0:
|
|
|
+ self.load_folder_list()
|
|
|
+ return self.folders
|
|
|
+
|
|
|
+ def load_folder_list(self, folder_id='_dot_public_folders', prefix='Team Content'):
|
|
|
+ res = self.session.get(f"{self.webservice}v1/objects/{folder_id}/items", headers=self.headers)
|
|
|
+ folder_list = res.json()['data']
|
|
|
+ for f in folder_list:
|
|
|
+ if f['type'] == 'folder':
|
|
|
+ folder = {
|
|
|
+ 'id': f['id'],
|
|
|
+ 'name': prefix + '/' + f['defaultName'].replace('/', '_')
|
|
|
+ }
|
|
|
+ self.folders.append(folder)
|
|
|
+ self.load_folder_list(folder['id'], folder['name'])
|
|
|
+ elif f['type'] == 'report':
|
|
|
+ report = {
|
|
|
+ 'id': f['id'],
|
|
|
+ 'name': f['defaultName'],
|
|
|
+ 'path': prefix
|
|
|
+ }
|
|
|
+ self.reports.append(report)
|
|
|
+ elif f['type'] == 'jobDefinition':
|
|
|
+ job = {
|
|
|
+ 'id': f['id'],
|
|
|
+ 'name': f['defaultName'],
|
|
|
+ 'path': prefix
|
|
|
+ }
|
|
|
+ job['details'] = self.get_job_details(job['id'])
|
|
|
+ self.jobs.append(job)
|
|
|
+
|
|
|
+ def get_job_details(self, job_id):
|
|
|
+ fields = ",".join([
|
|
|
+ 'userInterfaces,disabled',
|
|
|
+ 'runInAdvancedViewer,modificationTime,canBurst',
|
|
|
+ 'defaultPortalAction',
|
|
|
+ 'base.defaultName,tags,target.searchPath,target.disabled',
|
|
|
+ 'options,base.options'
|
|
|
+ ])
|
|
|
+ res = self.session.get(f"{self.webservice}v1/objects/{job_id}?fields={fields}", headers=self.headers)
|
|
|
+ job = res.json()['data'][0]
|
|
|
+ job.pop('_meta', None)
|
|
|
+ job.pop('id', None)
|
|
|
+ job.pop('type', None)
|
|
|
+ job.pop('defaultName', None)
|
|
|
+
|
|
|
+ fields2 = ",".join([
|
|
|
+ r'id,displaySequence,stepObject{defaultName}',
|
|
|
+ r'stepObject{id},stepObject{parameters}',
|
|
|
+ r'stepObject{canBurst},options,parameters'
|
|
|
+ ])
|
|
|
res = self.session.get(
|
|
|
- f"{self.webservice}v1/search/cm?fields={fields}&results=1000&query=.&hide_internal=all&filter={filter}",
|
|
|
+ f"{self.webservice}v1/objects/{job_id}/items?types=jobStepDefinition&fields={fields2}",
|
|
|
headers=self.headers
|
|
|
)
|
|
|
- # filename = self.log_dir + '/reports_error.log'
|
|
|
- # os.makedirs(os.path.dirname(filename), exist_ok=True)
|
|
|
- # with open(filename, "wb") as f:
|
|
|
- # f.write(res.content)
|
|
|
- self.reports = res.json()['results']
|
|
|
- for r in self.reports:
|
|
|
- r['path'] = "/".join([a['defaultName'].replace('/', '_') for a in r['ancestors']])
|
|
|
- r['name'] = r['defaultName']
|
|
|
- del(r['ancestors'])
|
|
|
- del(r['defaultName'])
|
|
|
-
|
|
|
- return self.reports
|
|
|
+ steps = res.json()['data']
|
|
|
+ for s in steps:
|
|
|
+ s.pop('_meta', None)
|
|
|
+ if s['stepObject'] is not None:
|
|
|
+ s['report_id'] = s['stepObject'][0]['id']
|
|
|
+ s.pop('stepObject', None)
|
|
|
+ job['steps'] = steps
|
|
|
+ return job
|
|
|
|
|
|
def get_report(self, report_id):
|
|
|
- if self.reports is None:
|
|
|
- self.reports = self.report_list()
|
|
|
+ self.get_folders()
|
|
|
report = [r for r in self.reports if r['id'] == report_id]
|
|
|
if len(report) == 0:
|
|
|
return None
|
|
@@ -96,8 +141,7 @@ class c11_api:
|
|
|
return report
|
|
|
|
|
|
def get_reports_in_folder(self, folder, recursive=False):
|
|
|
- if self.reports is None:
|
|
|
- self.reports = self.report_list()
|
|
|
+ self.get_folders()
|
|
|
if recursive:
|
|
|
return [r for r in self.reports if r['path'].startswith(folder)]
|
|
|
return [r for r in self.reports if r['path'] == folder]
|
|
@@ -118,18 +162,14 @@ class c11_api:
|
|
|
if r.status_code == 500:
|
|
|
bs = BeautifulSoup(r.text, 'xml')
|
|
|
report['error'] = bs.find_all('messageString')[0].string
|
|
|
- # time.sleep(2)
|
|
|
+ logging.error(report['error'])
|
|
|
return report
|
|
|
|
|
|
parts = decoder.MultipartDecoder.from_response(r).parts
|
|
|
|
|
|
- # for i, p in enumerate(parts):
|
|
|
- # with open(f"export/{report['report']}_{i}.xml", "w") as f:
|
|
|
- # f.write(p.text.replace('\x81', ''))
|
|
|
-
|
|
|
meta = {'required': {}, 'optional': {}}
|
|
|
bs = BeautifulSoup(parts[1].content, 'lxml')
|
|
|
- # print(bs.prettify())
|
|
|
+
|
|
|
for sv in bs.find_all('selectvalue'):
|
|
|
k = sv['parameter']
|
|
|
req = 'required' if sv['required'] == 'true' else 'optional'
|
|
@@ -146,6 +186,12 @@ class c11_api:
|
|
|
json.dump(meta, open(filename, 'w'), indent=2)
|
|
|
report['meta'] = meta
|
|
|
report['spec'] = parts[2].text
|
|
|
+ path = report['path'].replace('Team Content/ReportOutput', '')
|
|
|
+ report['filename'] = f"{self.export_dir}/{path}/{report['name']}.pdf"
|
|
|
+
|
|
|
+ report['params'] = list(re.findall(r'\[([^\]]+)\]', report['filename']))
|
|
|
+ for i, p in enumerate(report['params']):
|
|
|
+ report['filename'] = report['filename'].replace('[' + p + ']', '{' + str(i) + '}')
|
|
|
return report
|
|
|
|
|
|
def export_unstubbed(self, report_id):
|
|
@@ -201,36 +247,35 @@ class c11_api:
|
|
|
'SOAPAction': 'http://www.ibm.com/xmlns/prod/cognos/reportService/202004/'
|
|
|
}
|
|
|
|
|
|
- def request_file(self, report_id, params, filename, format='PDF'):
|
|
|
+ def request_file(self, report_id, params, format='PDF'):
|
|
|
report = self.get_report(report_id)
|
|
|
headers = self.get_report_headers(report_id)
|
|
|
|
|
|
soap = self.template.render({"caf": self.caf, "cam": self.cam,
|
|
|
"report": report, "format": format,
|
|
|
"prompt": 'false', "tracking": "", "params": params}).encode("utf-8")
|
|
|
- try:
|
|
|
- r = self.session.post(self.webservice + 'v1/reports', data=soap, headers=headers)
|
|
|
- except UnicodeEncodeError:
|
|
|
- filename = self.log_dir + '/' + os.path.basename(filename) + '.log'
|
|
|
- os.makedirs(os.path.dirname(filename), exist_ok=True)
|
|
|
- with open(filename, "w") as f:
|
|
|
- f.write(soap)
|
|
|
- return False
|
|
|
+ r = self.session.post(self.webservice + 'v1/reports', data=soap, headers=headers)
|
|
|
|
|
|
+ bs = BeautifulSoup(r.text, 'xml')
|
|
|
if r.status_code == 200:
|
|
|
- parts = decoder.MultipartDecoder.from_response(r).parts
|
|
|
- filename = self.export_dir + filename
|
|
|
- os.makedirs(os.path.dirname(filename), exist_ok=True)
|
|
|
- with open(filename, "wb") as f:
|
|
|
- f.write(parts[1].content)
|
|
|
- else:
|
|
|
- filename = self.log_dir + '/' + os.path.basename(filename) + '.log'
|
|
|
- os.makedirs(os.path.dirname(filename), exist_ok=True)
|
|
|
- with open(filename, "wb") as f:
|
|
|
- f.write(r.content)
|
|
|
- return True
|
|
|
+ try:
|
|
|
+ parts = decoder.MultipartDecoder.from_response(r).parts
|
|
|
+ except decoder.NonMultipartContentTypeException:
|
|
|
+ return 500, 'Timeout'
|
|
|
+ return 200, parts[1].content
|
|
|
+
|
|
|
+ error = bs.find_all('messageString')[0].string
|
|
|
+ logging.debug(error)
|
|
|
+ return r.status_code, error
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
api = c11_api()
|
|
|
api.login()
|
|
|
+ folders = api.get_folders()
|
|
|
+ filename = 'C:/GlobalCube/Tasks/gctools/logs/config/folders.json'
|
|
|
+ json.dump(folders, open(filename, 'w'), indent=2)
|
|
|
+ filename = 'C:/GlobalCube/Tasks/gctools/logs/config/reports.json'
|
|
|
+ json.dump(api.reports, open(filename, 'w'), indent=2)
|
|
|
+ filename = 'C:/GlobalCube/Tasks/gctools/logs/config/jobs.json'
|
|
|
+ json.dump(api.jobs, open(filename, 'w'), indent=2)
|