pyxecm 1.5__py3-none-any.whl → 1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyxecm might be problematic. Click here for more details.
- pyxecm/__init__.py +2 -0
- pyxecm/avts.py +1065 -0
- pyxecm/coreshare.py +467 -571
- pyxecm/customizer/customizer.py +160 -19
- pyxecm/customizer/k8s.py +139 -25
- pyxecm/customizer/m365.py +694 -1498
- pyxecm/customizer/payload.py +2306 -485
- pyxecm/customizer/pht.py +547 -124
- pyxecm/customizer/salesforce.py +378 -443
- pyxecm/customizer/servicenow.py +379 -133
- pyxecm/helper/assoc.py +20 -0
- pyxecm/helper/data.py +237 -33
- pyxecm/helper/xml.py +1 -1
- pyxecm/otawp.py +1810 -0
- pyxecm/otcs.py +3180 -2938
- pyxecm/otds.py +1591 -1875
- pyxecm/otmm.py +131 -11
- {pyxecm-1.5.dist-info → pyxecm-1.6.dist-info}/METADATA +3 -1
- pyxecm-1.6.dist-info/RECORD +32 -0
- {pyxecm-1.5.dist-info → pyxecm-1.6.dist-info}/WHEEL +1 -1
- pyxecm-1.5.dist-info/RECORD +0 -30
- {pyxecm-1.5.dist-info → pyxecm-1.6.dist-info}/LICENSE +0 -0
- {pyxecm-1.5.dist-info → pyxecm-1.6.dist-info}/top_level.txt +0 -0
pyxecm/otawp.py
ADDED
|
@@ -0,0 +1,1810 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Otawp module for synchorinizing the pojects , publsh and create run time instances for that.
|
|
3
|
+
loanmanagement is such application.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
import xml.etree.ElementTree as ET
|
|
8
|
+
import uuid
|
|
9
|
+
import json
|
|
10
|
+
import re
|
|
11
|
+
import time
|
|
12
|
+
import requests
|
|
13
|
+
from .otds import OTDS
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger("pyxecm.otawp")
|
|
16
|
+
|
|
17
|
+
REQUEST_HEADERS = {
|
|
18
|
+
"Content-Type": "text/xml; charset=utf-8",
|
|
19
|
+
"accept": "application/xml"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
REQUEST_FORM_HEADERS = {
|
|
23
|
+
"accept": "application/xml;charset=utf-8",
|
|
24
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
REQUEST_HEADERS_JSON = {
|
|
28
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
29
|
+
"accept": "application/json"
|
|
30
|
+
}
|
|
31
|
+
REQUEST_TIMEOUT = 60
|
|
32
|
+
|
|
33
|
+
class OTAWP:
|
|
34
|
+
"""Used to automate settings in OpenText AppWorks Platform (OTAWP)."""
|
|
35
|
+
_config: dict
|
|
36
|
+
_config = None
|
|
37
|
+
_cookie = None
|
|
38
|
+
_otawp_ticket = None
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
protocol: str,
|
|
43
|
+
hostname: str,
|
|
44
|
+
port: int,
|
|
45
|
+
username: str | None = None,
|
|
46
|
+
password: str | None = None,
|
|
47
|
+
otawp_ticket: str | None = None,
|
|
48
|
+
):
|
|
49
|
+
otawp_config = {}
|
|
50
|
+
|
|
51
|
+
otawp_config["hostname"] = hostname if hostname else "appworks"
|
|
52
|
+
otawp_config["protocol"] = protocol if protocol else "http"
|
|
53
|
+
otawp_config["port"] = port if port else 8080
|
|
54
|
+
otawp_config["username"] = username if username else "sysadmin"
|
|
55
|
+
otawp_config["password"] = password if password else ""
|
|
56
|
+
|
|
57
|
+
if otawp_ticket:
|
|
58
|
+
self._cookie = {"defaultinst_SAMLart": otawp_ticket}
|
|
59
|
+
|
|
60
|
+
otds_base_url = "{}://{}".format(protocol, otawp_config["hostname"])
|
|
61
|
+
if str(port) not in ["80", "443"]:
|
|
62
|
+
otds_base_url += f":{port}"
|
|
63
|
+
otds_base_url += "/home/system"
|
|
64
|
+
|
|
65
|
+
otawp_config["gatewayAuthenticationUrl"] = (
|
|
66
|
+
otds_base_url
|
|
67
|
+
+ "/com.eibus.web.soap.Gateway.wcp?organization=o=system,cn=cordys,cn=defaultInst,o=opentext.net"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
otawp_config["soapGatewayUrl"] = (
|
|
71
|
+
otds_base_url
|
|
72
|
+
+ "/com.eibus.web.soap.Gateway.wcp?organization=o=system,cn=cordys,cn=defaultInst,o=opentext.net&defaultinst_ct=abcd"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
otawp_config["createPriority"] = (
|
|
76
|
+
otds_base_url
|
|
77
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/Priority?defaultinst_ct=abcd"
|
|
78
|
+
)
|
|
79
|
+
otawp_config["getAllPriorities"] = (
|
|
80
|
+
otds_base_url
|
|
81
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/Priority/lists/PriorityList"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
otawp_config["createCustomer"] = (
|
|
85
|
+
otds_base_url
|
|
86
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/Customer?defaultinst_ct=abcd"
|
|
87
|
+
)
|
|
88
|
+
otawp_config["getAllCustomeres"] = (
|
|
89
|
+
otds_base_url
|
|
90
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/Customer/lists/CustomerList"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
otawp_config["createCaseType"] = (
|
|
94
|
+
otds_base_url
|
|
95
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/CaseType?defaultinst_ct=abcd"
|
|
96
|
+
)
|
|
97
|
+
otawp_config["getAllCaseTypes"] = (
|
|
98
|
+
otds_base_url
|
|
99
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/CaseType/lists/AllCaseTypes"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
otawp_config["createCategory"] = (
|
|
103
|
+
otds_base_url
|
|
104
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/Category?defaultinst_ct=abcd"
|
|
105
|
+
)
|
|
106
|
+
otawp_config["getAllCategories"] = (
|
|
107
|
+
otds_base_url
|
|
108
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/Category/lists/CategoryList"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
otawp_config["createSource"] = (
|
|
112
|
+
otds_base_url
|
|
113
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/Source"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
otawp_config["getAllSources"] = (
|
|
117
|
+
otds_base_url
|
|
118
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/Source/lists/AllSources"
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
otawp_config["getAllSubCategories"] = (
|
|
122
|
+
otds_base_url
|
|
123
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/Category/childEntities/SubCategory/lists/AllSubcategories"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
otawp_config["baseurl"] = (
|
|
127
|
+
otds_base_url
|
|
128
|
+
+ ""
|
|
129
|
+
)
|
|
130
|
+
otawp_config["createLoan"] = (
|
|
131
|
+
otds_base_url
|
|
132
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/Case?defaultinst_ct=abcd"
|
|
133
|
+
)
|
|
134
|
+
otawp_config["getAllLoans"] = (
|
|
135
|
+
otds_base_url
|
|
136
|
+
+ "/app/entityRestService/api/OpentextCaseManagement/entities/Case/lists/AllCasesList"
|
|
137
|
+
)
|
|
138
|
+
self._config = otawp_config
|
|
139
|
+
|
|
140
|
+
# end method definition
|
|
141
|
+
|
|
142
|
+
def baseurl(self) -> dict:
|
|
143
|
+
"""Returns the configuration dictionary
|
|
144
|
+
Returns:
|
|
145
|
+
dict: Configuration dictionary
|
|
146
|
+
"""
|
|
147
|
+
return self.config()["baseurl"]
|
|
148
|
+
|
|
149
|
+
# end method definition
|
|
150
|
+
|
|
151
|
+
def config(self) -> dict:
|
|
152
|
+
"""Returns the configuration dictionary
|
|
153
|
+
Returns:
|
|
154
|
+
dict: Configuration dictionary
|
|
155
|
+
"""
|
|
156
|
+
return self._config
|
|
157
|
+
|
|
158
|
+
# end method definition
|
|
159
|
+
|
|
160
|
+
def cookie(self) -> dict:
|
|
161
|
+
"""Returns the login cookie of OTAWP.
|
|
162
|
+
This is set by the authenticate() method
|
|
163
|
+
Returns:
|
|
164
|
+
dict: OTAWP cookie
|
|
165
|
+
"""
|
|
166
|
+
return self._cookie
|
|
167
|
+
|
|
168
|
+
# end method definition
|
|
169
|
+
|
|
170
|
+
def credentials(self) -> str:
|
|
171
|
+
"""Returns the SOAP payload with credentials (username and password)
|
|
172
|
+
Returns:
|
|
173
|
+
str: SOAP payload with username and password
|
|
174
|
+
"""
|
|
175
|
+
username = self.config()["username"]
|
|
176
|
+
password = self.config()["password"]
|
|
177
|
+
|
|
178
|
+
soap_payload = f"""
|
|
179
|
+
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
|
|
180
|
+
<SOAP:Header>
|
|
181
|
+
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
|
|
182
|
+
<wsse:UsernameToken xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
|
|
183
|
+
<wsse:Username>{username}</wsse:Username>
|
|
184
|
+
<wsse:Password>{password}</wsse:Password>
|
|
185
|
+
</wsse:UsernameToken>
|
|
186
|
+
<i18n:international xmlns:i18n="http://www.w3.org/2005/09/ws-i18n">
|
|
187
|
+
<locale xmlns="http://www.w3.org/2005/09/ws-i18n">en-US</locale>
|
|
188
|
+
</i18n:international>
|
|
189
|
+
</wsse:Security>
|
|
190
|
+
</SOAP:Header>
|
|
191
|
+
<SOAP:Body>
|
|
192
|
+
<samlp:Request xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" MajorVersion="1" MinorVersion="1">
|
|
193
|
+
<samlp:AuthenticationQuery>
|
|
194
|
+
<saml:Subject xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
|
|
195
|
+
<saml:NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">{username}</saml:NameIdentifier>
|
|
196
|
+
</saml:Subject>
|
|
197
|
+
</samlp:AuthenticationQuery>
|
|
198
|
+
</samlp:Request>
|
|
199
|
+
</SOAP:Body>
|
|
200
|
+
</SOAP:Envelope>
|
|
201
|
+
"""
|
|
202
|
+
return soap_payload
|
|
203
|
+
|
|
204
|
+
# end method definition
|
|
205
|
+
|
|
206
|
+
def credential_url(self) -> str:
|
|
207
|
+
"""Returns the Credentials URL of OTAWP
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
str: Credentials URL
|
|
211
|
+
"""
|
|
212
|
+
return self.config()["gatewayAuthenticationUrl"]
|
|
213
|
+
|
|
214
|
+
# end method definition
|
|
215
|
+
|
|
216
|
+
def gateway_url(self) -> str:
|
|
217
|
+
"""Returns soapGatewayUrl URL of OTAWP
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
str: soapGatewayUrl URL
|
|
221
|
+
"""
|
|
222
|
+
return self.config()["soapGatewayUrl"]
|
|
223
|
+
|
|
224
|
+
# end method definition
|
|
225
|
+
|
|
226
|
+
def create_priority_url(self) -> str:
|
|
227
|
+
"""Returns createPriority URL of OTAWP
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
str: createPriority URL
|
|
231
|
+
"""
|
|
232
|
+
return self.config()["createPriority"]
|
|
233
|
+
|
|
234
|
+
# end method definition
|
|
235
|
+
|
|
236
|
+
def get_all_priorities_url(self) -> str:
|
|
237
|
+
"""Returns getAllPriorities URL of OTAWP
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
str: getAllPriorities URL
|
|
241
|
+
"""
|
|
242
|
+
return self.config()["getAllPriorities"]
|
|
243
|
+
|
|
244
|
+
# end method definition
|
|
245
|
+
|
|
246
|
+
def create_customer_url(self) -> str:
|
|
247
|
+
"""Returns createCustomer URL of OTAWP
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
str: createCustomer url
|
|
251
|
+
"""
|
|
252
|
+
return self.config()["createCustomer"]
|
|
253
|
+
|
|
254
|
+
# end method definition
|
|
255
|
+
|
|
256
|
+
def get_all_customeres_url(self) -> str:
|
|
257
|
+
"""Returns getAllCustomeres url of OTAWP
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
str: getAllCustomeres url
|
|
261
|
+
"""
|
|
262
|
+
return self.config()["getAllCustomeres"]
|
|
263
|
+
|
|
264
|
+
# end method definition
|
|
265
|
+
|
|
266
|
+
def create_casetype_url(self) -> str:
|
|
267
|
+
"""Returns createCaseType url of OTAWP
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
str: createCaseType url
|
|
271
|
+
"""
|
|
272
|
+
return self.config()["createCaseType"]
|
|
273
|
+
|
|
274
|
+
# end method definition
|
|
275
|
+
|
|
276
|
+
def get_all_case_types_url(self) -> str:
|
|
277
|
+
"""Returns getAllCaseTypes URL of OTAWP
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
str: getAllCaseTypes URL
|
|
281
|
+
"""
|
|
282
|
+
return self.config()["getAllCaseTypes"]
|
|
283
|
+
|
|
284
|
+
# end method definition
|
|
285
|
+
|
|
286
|
+
def create_category_url(self) -> str:
|
|
287
|
+
"""Returns createCategory URL of OTAWP
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
str: createCategory URL
|
|
291
|
+
"""
|
|
292
|
+
return self.config()["createCategory"]
|
|
293
|
+
|
|
294
|
+
# end method definition
|
|
295
|
+
|
|
296
|
+
def get_all_categories_url(self) -> str:
|
|
297
|
+
"""Returns the getAllCategories URL of OTAWP
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
str: getAllCategories URL
|
|
301
|
+
"""
|
|
302
|
+
return self.config()["getAllCategories"]
|
|
303
|
+
|
|
304
|
+
# end method definition
|
|
305
|
+
|
|
306
|
+
def get_all_loans_url(self) -> str:
|
|
307
|
+
"""Returns getAllLoans URL of OTAWP
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
str: getAllLoans URL
|
|
311
|
+
"""
|
|
312
|
+
return self.config()["getAllLoans"]
|
|
313
|
+
|
|
314
|
+
# end method definition
|
|
315
|
+
|
|
316
|
+
def remove_namespace(self, tag):
|
|
317
|
+
"""Remove namespace from XML tag."""
|
|
318
|
+
return tag.split('}', 1)[-1]
|
|
319
|
+
|
|
320
|
+
# end method definition
|
|
321
|
+
|
|
322
|
+
def parse_xml(self, xml_string):
|
|
323
|
+
"""Parse XML string and return a dictionary without namespaces."""
|
|
324
|
+
def element_to_dict(element):
|
|
325
|
+
"""Convert XML element to dictionary."""
|
|
326
|
+
tag = self.remove_namespace(element.tag)
|
|
327
|
+
children = list(element)
|
|
328
|
+
if children:
|
|
329
|
+
return {tag: {self.remove_namespace(child.tag): element_to_dict(child) for child in children}}
|
|
330
|
+
return {tag: element.text.strip() if element.text else None}
|
|
331
|
+
root = ET.fromstring(xml_string)
|
|
332
|
+
return element_to_dict(root)
|
|
333
|
+
|
|
334
|
+
# end method definition
|
|
335
|
+
|
|
336
|
+
def find_key(self, data, target_key):
|
|
337
|
+
"""Recursively search for a key in a nested dictionary and return its value."""
|
|
338
|
+
if isinstance(data, dict):
|
|
339
|
+
if target_key in data:
|
|
340
|
+
return data[target_key]
|
|
341
|
+
for _, value in data.items():
|
|
342
|
+
result = self.find_key(value, target_key)
|
|
343
|
+
if result is not None:
|
|
344
|
+
return result
|
|
345
|
+
elif isinstance(data, list):
|
|
346
|
+
for item in data:
|
|
347
|
+
result = self.find_key(item, target_key)
|
|
348
|
+
if result is not None:
|
|
349
|
+
return result
|
|
350
|
+
return None
|
|
351
|
+
|
|
352
|
+
# end method definition
|
|
353
|
+
|
|
354
|
+
def parse_request_response(
|
|
355
|
+
self,
|
|
356
|
+
response_object: object,
|
|
357
|
+
additional_error_message: str = "",
|
|
358
|
+
show_error: bool = True,
|
|
359
|
+
) -> dict | None:
|
|
360
|
+
"""Converts the text property of a request response object to a Python dict in a safe way
|
|
361
|
+
that also handles exceptions.
|
|
362
|
+
|
|
363
|
+
Content Server may produce corrupt response when it gets restarted
|
|
364
|
+
or hitting resource limits. So we try to avoid a fatal error and bail
|
|
365
|
+
out more gracefully.
|
|
366
|
+
|
|
367
|
+
Args:
|
|
368
|
+
response_object (object): this is reponse object delivered by the request call
|
|
369
|
+
additional_error_message (str): print a custom error message
|
|
370
|
+
show_error (bool): if True log an error, if False log a warning
|
|
371
|
+
|
|
372
|
+
Returns:
|
|
373
|
+
dict: response or None in case of an error
|
|
374
|
+
"""
|
|
375
|
+
|
|
376
|
+
if not response_object:
|
|
377
|
+
return None
|
|
378
|
+
|
|
379
|
+
try:
|
|
380
|
+
dict_object = json.loads(response_object.text)
|
|
381
|
+
except json.JSONDecodeError as exception:
|
|
382
|
+
if additional_error_message:
|
|
383
|
+
message = "Cannot decode response as JSon. {}; error -> {}".format(
|
|
384
|
+
additional_error_message, exception
|
|
385
|
+
)
|
|
386
|
+
else:
|
|
387
|
+
message = "Cannot decode response as JSon; error -> {}".format(
|
|
388
|
+
exception
|
|
389
|
+
)
|
|
390
|
+
if show_error:
|
|
391
|
+
logger.error(message)
|
|
392
|
+
else:
|
|
393
|
+
logger.warning(message)
|
|
394
|
+
return None
|
|
395
|
+
return dict_object
|
|
396
|
+
|
|
397
|
+
# end method definition
|
|
398
|
+
|
|
399
|
+
def authenticate(self, revalidate: bool = False) -> dict | None:
|
|
400
|
+
"""Authenticate at appworks.
|
|
401
|
+
|
|
402
|
+
Args:
|
|
403
|
+
revalidate (bool, optional): determine if a re-authentication is enforced
|
|
404
|
+
(e.g. if session has timed out with 401 error)
|
|
405
|
+
Returns:
|
|
406
|
+
dict: Cookie information. Also stores cookie information in self._cookie
|
|
407
|
+
"""
|
|
408
|
+
|
|
409
|
+
logger.info("SAMLart generation started")
|
|
410
|
+
if self._cookie and not revalidate:
|
|
411
|
+
logger.info(
|
|
412
|
+
"Session still valid - return existing cookie -> %s",
|
|
413
|
+
str(self._cookie),
|
|
414
|
+
)
|
|
415
|
+
return self._cookie
|
|
416
|
+
|
|
417
|
+
otawp_ticket = "NotSet"
|
|
418
|
+
|
|
419
|
+
response = None
|
|
420
|
+
try:
|
|
421
|
+
self.credentials()
|
|
422
|
+
response = requests.post(
|
|
423
|
+
url=self.credential_url(),
|
|
424
|
+
data=self.credentials(),
|
|
425
|
+
headers=REQUEST_HEADERS,
|
|
426
|
+
timeout=REQUEST_TIMEOUT
|
|
427
|
+
)
|
|
428
|
+
except requests.exceptions.RequestException as exception:
|
|
429
|
+
logger.warning(
|
|
430
|
+
"Unable to connect to -> %s; error -> %s",
|
|
431
|
+
self.credential_url(),
|
|
432
|
+
exception.strerror,
|
|
433
|
+
)
|
|
434
|
+
logger.warning("OTAWP service may not be ready yet.")
|
|
435
|
+
return None
|
|
436
|
+
|
|
437
|
+
if response.ok:
|
|
438
|
+
logger.info("SAMLart generated successfully")
|
|
439
|
+
authenticate_dict = self.parse_xml(response.text)
|
|
440
|
+
if not authenticate_dict:
|
|
441
|
+
return None
|
|
442
|
+
assertion_artifact_dict = self.find_key(
|
|
443
|
+
authenticate_dict, "AssertionArtifact"
|
|
444
|
+
)
|
|
445
|
+
if isinstance(assertion_artifact_dict, dict):
|
|
446
|
+
otawp_ticket = assertion_artifact_dict.get("AssertionArtifact")
|
|
447
|
+
logger.info("SAML token -> %s", otawp_ticket)
|
|
448
|
+
else:
|
|
449
|
+
logger.error("Failed to request an OTAWP ticket; error -> %s", response.text)
|
|
450
|
+
return None
|
|
451
|
+
|
|
452
|
+
self._cookie = {"defaultinst_SAMLart": otawp_ticket, "defaultinst_ct": "abcd"}
|
|
453
|
+
self._otawp_ticket = otawp_ticket
|
|
454
|
+
|
|
455
|
+
return self._cookie
|
|
456
|
+
|
|
457
|
+
# end method definition
|
|
458
|
+
|
|
459
|
+
def create_workspace(
|
|
460
|
+
self,
|
|
461
|
+
workspace_name: str,
|
|
462
|
+
workspace_id: str
|
|
463
|
+
) -> dict | None:
|
|
464
|
+
"""Creates a workspace in cws
|
|
465
|
+
Args:
|
|
466
|
+
workspace_name (str): workspace_name
|
|
467
|
+
workspace_id (str): workspace_id
|
|
468
|
+
Returns:
|
|
469
|
+
response test or error text
|
|
470
|
+
"""
|
|
471
|
+
|
|
472
|
+
logger.info(
|
|
473
|
+
"Create workspace with name -> '%s' and ID -> %s...",
|
|
474
|
+
workspace_name,
|
|
475
|
+
workspace_id,
|
|
476
|
+
)
|
|
477
|
+
unique_id = uuid.uuid4()
|
|
478
|
+
|
|
479
|
+
license_post_body_json = f"""<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
|
|
480
|
+
<SOAP:Body>
|
|
481
|
+
<createWorkspace xmlns="http://schemas.cordys.com/cws/runtime/types/workspace/creation/DevelopmentWorkspaceCreator/1.0" async="false" workspaceID="__CWS System__" xmlns:c="http://schemas.cordys.com/cws/1.0">
|
|
482
|
+
<instance>
|
|
483
|
+
<c:Document s="T" path="D43B04C1-CD0B-A1EB-A898-53C71DB5D652">
|
|
484
|
+
<c:Header>
|
|
485
|
+
<c:System>
|
|
486
|
+
<c:TypeID>001A6B1E-0C0C-11DF-F5E9-866B84E5D671</c:TypeID>
|
|
487
|
+
<c:ID>D43B04C1-CD0B-A1EB-A898-53C71DB5D652</c:ID>
|
|
488
|
+
<c:Name>D43B04C1-CD0B-A1EB-A898-53C71DB5D652</c:Name>
|
|
489
|
+
<c:Description>D43B04C1-CD0B-A1EB-A898-53C71DB5D652</c:Description>
|
|
490
|
+
</c:System>
|
|
491
|
+
</c:Header>
|
|
492
|
+
<c:Content>
|
|
493
|
+
<DevelopmentWorkspaceCreator type="com.cordys.cws.runtime.types.workspace.creation.DevelopmentWorkspaceCreator" runtimeDocumentID="D43B04C1-CD0B-A1EB-A898-53C71DB61652">
|
|
494
|
+
<Workspace>
|
|
495
|
+
<uri id="{workspace_id}"/>
|
|
496
|
+
</Workspace>
|
|
497
|
+
</DevelopmentWorkspaceCreator>
|
|
498
|
+
</c:Content>
|
|
499
|
+
</c:Document>
|
|
500
|
+
</instance>
|
|
501
|
+
<__prefetch>
|
|
502
|
+
<Document xmlns="http://schemas.cordys.com/cws/1.0" path="{workspace_name}" s="N" isLocal="IN_LOCAL">
|
|
503
|
+
<Header>
|
|
504
|
+
<System>
|
|
505
|
+
<ID>{workspace_id}</ID>
|
|
506
|
+
<Name>{workspace_name}</Name>
|
|
507
|
+
<TypeID>{{4CE11E00-2D97-45C0-BC6C-FAEC1D871026}}</TypeID>
|
|
508
|
+
<ParentID/>
|
|
509
|
+
<Description>{workspace_name}</Description>
|
|
510
|
+
<CreatedBy>sysadmin</CreatedBy>
|
|
511
|
+
<CreationDate/>
|
|
512
|
+
<LastModifiedBy>sysadmin</LastModifiedBy>
|
|
513
|
+
<LastModifiedDate>2021-04-21T06:52:34.254</LastModifiedDate>
|
|
514
|
+
<FQN/>
|
|
515
|
+
<Annotation/>
|
|
516
|
+
<ParentID/>
|
|
517
|
+
<OptimisticLock/>
|
|
518
|
+
</System>
|
|
519
|
+
</Header>
|
|
520
|
+
<Content>
|
|
521
|
+
<DevelopmentWorkspace xmlns="http://schemas.cordys.com/cws/runtime/types/workspace/DevelopmentWorkspace/1.0" runtimeDocumentID="D43B04C1-CD0B-A1EB-A898-53C71DB59652" type="com.cordys.cws.runtime.types.workspace.DevelopmentWorkspace">
|
|
522
|
+
<ExternalID/>
|
|
523
|
+
<OrganizationName/>
|
|
524
|
+
<SCMAdapter>
|
|
525
|
+
<uri id="{unique_id}"/>
|
|
526
|
+
</SCMAdapter>
|
|
527
|
+
<UpgradedTo/>
|
|
528
|
+
<LastWorkspaceUpgradeStep/>
|
|
529
|
+
<Metaspace/>
|
|
530
|
+
</DevelopmentWorkspace>
|
|
531
|
+
</Content>
|
|
532
|
+
</Document>
|
|
533
|
+
<Document xmlns="http://schemas.cordys.com/cws/1.0" path="{workspace_name}/Untitled No SCM adapter" s="N" isLocal="IN_LOCAL">
|
|
534
|
+
<Header>
|
|
535
|
+
<System>
|
|
536
|
+
<ID>{unique_id}</ID>
|
|
537
|
+
<Name>Untitled No SCM adapter</Name>
|
|
538
|
+
<TypeID>{{E89F3F62-8CA3-4F93-95A8-F76642FD5124}}</TypeID>
|
|
539
|
+
<ParentID>{workspace_id}</ParentID>
|
|
540
|
+
<Description>Untitled No SCM adapter</Description>
|
|
541
|
+
<CreatedBy>sysadmin</CreatedBy>
|
|
542
|
+
<CreationDate/>
|
|
543
|
+
<LastModifiedBy>sysadmin</LastModifiedBy>
|
|
544
|
+
<LastModifiedDate>2021-04-21T06:52:34.254</LastModifiedDate>
|
|
545
|
+
<FQN/>
|
|
546
|
+
<Annotation/>
|
|
547
|
+
<OptimisticLock/>
|
|
548
|
+
</System>
|
|
549
|
+
</Header>
|
|
550
|
+
<Content>
|
|
551
|
+
<NullAdapter xmlns="http://schemas.cordys.com/cws/runtime/types/teamdevelopment/NullAdapter/1.0" runtimeDocumentID="D43B04C1-CD0B-A1EB-A898-53C71DB51652" type="com.cordys.cws.runtime.types.teamdevelopment.NullAdapter">
|
|
552
|
+
<Workspace>
|
|
553
|
+
<uri id="{workspace_id}"/>
|
|
554
|
+
</Workspace>
|
|
555
|
+
</NullAdapter>
|
|
556
|
+
</Content>
|
|
557
|
+
</Document>
|
|
558
|
+
</__prefetch>
|
|
559
|
+
</createWorkspace>
|
|
560
|
+
</SOAP:Body>
|
|
561
|
+
</SOAP:Envelope>"""
|
|
562
|
+
|
|
563
|
+
retries = 0
|
|
564
|
+
while True:
|
|
565
|
+
response = requests.post(
|
|
566
|
+
url=self.gateway_url(),
|
|
567
|
+
data=license_post_body_json,
|
|
568
|
+
headers=REQUEST_HEADERS,
|
|
569
|
+
cookies=self.cookie(),
|
|
570
|
+
timeout=None,
|
|
571
|
+
)
|
|
572
|
+
if response.ok:
|
|
573
|
+
logger.info(
|
|
574
|
+
"Successfully created workspace -> '%s' with ID -> %s",
|
|
575
|
+
workspace_name,
|
|
576
|
+
workspace_id,
|
|
577
|
+
)
|
|
578
|
+
return response.text
|
|
579
|
+
# Check if Session has expired - then re-authenticate and try once more
|
|
580
|
+
if response.status_code == 401 and retries == 0:
|
|
581
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
582
|
+
self.authenticate(revalidate=True)
|
|
583
|
+
retries += 1
|
|
584
|
+
logger.error(response.text)
|
|
585
|
+
return response.text
|
|
586
|
+
|
|
587
|
+
# end method definition
|
|
588
|
+
|
|
589
|
+
def sync_workspace(
|
|
590
|
+
self,
|
|
591
|
+
workspace_name: str,
|
|
592
|
+
workspace_id: str
|
|
593
|
+
) -> dict | None:
|
|
594
|
+
""" sync workspaces
|
|
595
|
+
Args:
|
|
596
|
+
workspace_name (str): workspace_name
|
|
597
|
+
workspace_id (str): workspace_id
|
|
598
|
+
Returns:
|
|
599
|
+
Request response (dictionary) or None if the REST call fails
|
|
600
|
+
"""
|
|
601
|
+
|
|
602
|
+
logger.info("Start synchronization of workspace -> '%s'...", workspace_name)
|
|
603
|
+
|
|
604
|
+
license_post_body_json = f"""<SOAP:Envelope xmlns:SOAP=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n" +
|
|
605
|
+
" <SOAP:Body>\r\n" +
|
|
606
|
+
" <Synchronize workspaceID=\"{workspace_id}\" xmlns=\"http://schemas.cordys.com/cws/synchronize/1.0\" >\r\n" +
|
|
607
|
+
" <DocumentID/>\r\n" +
|
|
608
|
+
" <Asynchronous>false</Asynchronous>\r\n" +
|
|
609
|
+
" </Synchronize>\r\n" +
|
|
610
|
+
" </SOAP:Body>\r\n" +
|
|
611
|
+
"</SOAP:Envelope>"""
|
|
612
|
+
# self.authenticate(revalidate=True)
|
|
613
|
+
|
|
614
|
+
retries = 0
|
|
615
|
+
while True:
|
|
616
|
+
response = requests.post(
|
|
617
|
+
url=self.gateway_url(),
|
|
618
|
+
data=license_post_body_json,
|
|
619
|
+
headers=REQUEST_HEADERS,
|
|
620
|
+
cookies=self.cookie(),
|
|
621
|
+
timeout=None,
|
|
622
|
+
)
|
|
623
|
+
if response.ok:
|
|
624
|
+
logger.info("Workspace -> '%s' synced successfully", workspace_name)
|
|
625
|
+
return self.parse_xml(response.text)
|
|
626
|
+
if response.status_code == 401 and retries == 0:
|
|
627
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
628
|
+
self.authenticate(revalidate=True)
|
|
629
|
+
retries += 1
|
|
630
|
+
logger.error(response.text)
|
|
631
|
+
return None
|
|
632
|
+
|
|
633
|
+
# end method definition
|
|
634
|
+
|
|
635
|
+
def publish_project(
|
|
636
|
+
self,
|
|
637
|
+
workspace_name: str,
|
|
638
|
+
project_name: str,
|
|
639
|
+
workspace_id: str,
|
|
640
|
+
project_id: str
|
|
641
|
+
) -> dict | bool:
|
|
642
|
+
"""
|
|
643
|
+
Publish the workspace project.
|
|
644
|
+
|
|
645
|
+
Args:
|
|
646
|
+
workspace_name (str): The name of the workspace.
|
|
647
|
+
project_name (str): The name of the project.
|
|
648
|
+
workspace_id (str): The workspace ID.
|
|
649
|
+
project_id (str): The project ID.
|
|
650
|
+
|
|
651
|
+
Returns:
|
|
652
|
+
dict | bool: Request response (dictionary) if successful, False if it fails after retries.
|
|
653
|
+
"""
|
|
654
|
+
|
|
655
|
+
logger.info(
|
|
656
|
+
"Publish project -> '%s' in workspace -> '%s'...",
|
|
657
|
+
project_name,
|
|
658
|
+
workspace_name,
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
project_publish = f"""<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
|
|
662
|
+
<SOAP:Body>
|
|
663
|
+
<deployObject xmlns="http://schemas.cordys.com/cws/internal/buildhelper/BuildHelper/1.0" async="false" workspaceID="{workspace_id}" xmlns:c="http://schemas.cordys.com/cws/1.0">
|
|
664
|
+
<object>
|
|
665
|
+
<c:uri id="{project_id}"/>
|
|
666
|
+
</object>
|
|
667
|
+
</deployObject>
|
|
668
|
+
</SOAP:Body>
|
|
669
|
+
</SOAP:Envelope>"""
|
|
670
|
+
|
|
671
|
+
# Initialize retry parameters
|
|
672
|
+
max_retries = 10
|
|
673
|
+
retries = 0
|
|
674
|
+
success_indicator = "deployObjectResponse"
|
|
675
|
+
|
|
676
|
+
while retries < max_retries:
|
|
677
|
+
response = requests.post(
|
|
678
|
+
url=self.gateway_url(),
|
|
679
|
+
data=project_publish,
|
|
680
|
+
headers=REQUEST_HEADERS,
|
|
681
|
+
cookies=self.cookie(),
|
|
682
|
+
timeout=None,
|
|
683
|
+
)
|
|
684
|
+
|
|
685
|
+
# Check if the response is successful
|
|
686
|
+
if response.ok:
|
|
687
|
+
# Check if the response contains the success indicator
|
|
688
|
+
if success_indicator in response.text:
|
|
689
|
+
logger.info(
|
|
690
|
+
"Successfully published project -> '%s' in workspace -> '%s'",
|
|
691
|
+
project_name,
|
|
692
|
+
workspace_name,
|
|
693
|
+
)
|
|
694
|
+
return True
|
|
695
|
+
|
|
696
|
+
# If success indicator is not found, retry
|
|
697
|
+
logger.warning(
|
|
698
|
+
"Expected success indicator -> '%s' but it was not found in response. Retrying in 30 seconds... (Attempt %d of %d)",
|
|
699
|
+
success_indicator,
|
|
700
|
+
retries + 1,
|
|
701
|
+
max_retries,
|
|
702
|
+
)
|
|
703
|
+
time.sleep(30)
|
|
704
|
+
retries += 1
|
|
705
|
+
continue
|
|
706
|
+
|
|
707
|
+
# Check for session expiry and retry authentication (only once)
|
|
708
|
+
if response.status_code == 401 and retries == 0:
|
|
709
|
+
logger.warning("Session has expired - re-authenticating...")
|
|
710
|
+
self.authenticate(revalidate=True)
|
|
711
|
+
retries += 1
|
|
712
|
+
continue
|
|
713
|
+
|
|
714
|
+
# Log any other error and break the loop
|
|
715
|
+
logger.error(
|
|
716
|
+
"Error publishing project -> '%s' in workspace -> '%s'; response -> %s",
|
|
717
|
+
project_name,
|
|
718
|
+
workspace_name,
|
|
719
|
+
response.text,
|
|
720
|
+
)
|
|
721
|
+
break
|
|
722
|
+
|
|
723
|
+
# After reaching the maximum number of retries, log failure and return False
|
|
724
|
+
logger.error(
|
|
725
|
+
"Max retries reached. Failed to publish project -> '%s' in workspace -> '%s'.",
|
|
726
|
+
project_name,
|
|
727
|
+
workspace_name,
|
|
728
|
+
)
|
|
729
|
+
return False
|
|
730
|
+
|
|
731
|
+
# end method definition
|
|
732
|
+
|
|
733
|
+
def create_priority(
|
|
734
|
+
self,
|
|
735
|
+
name: str,
|
|
736
|
+
description: str,
|
|
737
|
+
status: int
|
|
738
|
+
) -> dict | None:
|
|
739
|
+
""" Create Priority entity instances.
|
|
740
|
+
|
|
741
|
+
Args:
|
|
742
|
+
name (str): name
|
|
743
|
+
description (str): description
|
|
744
|
+
status (int): status
|
|
745
|
+
Returns:
|
|
746
|
+
dict: Request response (dictionary) or None if the REST call fails
|
|
747
|
+
"""
|
|
748
|
+
create_priority = {
|
|
749
|
+
"Properties": {
|
|
750
|
+
"Name": name,
|
|
751
|
+
"Description": description,
|
|
752
|
+
"Status": status
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
retries = 0
|
|
756
|
+
while True:
|
|
757
|
+
response = requests.post(
|
|
758
|
+
url=self.create_priority_url(),
|
|
759
|
+
json=create_priority,
|
|
760
|
+
headers=REQUEST_HEADERS_JSON,
|
|
761
|
+
cookies=self.cookie(),
|
|
762
|
+
timeout=None,
|
|
763
|
+
)
|
|
764
|
+
if response.ok:
|
|
765
|
+
logger.info("Priority created successfully")
|
|
766
|
+
return self.parse_request_response(
|
|
767
|
+
response, "This can be normal during restart", False
|
|
768
|
+
)
|
|
769
|
+
if response.status_code == 401 and retries == 0:
|
|
770
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
771
|
+
self.authenticate(revalidate=True)
|
|
772
|
+
retries += 1
|
|
773
|
+
logger.error(response.text)
|
|
774
|
+
return None
|
|
775
|
+
|
|
776
|
+
# end method definition
|
|
777
|
+
|
|
778
|
+
def get_all_priorities(
|
|
779
|
+
self
|
|
780
|
+
) -> dict | None:
|
|
781
|
+
""" Get all priorities from entity
|
|
782
|
+
Args:
|
|
783
|
+
None
|
|
784
|
+
Returns:
|
|
785
|
+
dict: Request response (dictionary) or None if the REST call fails
|
|
786
|
+
"""
|
|
787
|
+
retries = 0
|
|
788
|
+
while True:
|
|
789
|
+
response = requests.get(
|
|
790
|
+
url=self.get_all_priorities_url(),
|
|
791
|
+
headers=REQUEST_HEADERS_JSON,
|
|
792
|
+
cookies=self.cookie(),
|
|
793
|
+
timeout=None,
|
|
794
|
+
)
|
|
795
|
+
if response.ok:
|
|
796
|
+
authenticate_dict = self.parse_request_response(
|
|
797
|
+
response, "This can be normal during restart", False
|
|
798
|
+
)
|
|
799
|
+
if not authenticate_dict:
|
|
800
|
+
return None
|
|
801
|
+
return authenticate_dict
|
|
802
|
+
if response.status_code == 401 and retries == 0:
|
|
803
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
804
|
+
self.authenticate(revalidate=True)
|
|
805
|
+
retries += 1
|
|
806
|
+
logger.error(response.text)
|
|
807
|
+
return None
|
|
808
|
+
|
|
809
|
+
# end method definition
|
|
810
|
+
|
|
811
|
+
def create_customer(
|
|
812
|
+
self,
|
|
813
|
+
customer_name: str,
|
|
814
|
+
legal_business_name: str,
|
|
815
|
+
trading_name: str
|
|
816
|
+
) -> dict | None:
|
|
817
|
+
""" Create customer entity instance
|
|
818
|
+
|
|
819
|
+
Args:
|
|
820
|
+
customer_name (str): customer_name
|
|
821
|
+
legal_business_name (str): legal_business_name
|
|
822
|
+
trading_name (str): trading_name
|
|
823
|
+
Returns:
|
|
824
|
+
dict: Request response (dictionary) or None if the REST call fails
|
|
825
|
+
"""
|
|
826
|
+
create_customer = {
|
|
827
|
+
"Properties": {
|
|
828
|
+
"CustomerName": customer_name,
|
|
829
|
+
"LegalBusinessName": legal_business_name,
|
|
830
|
+
"TradingName": trading_name
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
retries = 0
|
|
834
|
+
while True:
|
|
835
|
+
response = requests.post(
|
|
836
|
+
url=self.create_customer_url(),
|
|
837
|
+
json=create_customer,
|
|
838
|
+
headers=REQUEST_HEADERS_JSON,
|
|
839
|
+
cookies=self.cookie(),
|
|
840
|
+
timeout=None,
|
|
841
|
+
)
|
|
842
|
+
if response.ok:
|
|
843
|
+
logger.info("Customer record created successfully")
|
|
844
|
+
return self.parse_request_response(response, "This can be normal during restart", False)
|
|
845
|
+
if response.status_code == 401 and retries == 0:
|
|
846
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
847
|
+
self.authenticate(revalidate=True)
|
|
848
|
+
retries += 1
|
|
849
|
+
logger.error(response.text)
|
|
850
|
+
return None
|
|
851
|
+
|
|
852
|
+
# end method definition
|
|
853
|
+
|
|
854
|
+
def get_all_customers(
|
|
855
|
+
self
|
|
856
|
+
) -> dict | None:
|
|
857
|
+
"""get all customer entity imstances
|
|
858
|
+
|
|
859
|
+
Args:
|
|
860
|
+
None
|
|
861
|
+
Returns:
|
|
862
|
+
dict: Request response (dictionary) or None if the REST call fails
|
|
863
|
+
"""
|
|
864
|
+
|
|
865
|
+
retries = 0
|
|
866
|
+
while True:
|
|
867
|
+
response = requests.get(
|
|
868
|
+
url=self.get_all_customeres_url(),
|
|
869
|
+
headers=REQUEST_HEADERS_JSON,
|
|
870
|
+
cookies=self.cookie(),
|
|
871
|
+
timeout=None,
|
|
872
|
+
)
|
|
873
|
+
if response.ok:
|
|
874
|
+
authenticate_dict = self.parse_request_response(
|
|
875
|
+
response, "This can be normal during restart", False
|
|
876
|
+
)
|
|
877
|
+
if not authenticate_dict:
|
|
878
|
+
return None
|
|
879
|
+
return authenticate_dict
|
|
880
|
+
if response.status_code == 401 and retries == 0:
|
|
881
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
882
|
+
self.authenticate(revalidate=True)
|
|
883
|
+
retries += 1
|
|
884
|
+
logger.error(response.text)
|
|
885
|
+
return None
|
|
886
|
+
|
|
887
|
+
# end method definition
|
|
888
|
+
|
|
889
|
+
def create_case_type(
|
|
890
|
+
self,
|
|
891
|
+
name: str,
|
|
892
|
+
description: str,
|
|
893
|
+
status: int
|
|
894
|
+
) -> dict | None:
|
|
895
|
+
"""create case_type entity instances
|
|
896
|
+
|
|
897
|
+
Args:
|
|
898
|
+
name (str): name
|
|
899
|
+
description (str): description
|
|
900
|
+
status (str): status
|
|
901
|
+
Returns:
|
|
902
|
+
dict: Request response (dictionary) or None if the REST call fails
|
|
903
|
+
"""
|
|
904
|
+
create_case_type = {
|
|
905
|
+
"Properties": {
|
|
906
|
+
"Name": name,
|
|
907
|
+
"Description": description,
|
|
908
|
+
"Status": status
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
retries = 0
|
|
912
|
+
while True:
|
|
913
|
+
response = requests.post(
|
|
914
|
+
url=self.create_casetype_url(),
|
|
915
|
+
json=create_case_type,
|
|
916
|
+
headers=REQUEST_HEADERS_JSON,
|
|
917
|
+
cookies=self.cookie(),
|
|
918
|
+
timeout=None,
|
|
919
|
+
)
|
|
920
|
+
if response.ok:
|
|
921
|
+
logger.info("Case type created successfully")
|
|
922
|
+
return self.parse_request_response(
|
|
923
|
+
response, "This can be normal during restart", False
|
|
924
|
+
)
|
|
925
|
+
if response.status_code == 401 and retries == 0:
|
|
926
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
927
|
+
self.authenticate(revalidate=True)
|
|
928
|
+
retries += 1
|
|
929
|
+
logger.error(response.text)
|
|
930
|
+
return None
|
|
931
|
+
|
|
932
|
+
# end method definition
|
|
933
|
+
|
|
934
|
+
def get_all_case_type(
|
|
935
|
+
self
|
|
936
|
+
) -> dict | None:
|
|
937
|
+
"""get all case type entty instances
|
|
938
|
+
|
|
939
|
+
Args:
|
|
940
|
+
None
|
|
941
|
+
Returns:
|
|
942
|
+
dict: Request response (dictionary) or None if the REST call fails
|
|
943
|
+
"""
|
|
944
|
+
retries = 0
|
|
945
|
+
while True:
|
|
946
|
+
response = requests.get(
|
|
947
|
+
url=self.get_all_case_types_url(),
|
|
948
|
+
headers=REQUEST_HEADERS_JSON,
|
|
949
|
+
cookies=self.cookie(),
|
|
950
|
+
timeout=None,
|
|
951
|
+
)
|
|
952
|
+
if response.ok:
|
|
953
|
+
authenticate_dict = self.parse_request_response(
|
|
954
|
+
response, "This can be normal during restart", False
|
|
955
|
+
)
|
|
956
|
+
if not authenticate_dict:
|
|
957
|
+
return None
|
|
958
|
+
return authenticate_dict
|
|
959
|
+
if response.status_code == 401 and retries == 0:
|
|
960
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
961
|
+
self.authenticate(revalidate=True)
|
|
962
|
+
retries += 1
|
|
963
|
+
logger.error(response.text)
|
|
964
|
+
return None
|
|
965
|
+
|
|
966
|
+
# end method definition
|
|
967
|
+
|
|
968
|
+
def create_category(
|
|
969
|
+
self,
|
|
970
|
+
case_prefix: str,
|
|
971
|
+
description: str,
|
|
972
|
+
name: str,
|
|
973
|
+
status: int
|
|
974
|
+
) -> dict | None:
|
|
975
|
+
"""create category entity instance
|
|
976
|
+
|
|
977
|
+
Args:
|
|
978
|
+
case_prefix (str): workspace_name
|
|
979
|
+
description (str): description
|
|
980
|
+
name (str): name
|
|
981
|
+
status (str): status
|
|
982
|
+
Returns:
|
|
983
|
+
dict: Request response (dictionary) or None if the REST call fails
|
|
984
|
+
"""
|
|
985
|
+
create_categoty = {
|
|
986
|
+
"Properties": {
|
|
987
|
+
"CasePrefix": case_prefix,
|
|
988
|
+
"Description": description,
|
|
989
|
+
"Name": name,
|
|
990
|
+
"Status": status
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
retries = 0
|
|
994
|
+
while True:
|
|
995
|
+
response = requests.post(
|
|
996
|
+
url=self.create_category_url(),
|
|
997
|
+
json=create_categoty,
|
|
998
|
+
headers=REQUEST_HEADERS_JSON,
|
|
999
|
+
cookies=self.cookie(),
|
|
1000
|
+
timeout=None,
|
|
1001
|
+
)
|
|
1002
|
+
if response.ok:
|
|
1003
|
+
logger.info("Category created successfully")
|
|
1004
|
+
return self.parse_request_response(response, "This can be normal during restart", False)
|
|
1005
|
+
if response.status_code == 401 and retries == 0:
|
|
1006
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
1007
|
+
self.authenticate(revalidate=True)
|
|
1008
|
+
retries += 1
|
|
1009
|
+
logger.error(response.text)
|
|
1010
|
+
return None
|
|
1011
|
+
|
|
1012
|
+
# end method definition
|
|
1013
|
+
|
|
1014
|
+
def get_all_categories(
|
|
1015
|
+
self
|
|
1016
|
+
) -> dict | None:
|
|
1017
|
+
"""Get all categories entity intances
|
|
1018
|
+
|
|
1019
|
+
Args:
|
|
1020
|
+
None
|
|
1021
|
+
Returns:
|
|
1022
|
+
dict: Request response (dictionary) or None if the REST call fails
|
|
1023
|
+
"""
|
|
1024
|
+
|
|
1025
|
+
retries = 0
|
|
1026
|
+
while True:
|
|
1027
|
+
response = requests.get(
|
|
1028
|
+
url=self.get_all_categories_url(),
|
|
1029
|
+
headers=REQUEST_HEADERS_JSON,
|
|
1030
|
+
cookies=self.cookie(),
|
|
1031
|
+
timeout=None,
|
|
1032
|
+
)
|
|
1033
|
+
if response.ok:
|
|
1034
|
+
authenticate_dict = self.parse_request_response(
|
|
1035
|
+
response, "This can be normal during restart", False
|
|
1036
|
+
)
|
|
1037
|
+
if not authenticate_dict:
|
|
1038
|
+
return None
|
|
1039
|
+
return authenticate_dict
|
|
1040
|
+
if response.status_code == 401 and retries == 0:
|
|
1041
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
1042
|
+
self.authenticate(revalidate=True)
|
|
1043
|
+
retries += 1
|
|
1044
|
+
logger.error(response.text)
|
|
1045
|
+
return None
|
|
1046
|
+
|
|
1047
|
+
# end method definition
|
|
1048
|
+
|
|
1049
|
+
def create_sub_categoy(
|
|
1050
|
+
self,
|
|
1051
|
+
name: str,
|
|
1052
|
+
description: str,
|
|
1053
|
+
status: int,
|
|
1054
|
+
parentid: int
|
|
1055
|
+
) -> dict | None:
|
|
1056
|
+
""" create sub_categoy entity istances
|
|
1057
|
+
|
|
1058
|
+
Args:
|
|
1059
|
+
name (str): name
|
|
1060
|
+
description (str): description
|
|
1061
|
+
status (int): status
|
|
1062
|
+
parentid (int): parentid
|
|
1063
|
+
Returns:
|
|
1064
|
+
dict: Request response (dictionary) or None if the REST call fails
|
|
1065
|
+
"""
|
|
1066
|
+
create_sub_categoty = {
|
|
1067
|
+
"Properties": {
|
|
1068
|
+
"Name": name,
|
|
1069
|
+
"Description": description,
|
|
1070
|
+
"Status": status
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
retries = 0
|
|
1074
|
+
while True:
|
|
1075
|
+
base_url = self.baseurl()
|
|
1076
|
+
endpoint = "/app/entityRestService/api/OpentextCaseManagement/entities/Category/items/"
|
|
1077
|
+
child_path = "/childEntities/SubCategory?defaultinst_ct=abcd"
|
|
1078
|
+
response = requests.post(
|
|
1079
|
+
url=base_url + endpoint + str(parentid) + child_path,
|
|
1080
|
+
json=create_sub_categoty,
|
|
1081
|
+
headers=REQUEST_HEADERS_JSON,
|
|
1082
|
+
cookies=self.cookie(),
|
|
1083
|
+
timeout=None,
|
|
1084
|
+
)
|
|
1085
|
+
if response.ok:
|
|
1086
|
+
logger.info("Sub category created successfully")
|
|
1087
|
+
return self.parse_request_response(
|
|
1088
|
+
response, "This can be normal during restart", False
|
|
1089
|
+
)
|
|
1090
|
+
if response.status_code == 401 and retries == 0:
|
|
1091
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
1092
|
+
self.authenticate(revalidate=True)
|
|
1093
|
+
retries += 1
|
|
1094
|
+
logger.error(response.text)
|
|
1095
|
+
return None
|
|
1096
|
+
|
|
1097
|
+
# end method definition
|
|
1098
|
+
|
|
1099
|
+
def get_all_sub_categeries(
|
|
1100
|
+
self,
|
|
1101
|
+
parentid: int
|
|
1102
|
+
) -> dict | None:
|
|
1103
|
+
"""Get all sub categeries entity instances
|
|
1104
|
+
|
|
1105
|
+
Args:
|
|
1106
|
+
parentid (int): parentid
|
|
1107
|
+
Returns:
|
|
1108
|
+
dict: Request response (dictionary) or None if the REST call fails
|
|
1109
|
+
"""
|
|
1110
|
+
retries = 0
|
|
1111
|
+
while True:
|
|
1112
|
+
base_url = self.baseurl()
|
|
1113
|
+
endpoint = "/app/entityRestService/api/OpentextCaseManagement/entities/Category/items/"
|
|
1114
|
+
child_path = "/childEntities/SubCategory"
|
|
1115
|
+
response = requests.get(
|
|
1116
|
+
url=base_url + endpoint + str(parentid) + child_path,
|
|
1117
|
+
headers=REQUEST_HEADERS_JSON,
|
|
1118
|
+
cookies=self.cookie(),
|
|
1119
|
+
timeout=None,
|
|
1120
|
+
)
|
|
1121
|
+
if response.ok:
|
|
1122
|
+
authenticate_dict = self.parse_request_response(
|
|
1123
|
+
response, "This can be normal during restart", False
|
|
1124
|
+
)
|
|
1125
|
+
if not authenticate_dict:
|
|
1126
|
+
return None
|
|
1127
|
+
return authenticate_dict
|
|
1128
|
+
if response.status_code == 401 and retries == 0:
|
|
1129
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
1130
|
+
self.authenticate(revalidate=True)
|
|
1131
|
+
retries += 1
|
|
1132
|
+
logger.error(response.text)
|
|
1133
|
+
return None
|
|
1134
|
+
|
|
1135
|
+
# end method definition
|
|
1136
|
+
|
|
1137
|
+
def create_loan(
|
|
1138
|
+
self,
|
|
1139
|
+
subject: str,
|
|
1140
|
+
description: str,
|
|
1141
|
+
loan_amount: str,
|
|
1142
|
+
loan_duration_in_months: str,
|
|
1143
|
+
category: str,
|
|
1144
|
+
subcategory: str,
|
|
1145
|
+
piority: str,
|
|
1146
|
+
service: str,
|
|
1147
|
+
customer: str
|
|
1148
|
+
|
|
1149
|
+
) -> dict | None:
|
|
1150
|
+
"""create loan entity instance
|
|
1151
|
+
|
|
1152
|
+
Args:
|
|
1153
|
+
subject (str): subject
|
|
1154
|
+
description (str): description
|
|
1155
|
+
loan_amount (str): loan_amount
|
|
1156
|
+
loan_duration_in_months (str): loan_duration_in_months
|
|
1157
|
+
category (str): category
|
|
1158
|
+
subcategory (str): subcategory
|
|
1159
|
+
piority (str): piority
|
|
1160
|
+
service (str): service
|
|
1161
|
+
customer (str): customer
|
|
1162
|
+
Returns:
|
|
1163
|
+
dict: Request response (dictionary) or None if the REST call fails
|
|
1164
|
+
"""
|
|
1165
|
+
create_loan = f"""<SOAP:Envelope xmlns:SOAP=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n
|
|
1166
|
+
<SOAP:Body>\r\n
|
|
1167
|
+
<CreateCase xmlns=\"http://schemas/OpentextCaseManagement/Case/operations\">\r\n
|
|
1168
|
+
<ns0:Case-create xmlns:ns0=\"http://schemas/OpentextCaseManagement/Case\">\r\n
|
|
1169
|
+
<ns0:Subject>{subject}</ns0:Subject>\r\n
|
|
1170
|
+
<ns0:Description>{description}</ns0:Description>\r\n
|
|
1171
|
+
<ns0:LoanAmount>{loan_amount}</ns0:LoanAmount>\r\n
|
|
1172
|
+
<ns0:LoanDurationInMonths>{loan_duration_in_months}</ns0:LoanDurationInMonths>\r\n
|
|
1173
|
+
\r\n
|
|
1174
|
+
<ns0:CaseType>\r\n
|
|
1175
|
+
<ns1:CaseType-id xmlns:ns1=\"http://schemas/OpentextCaseManagement/CaseType\">\r\n
|
|
1176
|
+
<ns1:Id>{service}</ns1:Id>\r\n
|
|
1177
|
+
</ns1:CaseType-id>\r\n
|
|
1178
|
+
</ns0:CaseType>\r\n
|
|
1179
|
+
\r\n
|
|
1180
|
+
<ns0:Category>\r\n
|
|
1181
|
+
<ns2:Category-id xmlns:ns2=\"http://schemas/OpentextCaseManagement/Category\">\r\n
|
|
1182
|
+
<ns2:Id>{category}</ns2:Id>\r\n
|
|
1183
|
+
</ns2:Category-id>\r\n
|
|
1184
|
+
</ns0:Category>\r\n
|
|
1185
|
+
\r\n
|
|
1186
|
+
<ns0:SubCategory>\r\n
|
|
1187
|
+
<ns5:SubCategory-id xmlns:ns5=\"http://schemas/OpentextCaseManagement/Category.SubCategory\">\r\n
|
|
1188
|
+
<ns5:Id>{category}</ns5:Id>\r\n
|
|
1189
|
+
<ns5:Id1>{subcategory}</ns5:Id1>\r\n
|
|
1190
|
+
</ns5:SubCategory-id>\r\n
|
|
1191
|
+
</ns0:SubCategory>\r\n
|
|
1192
|
+
\r\n
|
|
1193
|
+
<ns0:Priority>\r\n
|
|
1194
|
+
<ns3:Priority-id xmlns:ns3=\"http://schemas/OpentextCaseManagement/Priority\">\r\n
|
|
1195
|
+
<ns3:Id>{piority}</ns3:Id>\r\n
|
|
1196
|
+
</ns3:Priority-id>\r\n
|
|
1197
|
+
</ns0:Priority>\r\n
|
|
1198
|
+
\r\n
|
|
1199
|
+
<ns0:ToCustomer>\r\n
|
|
1200
|
+
<ns9:Customer-id xmlns:ns9=\"http://schemas/OpentextCaseManagement/Customer\">\r\n
|
|
1201
|
+
<ns9:Id>{customer}</ns9:Id>\r\n
|
|
1202
|
+
</ns9:Customer-id>\r\n
|
|
1203
|
+
</ns0:ToCustomer>\r\n
|
|
1204
|
+
\r\n
|
|
1205
|
+
</ns0:Case-create>\r\n
|
|
1206
|
+
</CreateCase>\r\n
|
|
1207
|
+
</SOAP:Body>\r\n
|
|
1208
|
+
</SOAP:Envelope>"""
|
|
1209
|
+
|
|
1210
|
+
retries = 0
|
|
1211
|
+
while True:
|
|
1212
|
+
response = requests.post(
|
|
1213
|
+
url=self.gateway_url(),
|
|
1214
|
+
data=create_loan,
|
|
1215
|
+
headers=REQUEST_HEADERS,
|
|
1216
|
+
cookies=self.cookie(),
|
|
1217
|
+
timeout=None,
|
|
1218
|
+
)
|
|
1219
|
+
if response.ok:
|
|
1220
|
+
logger.info("Loan created successfully")
|
|
1221
|
+
return self.parse_xml(response.text)
|
|
1222
|
+
if response.status_code == 401 and retries == 0:
|
|
1223
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
1224
|
+
self.authenticate(revalidate=True)
|
|
1225
|
+
retries += 1
|
|
1226
|
+
logger.error(response.text)
|
|
1227
|
+
return None
|
|
1228
|
+
|
|
1229
|
+
# end method definition
|
|
1230
|
+
|
|
1231
|
+
def get_all_loan(
|
|
1232
|
+
self
|
|
1233
|
+
) -> dict | None:
|
|
1234
|
+
"""get all loan entity instances
|
|
1235
|
+
|
|
1236
|
+
Args:
|
|
1237
|
+
None
|
|
1238
|
+
Returns:
|
|
1239
|
+
dict: Request response (dictionary) or None if the REST call fails
|
|
1240
|
+
"""
|
|
1241
|
+
|
|
1242
|
+
retries = 0
|
|
1243
|
+
while True:
|
|
1244
|
+
response = requests.get(
|
|
1245
|
+
url=self.get_all_loans_url(),
|
|
1246
|
+
headers=REQUEST_HEADERS_JSON,
|
|
1247
|
+
cookies=self.cookie(),
|
|
1248
|
+
timeout=None,
|
|
1249
|
+
)
|
|
1250
|
+
if response.ok:
|
|
1251
|
+
authenticate_dict = self.parse_request_response(
|
|
1252
|
+
response, "This can be normal during restart", False
|
|
1253
|
+
)
|
|
1254
|
+
if not authenticate_dict:
|
|
1255
|
+
return None
|
|
1256
|
+
return authenticate_dict
|
|
1257
|
+
if response.status_code == 401 and retries == 0:
|
|
1258
|
+
logger.warning("Session has expired - try to re-authenticate...")
|
|
1259
|
+
self.authenticate(revalidate=True)
|
|
1260
|
+
retries += 1
|
|
1261
|
+
else:
|
|
1262
|
+
logger.error(response.text)
|
|
1263
|
+
return None
|
|
1264
|
+
|
|
1265
|
+
# end method definition
|
|
1266
|
+
|
|
1267
|
+
def validate_workspace_response(
|
|
1268
|
+
self,
|
|
1269
|
+
response: str,
|
|
1270
|
+
workspace_name: str
|
|
1271
|
+
) -> bool:
|
|
1272
|
+
"""
|
|
1273
|
+
Verify if the workspace exists or was created successfully.
|
|
1274
|
+
|
|
1275
|
+
Args:
|
|
1276
|
+
response (str): response to validate
|
|
1277
|
+
workspace_name (str): The name of the workspace.
|
|
1278
|
+
|
|
1279
|
+
Returns:
|
|
1280
|
+
bool: True if the workspace exists or was created successfully, else False.
|
|
1281
|
+
"""
|
|
1282
|
+
|
|
1283
|
+
if "Object already exists" in response or "createWorkspaceResponse" in response:
|
|
1284
|
+
logger.info(
|
|
1285
|
+
"The workspace already exists or was created with the name -> '%s'",
|
|
1286
|
+
workspace_name,
|
|
1287
|
+
)
|
|
1288
|
+
return True
|
|
1289
|
+
|
|
1290
|
+
logger.info(
|
|
1291
|
+
"The workspace -> '%s' does not exist or was not created. Please verify configurtion!",
|
|
1292
|
+
workspace_name,
|
|
1293
|
+
)
|
|
1294
|
+
return False
|
|
1295
|
+
|
|
1296
|
+
# end method definition
|
|
1297
|
+
|
|
1298
|
+
def is_workspace_already_exists(
|
|
1299
|
+
self,
|
|
1300
|
+
response: str,
|
|
1301
|
+
workspace_name: str
|
|
1302
|
+
) -> bool:
|
|
1303
|
+
"""verify is workspace exists
|
|
1304
|
+
Args:
|
|
1305
|
+
workspace_name (str): workspace_name
|
|
1306
|
+
Returns:
|
|
1307
|
+
bool: return true if workspace exist else return false
|
|
1308
|
+
"""
|
|
1309
|
+
|
|
1310
|
+
if "Object already exists" in response:
|
|
1311
|
+
logger.info(
|
|
1312
|
+
"The workspace already exists with the name -> '%s'", workspace_name
|
|
1313
|
+
)
|
|
1314
|
+
return True
|
|
1315
|
+
logger.info(
|
|
1316
|
+
"The Workspace has been created with the name -> '%s'", workspace_name
|
|
1317
|
+
)
|
|
1318
|
+
return False
|
|
1319
|
+
|
|
1320
|
+
# end method definition
|
|
1321
|
+
|
|
1322
|
+
def create_workspace_with_retry(self, workspace_name: str, workspace_gui_id: str) -> dict | None:
|
|
1323
|
+
"""
|
|
1324
|
+
Calls create_workspace and retries if the response contains specific error messages.
|
|
1325
|
+
Retries until the response does not contain the errors or a max retry limit is reached.
|
|
1326
|
+
"""
|
|
1327
|
+
|
|
1328
|
+
max_retries = 20 # Define the maximum number of retries
|
|
1329
|
+
retries = 0
|
|
1330
|
+
error_messages = [
|
|
1331
|
+
"Collaborative Workspace Service Container is not able to handle the SOAP request",
|
|
1332
|
+
"Service Group Lookup failure"
|
|
1333
|
+
]
|
|
1334
|
+
|
|
1335
|
+
while retries < max_retries:
|
|
1336
|
+
response = self.create_workspace(workspace_name, workspace_gui_id)
|
|
1337
|
+
|
|
1338
|
+
# Check if any error message is in the response
|
|
1339
|
+
if any(error_message in response for error_message in error_messages):
|
|
1340
|
+
logger.info("Workspace service error, waiting 60 seconds to retry... (Retry %d of %d)", retries + 1, max_retries)
|
|
1341
|
+
time.sleep(60)
|
|
1342
|
+
retries += 1
|
|
1343
|
+
else:
|
|
1344
|
+
logger.info("Collaborative Workspace Service Container is ready")
|
|
1345
|
+
return response
|
|
1346
|
+
|
|
1347
|
+
# After max retries, log and return the response or handle as needed
|
|
1348
|
+
logger.error(
|
|
1349
|
+
"Max retries reached for workspace -> '%s', unable to create successfully.",
|
|
1350
|
+
workspace_name,
|
|
1351
|
+
)
|
|
1352
|
+
return response
|
|
1353
|
+
|
|
1354
|
+
# end method definition
|
|
1355
|
+
|
|
1356
|
+
def loan_management_runtime(self) -> dict | None:
|
|
1357
|
+
"""it will create all runtime objects for loan management application
|
|
1358
|
+
Args:
|
|
1359
|
+
None
|
|
1360
|
+
Returns:
|
|
1361
|
+
None
|
|
1362
|
+
"""
|
|
1363
|
+
|
|
1364
|
+
logger.debug(" RUNTIME -->> Category instance creation started ........ ")
|
|
1365
|
+
category_resp_dict = []
|
|
1366
|
+
if not self.verify_category_exists("Short Term Loan"):
|
|
1367
|
+
self.create_category("LOAN","Short Term Loan","Short Term Loan",1)
|
|
1368
|
+
if not self.verify_category_exists("Long Term Loan"):
|
|
1369
|
+
self.create_category("LOAN","Long Term Loan","Long Term Loan",1)
|
|
1370
|
+
if not self.verify_category_exists("Flexi Loan"):
|
|
1371
|
+
self.create_category("LOAN","Flexi Loan","Flexi Loan",1)
|
|
1372
|
+
category_resp_dict = self.get_category_lists()
|
|
1373
|
+
logger.debug(" RUNTIME -->> Category instance creation ended")
|
|
1374
|
+
|
|
1375
|
+
############################# Sub category
|
|
1376
|
+
logger.debug(" RUNTIME -->> Sub Category instance creation started ........")
|
|
1377
|
+
stl = 0
|
|
1378
|
+
ltl = 0
|
|
1379
|
+
fl = 0
|
|
1380
|
+
if not self.verify_sub_category_exists("Business",0,category_resp_dict):
|
|
1381
|
+
response_dict = self.create_sub_categoy("Business","Business",1,category_resp_dict[0])
|
|
1382
|
+
stl = response_dict["Identity"]["Id"]
|
|
1383
|
+
logger.info("Sub category id stl: %s ", stl)
|
|
1384
|
+
else:
|
|
1385
|
+
stl = self.return_sub_category_exists_id("Business",0,category_resp_dict)
|
|
1386
|
+
logger.info("Sub category id stl -> %s ", stl)
|
|
1387
|
+
|
|
1388
|
+
if not self.verify_sub_category_exists("Business",1,category_resp_dict):
|
|
1389
|
+
response_dict=self.create_sub_categoy("Business","Business",1,category_resp_dict[1])
|
|
1390
|
+
ltl = response_dict["Identity"]["Id"]
|
|
1391
|
+
logger.info("Sub category id ltl -> %s ", ltl)
|
|
1392
|
+
else:
|
|
1393
|
+
ltl = self.return_sub_category_exists_id("Business",1,category_resp_dict)
|
|
1394
|
+
logger.info("Sub category id ltl -> %s ", ltl)
|
|
1395
|
+
if not self.verify_sub_category_exists("Business",2,category_resp_dict):
|
|
1396
|
+
response_dict= self.create_sub_categoy("Business","Business",1,category_resp_dict[2])
|
|
1397
|
+
fl = response_dict["Identity"]["Id"]
|
|
1398
|
+
logger.info("Sub category id fl -> %s ", fl)
|
|
1399
|
+
else:
|
|
1400
|
+
fl = self.return_sub_category_exists_id("Business",2,category_resp_dict)
|
|
1401
|
+
logger.info("Sub category id fl -> %s ", fl)
|
|
1402
|
+
logger.debug(" RUNTIME -->> Sub Category instance creation ended")
|
|
1403
|
+
|
|
1404
|
+
############################# Case Types
|
|
1405
|
+
logger.debug(" RUNTIME -->> Case Types instance creation started ........")
|
|
1406
|
+
case_type_list = []
|
|
1407
|
+
|
|
1408
|
+
if not self.vverify_case_type_exists("Query"):
|
|
1409
|
+
self.create_case_type("Query","Query",1)
|
|
1410
|
+
if not self.vverify_case_type_exists("Help"):
|
|
1411
|
+
self.create_case_type("Help","Help",1)
|
|
1412
|
+
if not self.vverify_case_type_exists("Update Contact Details"):
|
|
1413
|
+
self.create_case_type("Update Contact Details","Update Contact Details",1)
|
|
1414
|
+
if not self.vverify_case_type_exists("New Loan Request"):
|
|
1415
|
+
self.create_case_type("New Loan Request","New Loan Request",1)
|
|
1416
|
+
if not self.vverify_case_type_exists("Loan Closure"):
|
|
1417
|
+
self.create_case_type("Loan Closure","Loan Closure",1)
|
|
1418
|
+
case_type_list = self.get_case_type_lists()
|
|
1419
|
+
logger.debug(" RUNTIME -->> Case Types instance creation ended")
|
|
1420
|
+
|
|
1421
|
+
############################# CUSTMOR
|
|
1422
|
+
logger.debug(" RUNTIME -->> Customer instance creation stated ........")
|
|
1423
|
+
customer_list = []
|
|
1424
|
+
if not self.verify_customer_exists("InaPlex Limited"):
|
|
1425
|
+
self.create_customer("InaPlex Limited","InaPlex Limited","InaPlex Limited")
|
|
1426
|
+
|
|
1427
|
+
if not self.verify_customer_exists("Interwoven, Inc"):
|
|
1428
|
+
self.create_customer("Interwoven, Inc","Interwoven, Inc","Interwoven, Inc")
|
|
1429
|
+
|
|
1430
|
+
if not self.verify_customer_exists("Jones Lang LaSalle"):
|
|
1431
|
+
self.create_customer("Jones Lang LaSalle","Jones Lang LaSalle","Jones Lang LaSalle")
|
|
1432
|
+
|
|
1433
|
+
if not self.verify_customer_exists("Key Point Consulting"):
|
|
1434
|
+
self.create_customer("Key Point Consulting","Key Point Consulting","Key Point Consulting")
|
|
1435
|
+
|
|
1436
|
+
customer_list = self.get_customer_lists()
|
|
1437
|
+
logger.debug(" RUNTIME -->> Customer instance creation ended")
|
|
1438
|
+
|
|
1439
|
+
######################################## PRIORITY
|
|
1440
|
+
logger.debug(" RUNTIME -->> priority instance creation started ........")
|
|
1441
|
+
prioity_list = []
|
|
1442
|
+
if not self.verify_priority_exists("High"):
|
|
1443
|
+
self.create_priority("High","High",1)
|
|
1444
|
+
if not self.verify_priority_exists("Medium"):
|
|
1445
|
+
self.create_priority("Medium","Medium",1)
|
|
1446
|
+
if not self.verify_priority_exists("Low"):
|
|
1447
|
+
self.create_priority("Low","Low",1)
|
|
1448
|
+
prioity_list = self.get_priority_lists()
|
|
1449
|
+
logger.debug(" RUNTIME -->> priority instance creation ended")
|
|
1450
|
+
|
|
1451
|
+
############################# LOAN
|
|
1452
|
+
loan_for_business = "Loan for Business1"
|
|
1453
|
+
loan_for_corporate_business = "Loan for Corporate Business1"
|
|
1454
|
+
loan_for_business_loan_request = "Loan for Business Loan Request1"
|
|
1455
|
+
|
|
1456
|
+
logger.debug(" RUNTIME -->> loan instance creation started ........")
|
|
1457
|
+
loan_resp_dict = self.get_all_loan()
|
|
1458
|
+
names = [item["Properties"]["Subject"] for item in loan_resp_dict["_embedded"]["AllCasesList"]]
|
|
1459
|
+
if loan_for_business in names:
|
|
1460
|
+
logger.info("Customer record Loan_for_business exists")
|
|
1461
|
+
else:
|
|
1462
|
+
logger.info("Creating customer Record with Loan_for_business ")
|
|
1463
|
+
response_dict = self.create_loan(
|
|
1464
|
+
loan_for_business,
|
|
1465
|
+
loan_for_business,
|
|
1466
|
+
1,
|
|
1467
|
+
2,
|
|
1468
|
+
category_resp_dict[0],
|
|
1469
|
+
stl,
|
|
1470
|
+
prioity_list[0],
|
|
1471
|
+
case_type_list[0],
|
|
1472
|
+
customer_list[0],
|
|
1473
|
+
)
|
|
1474
|
+
|
|
1475
|
+
if loan_for_corporate_business in names:
|
|
1476
|
+
logger.info("Customer record Loan_for_Corporate_Business exists")
|
|
1477
|
+
else:
|
|
1478
|
+
logger.info("Creating customer Record with Loan_for_Corporate_Business ")
|
|
1479
|
+
response_dict = self.create_loan(
|
|
1480
|
+
loan_for_corporate_business,
|
|
1481
|
+
loan_for_corporate_business,
|
|
1482
|
+
1,
|
|
1483
|
+
2,
|
|
1484
|
+
category_resp_dict[1],
|
|
1485
|
+
ltl,
|
|
1486
|
+
prioity_list[1],
|
|
1487
|
+
case_type_list[1],
|
|
1488
|
+
customer_list[1],
|
|
1489
|
+
)
|
|
1490
|
+
|
|
1491
|
+
if loan_for_business_loan_request in names:
|
|
1492
|
+
logger.info("Customer record Loan_for_business_Loan_Request exists")
|
|
1493
|
+
else:
|
|
1494
|
+
logger.info("Creating customer Record with loan_for_business_loan_request")
|
|
1495
|
+
response_dict = self.create_loan(
|
|
1496
|
+
loan_for_business_loan_request,
|
|
1497
|
+
loan_for_business_loan_request,
|
|
1498
|
+
1,
|
|
1499
|
+
2,
|
|
1500
|
+
category_resp_dict[2],
|
|
1501
|
+
fl,
|
|
1502
|
+
prioity_list[2],
|
|
1503
|
+
case_type_list[2],
|
|
1504
|
+
customer_list[2],
|
|
1505
|
+
)
|
|
1506
|
+
logger.debug(" RUNTIME -->> loan instance creation ended")
|
|
1507
|
+
|
|
1508
|
+
# end method definition
|
|
1509
|
+
|
|
1510
|
+
def get_category_lists(self) -> list:
|
|
1511
|
+
"""get All category entty instances id's
|
|
1512
|
+
Args:
|
|
1513
|
+
None
|
|
1514
|
+
Returns:
|
|
1515
|
+
list: list of category IDs
|
|
1516
|
+
"""
|
|
1517
|
+
|
|
1518
|
+
category_resp_dict = []
|
|
1519
|
+
categoy_resp_dict = self.get_all_categories()
|
|
1520
|
+
for item in categoy_resp_dict["_embedded"]["CategoryList"]:
|
|
1521
|
+
first_item_href = item["_links"]["item"]["href"]
|
|
1522
|
+
integer_value = int(re.search(r'\d+', first_item_href).group())
|
|
1523
|
+
logger.info("Category created with ID -> %d", integer_value)
|
|
1524
|
+
category_resp_dict.append(integer_value)
|
|
1525
|
+
logger.info("All extracted category IDs -> %s", category_resp_dict)
|
|
1526
|
+
|
|
1527
|
+
return category_resp_dict
|
|
1528
|
+
|
|
1529
|
+
# end method definition
|
|
1530
|
+
|
|
1531
|
+
def get_case_type_lists(self) -> list:
|
|
1532
|
+
"""Get All CaseType entity instances IDs
|
|
1533
|
+
Args:
|
|
1534
|
+
None
|
|
1535
|
+
Returns:
|
|
1536
|
+
list: list contains CaseType IDs
|
|
1537
|
+
"""
|
|
1538
|
+
|
|
1539
|
+
case_type_list = []
|
|
1540
|
+
casetype_resp_dict = self.get_all_case_type()
|
|
1541
|
+
for item in casetype_resp_dict["_embedded"]["AllCaseTypes"]:
|
|
1542
|
+
first_item_href = item["_links"]["item"]["href"]
|
|
1543
|
+
integer_value = int(re.search(r'\d+', first_item_href).group())
|
|
1544
|
+
logger.info("Case type created with ID -> %d", integer_value)
|
|
1545
|
+
case_type_list.append(integer_value)
|
|
1546
|
+
logger.info("All extracted case type IDs -> %s", case_type_list)
|
|
1547
|
+
|
|
1548
|
+
return case_type_list
|
|
1549
|
+
|
|
1550
|
+
# end method definition
|
|
1551
|
+
|
|
1552
|
+
def get_customer_lists(self) -> list:
|
|
1553
|
+
"""Get all customer entity instances id's
|
|
1554
|
+
Args:
|
|
1555
|
+
None
|
|
1556
|
+
Returns:
|
|
1557
|
+
list: list of customer IDs
|
|
1558
|
+
"""
|
|
1559
|
+
|
|
1560
|
+
customer_list = []
|
|
1561
|
+
customer_resp_dict = self.get_all_customers()
|
|
1562
|
+
for item in customer_resp_dict["_embedded"]["CustomerList"]:
|
|
1563
|
+
first_item_href = item["_links"]["item"]["href"]
|
|
1564
|
+
integer_value = int(re.search(r'\d+', first_item_href).group())
|
|
1565
|
+
logger.info("Customer created with ID -> %d", integer_value)
|
|
1566
|
+
customer_list.append(integer_value)
|
|
1567
|
+
logger.info("All extracted Customer IDs -> %s ", customer_list)
|
|
1568
|
+
return customer_list
|
|
1569
|
+
|
|
1570
|
+
# end method definition
|
|
1571
|
+
|
|
1572
|
+
def get_priority_lists(self) -> list:
|
|
1573
|
+
"""get all priority entity instances IDs
|
|
1574
|
+
Args:
|
|
1575
|
+
None
|
|
1576
|
+
Returns:
|
|
1577
|
+
list: list contains priority IDs
|
|
1578
|
+
"""
|
|
1579
|
+
|
|
1580
|
+
prioity_list = []
|
|
1581
|
+
authenticate_dict = self.get_all_priorities()
|
|
1582
|
+
for item in authenticate_dict["_embedded"]["PriorityList"]:
|
|
1583
|
+
first_item_href = item["_links"]["item"]["href"]
|
|
1584
|
+
integer_value = int(re.search(r'\d+', first_item_href).group())
|
|
1585
|
+
logger.info("Priority created with ID -> %d", integer_value)
|
|
1586
|
+
prioity_list.append(integer_value)
|
|
1587
|
+
logger.info("All extracted priority IDs -> %s ", prioity_list)
|
|
1588
|
+
|
|
1589
|
+
return prioity_list
|
|
1590
|
+
|
|
1591
|
+
# end method definition
|
|
1592
|
+
|
|
1593
|
+
def verify_category_exists(self, name: str) -> bool:
|
|
1594
|
+
"""verify category entity instance already exists
|
|
1595
|
+
Args:
|
|
1596
|
+
name (str): name of the category
|
|
1597
|
+
Returns:
|
|
1598
|
+
bool: returns True if already record exists with same name, else returns False
|
|
1599
|
+
"""
|
|
1600
|
+
|
|
1601
|
+
categoy_resp_dict = self.get_all_categories()
|
|
1602
|
+
names = [item["Properties"]["Name"] for item in categoy_resp_dict["_embedded"]["CategoryList"]]
|
|
1603
|
+
if name in names:
|
|
1604
|
+
logger.info("Category record -> '%s' already exists", name)
|
|
1605
|
+
return True
|
|
1606
|
+
logger.info("Creating category record -> '%s'", name)
|
|
1607
|
+
|
|
1608
|
+
return False
|
|
1609
|
+
|
|
1610
|
+
# end method definition
|
|
1611
|
+
|
|
1612
|
+
def vverify_case_type_exists(self, name: str) -> bool:
|
|
1613
|
+
"""verify case type entity instance already exists
|
|
1614
|
+
Args:
|
|
1615
|
+
name (str): name of the case type
|
|
1616
|
+
Returns:
|
|
1617
|
+
bool: returns True if already record exists with same name, else returns False
|
|
1618
|
+
"""
|
|
1619
|
+
|
|
1620
|
+
casetype_resp_dict = self.get_all_case_type()
|
|
1621
|
+
names = [item["Properties"]["Name"] for item in casetype_resp_dict["_embedded"]["AllCaseTypes"]]
|
|
1622
|
+
if name in names:
|
|
1623
|
+
logger.info("Case type record -> '%s' already exists", name)
|
|
1624
|
+
return True
|
|
1625
|
+
logger.info("Creating case type record -> '%s'", name)
|
|
1626
|
+
|
|
1627
|
+
return False
|
|
1628
|
+
|
|
1629
|
+
# end method definition
|
|
1630
|
+
|
|
1631
|
+
def verify_customer_exists(self, name: str) -> bool:
|
|
1632
|
+
"""verify cusomer entty instance already exists
|
|
1633
|
+
Args:
|
|
1634
|
+
name (str): name of the customer
|
|
1635
|
+
Returns:
|
|
1636
|
+
bool: returns True if already record exists with same name, else returns False
|
|
1637
|
+
"""
|
|
1638
|
+
customer_resp_dict = self.get_all_customers()
|
|
1639
|
+
names = [item["Properties"]["CustomerName"] for item in customer_resp_dict["_embedded"]["CustomerList"]]
|
|
1640
|
+
if name in names:
|
|
1641
|
+
logger.info("Customer -> '%s' already exists", name)
|
|
1642
|
+
return True
|
|
1643
|
+
logger.info("Creating customer -> '%s'", name)
|
|
1644
|
+
return False
|
|
1645
|
+
|
|
1646
|
+
# end method definition
|
|
1647
|
+
|
|
1648
|
+
def verify_priority_exists(self, name: str) -> bool:
|
|
1649
|
+
"""verify piority entity instance already exists
|
|
1650
|
+
Args:
|
|
1651
|
+
name (str): name of the priority
|
|
1652
|
+
Returns:
|
|
1653
|
+
bool: returns True if already record exists with same name, else returns False
|
|
1654
|
+
"""
|
|
1655
|
+
|
|
1656
|
+
authenticate_dict = self.get_all_priorities()
|
|
1657
|
+
names = [item["Properties"]["Name"] for item in authenticate_dict["_embedded"]["PriorityList"]]
|
|
1658
|
+
if name in names:
|
|
1659
|
+
logger.info("Priority -> '%s' already exists", name)
|
|
1660
|
+
return True
|
|
1661
|
+
logger.info("Creating priority -> '%s'", name)
|
|
1662
|
+
|
|
1663
|
+
return False
|
|
1664
|
+
|
|
1665
|
+
# end method definition
|
|
1666
|
+
|
|
1667
|
+
def verify_sub_category_exists(self, name: str, index: int, category_resp_dict: list) -> bool:
|
|
1668
|
+
"""verify sub category entity instance already exists
|
|
1669
|
+
Args:
|
|
1670
|
+
name (str): name of the sub category
|
|
1671
|
+
Returns:
|
|
1672
|
+
bool: returns true if record already exists with same name, else returns false
|
|
1673
|
+
"""
|
|
1674
|
+
|
|
1675
|
+
subcategoy_resp_dict = self.get_all_sub_categeries(category_resp_dict[index])
|
|
1676
|
+
names = [item["Properties"]["Name"] for item in subcategoy_resp_dict["_embedded"]["SubCategory"]]
|
|
1677
|
+
stl=0
|
|
1678
|
+
if name in names:
|
|
1679
|
+
logger.info("Sub category -> '%s' already exists", name)
|
|
1680
|
+
for item in subcategoy_resp_dict["_embedded"]["SubCategory"]:
|
|
1681
|
+
stl = item["Identity"]["Id"]
|
|
1682
|
+
logger.info("Sub category created with ID -> %s", stl)
|
|
1683
|
+
return True
|
|
1684
|
+
logger.info("Creating sub category -> '%s'", name)
|
|
1685
|
+
|
|
1686
|
+
return False
|
|
1687
|
+
|
|
1688
|
+
# end method definition
|
|
1689
|
+
|
|
1690
|
+
def return_sub_category_exists_id(self, name: str, index: int, category_resp_dict: list) -> int:
|
|
1691
|
+
"""verify sub category entity instance id already exists
|
|
1692
|
+
Args:
|
|
1693
|
+
name (str): name of the sub-category
|
|
1694
|
+
Returns:
|
|
1695
|
+
bool: returns true if record already exists with same name, else returns false
|
|
1696
|
+
"""
|
|
1697
|
+
|
|
1698
|
+
subcategoy_resp_dict = self.get_all_sub_categeries(category_resp_dict[index])
|
|
1699
|
+
names = [item["Properties"]["Name"] for item in subcategoy_resp_dict["_embedded"]["SubCategory"]]
|
|
1700
|
+
stl=0
|
|
1701
|
+
if name in names:
|
|
1702
|
+
logger.info("Sub category record -> '%s' already exists", name)
|
|
1703
|
+
for item in subcategoy_resp_dict["_embedded"]["SubCategory"]:
|
|
1704
|
+
stl = item["Identity"]["Id"]
|
|
1705
|
+
logger.info("Sub category created with ID -> %s", stl)
|
|
1706
|
+
return stl
|
|
1707
|
+
|
|
1708
|
+
return None
|
|
1709
|
+
|
|
1710
|
+
# end method definition
|
|
1711
|
+
|
|
1712
|
+
def create_users_from_config_file(self, otawpsection: str, _otds: OTDS):
|
|
1713
|
+
"""read user information from customizer file and call create user method
|
|
1714
|
+
Args:
|
|
1715
|
+
otawpsection (str): yaml bock related to appworks
|
|
1716
|
+
Returns:
|
|
1717
|
+
None
|
|
1718
|
+
"""
|
|
1719
|
+
|
|
1720
|
+
otds = otawpsection.get("otds", {})
|
|
1721
|
+
if otds is not None:
|
|
1722
|
+
users = otds.get("users", [])
|
|
1723
|
+
if users is not None:
|
|
1724
|
+
for user in users:
|
|
1725
|
+
_otds.add_user(
|
|
1726
|
+
user.get("partition"),
|
|
1727
|
+
user.get("name"),
|
|
1728
|
+
user.get("description"),
|
|
1729
|
+
user.get("first_name"),
|
|
1730
|
+
user.get("last_name"),
|
|
1731
|
+
user.get("email"),
|
|
1732
|
+
)
|
|
1733
|
+
roles = otds.get("roles", [])
|
|
1734
|
+
if roles is not None:
|
|
1735
|
+
for role in roles:
|
|
1736
|
+
_otds.add_user_to_group(
|
|
1737
|
+
user.get("name") + "@" + user.get("partition"),
|
|
1738
|
+
# user.get('name'),
|
|
1739
|
+
role.get("name"),
|
|
1740
|
+
)
|
|
1741
|
+
else:
|
|
1742
|
+
logger.error(
|
|
1743
|
+
"Verifying Users section: roles section not presented in yaml for otds users"
|
|
1744
|
+
)
|
|
1745
|
+
else:
|
|
1746
|
+
logger.error(
|
|
1747
|
+
"Verifying Users section: user section not presented in yaml"
|
|
1748
|
+
)
|
|
1749
|
+
else:
|
|
1750
|
+
logger.error("Verifying Users section: otds section not presented in yaml")
|
|
1751
|
+
|
|
1752
|
+
# end method definition
|
|
1753
|
+
|
|
1754
|
+
def create_roles_from_config_file(self, otawpsection: str, _otds: OTDS):
|
|
1755
|
+
"""read grop information from customizer file and call create grop method
|
|
1756
|
+
Args:
|
|
1757
|
+
otawpsection (str): yaml bock related to appworks
|
|
1758
|
+
_otds (object): the OTDS object used to access the OTDS REST API
|
|
1759
|
+
Returns:
|
|
1760
|
+
None
|
|
1761
|
+
"""
|
|
1762
|
+
|
|
1763
|
+
otds = otawpsection.get("otds", {})
|
|
1764
|
+
if otds is not None:
|
|
1765
|
+
roles = otds.get("roles", [])
|
|
1766
|
+
if roles is not None:
|
|
1767
|
+
for role in roles:
|
|
1768
|
+
# Add new group if it does not yet exist:
|
|
1769
|
+
if not _otds.get_group(group=role.get("name"), show_error=False):
|
|
1770
|
+
_otds.add_group(
|
|
1771
|
+
role.get("partition"),
|
|
1772
|
+
role.get("name"),
|
|
1773
|
+
role.get("description"),
|
|
1774
|
+
)
|
|
1775
|
+
else:
|
|
1776
|
+
logger.error(
|
|
1777
|
+
"Verifying roles section: roles section not presented in yaml"
|
|
1778
|
+
)
|
|
1779
|
+
else:
|
|
1780
|
+
logger.error("Verifying roles section: otds section not presented in yaml")
|
|
1781
|
+
|
|
1782
|
+
# end method definition
|
|
1783
|
+
|
|
1784
|
+
def create_loanruntime_from_config_file(self, platform: str):
|
|
1785
|
+
"""verify flag and call loan_management_runtime()
|
|
1786
|
+
Args:
|
|
1787
|
+
platform (str): yaml bock related to platform
|
|
1788
|
+
Returns:
|
|
1789
|
+
None
|
|
1790
|
+
"""
|
|
1791
|
+
|
|
1792
|
+
runtime = platform.get("runtime", {})
|
|
1793
|
+
if runtime is not None:
|
|
1794
|
+
app_names = runtime.get("appNames", [])
|
|
1795
|
+
if app_names is not None:
|
|
1796
|
+
for app_name in app_names:
|
|
1797
|
+
if app_name == "loanManagement":
|
|
1798
|
+
self.loan_management_runtime()
|
|
1799
|
+
else:
|
|
1800
|
+
logger.error(
|
|
1801
|
+
"Verifying runtime section: loanManagement not exits in yaml entry"
|
|
1802
|
+
)
|
|
1803
|
+
else:
|
|
1804
|
+
logger.error(
|
|
1805
|
+
"Verifying runtime section: App name section is empty in yaml"
|
|
1806
|
+
)
|
|
1807
|
+
else:
|
|
1808
|
+
logger.error("Verifying runtime section: Runtime section is empty in yaml")
|
|
1809
|
+
|
|
1810
|
+
# end method definition
|