pyxecm 1.5__py3-none-any.whl → 2.0.0__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 +6 -2
- pyxecm/avts.py +1492 -0
- pyxecm/coreshare.py +1075 -960
- pyxecm/customizer/__init__.py +16 -4
- pyxecm/customizer/__main__.py +58 -0
- pyxecm/customizer/api/__init__.py +5 -0
- pyxecm/customizer/api/__main__.py +6 -0
- pyxecm/customizer/api/app.py +914 -0
- pyxecm/customizer/api/auth.py +154 -0
- pyxecm/customizer/api/metrics.py +92 -0
- pyxecm/customizer/api/models.py +13 -0
- pyxecm/customizer/api/payload_list.py +865 -0
- pyxecm/customizer/api/settings.py +103 -0
- pyxecm/customizer/browser_automation.py +332 -139
- pyxecm/customizer/customizer.py +1075 -1057
- pyxecm/customizer/exceptions.py +35 -0
- pyxecm/customizer/guidewire.py +322 -0
- pyxecm/customizer/k8s.py +787 -338
- pyxecm/customizer/log.py +107 -0
- pyxecm/customizer/m365.py +3424 -2270
- pyxecm/customizer/nhc.py +1169 -0
- pyxecm/customizer/openapi.py +258 -0
- pyxecm/customizer/payload.py +18201 -7030
- pyxecm/customizer/pht.py +1047 -210
- pyxecm/customizer/salesforce.py +836 -727
- pyxecm/customizer/sap.py +58 -41
- pyxecm/customizer/servicenow.py +851 -383
- pyxecm/customizer/settings.py +442 -0
- pyxecm/customizer/successfactors.py +408 -346
- pyxecm/customizer/translate.py +83 -48
- pyxecm/helper/__init__.py +5 -2
- pyxecm/helper/assoc.py +98 -38
- pyxecm/helper/data.py +2482 -742
- pyxecm/helper/logadapter.py +27 -0
- pyxecm/helper/web.py +229 -101
- pyxecm/helper/xml.py +528 -172
- pyxecm/maintenance_page/__init__.py +5 -0
- pyxecm/maintenance_page/__main__.py +6 -0
- pyxecm/maintenance_page/app.py +51 -0
- pyxecm/maintenance_page/settings.py +28 -0
- pyxecm/maintenance_page/static/favicon.avif +0 -0
- pyxecm/maintenance_page/templates/maintenance.html +165 -0
- pyxecm/otac.py +234 -140
- pyxecm/otawp.py +2689 -0
- pyxecm/otcs.py +12344 -7547
- pyxecm/otds.py +3166 -2219
- pyxecm/otiv.py +36 -21
- pyxecm/otmm.py +1363 -296
- pyxecm/otpd.py +231 -127
- pyxecm-2.0.0.dist-info/METADATA +145 -0
- pyxecm-2.0.0.dist-info/RECORD +54 -0
- {pyxecm-1.5.dist-info → pyxecm-2.0.0.dist-info}/WHEEL +1 -1
- pyxecm-1.5.dist-info/METADATA +0 -51
- pyxecm-1.5.dist-info/RECORD +0 -30
- {pyxecm-1.5.dist-info → pyxecm-2.0.0.dist-info/licenses}/LICENSE +0 -0
- {pyxecm-1.5.dist-info → pyxecm-2.0.0.dist-info}/top_level.txt +0 -0
pyxecm/otpd.py
CHANGED
|
@@ -1,43 +1,22 @@
|
|
|
1
|
-
"""
|
|
2
|
-
OTPD Module to implement functions to read / write PowerDocs objects
|
|
3
|
-
|
|
4
|
-
Class: OTPD
|
|
5
|
-
Methods:
|
|
6
|
-
|
|
7
|
-
__init__ : class initializer
|
|
8
|
-
config : returns config data set
|
|
9
|
-
credentials: Get credentials (username and password)
|
|
10
|
-
set_credentials: Set new credentials
|
|
11
|
-
hostname: Get the configured PowerDocs hostname
|
|
12
|
-
set_hostname: Set the hostname of PowerDocs
|
|
13
|
-
base_url : Get PowerDocs base URL
|
|
14
|
-
rest_url : Get PowerDocs REST base URL
|
|
15
|
-
|
|
16
|
-
parse_request_response: Converts the text property of a request
|
|
17
|
-
response object to a Python dict in a safe way
|
|
18
|
-
|
|
19
|
-
authenticate : Authenticates at PowerDocs and retrieve OTCS Ticket.
|
|
20
|
-
|
|
21
|
-
import_database: imports the PowerDocs database from a zip file
|
|
22
|
-
apply_setting: apply a setting to a PowerDocs tenant
|
|
23
|
-
|
|
24
|
-
"""
|
|
1
|
+
"""OTPD Module to implement functions to read / write PowerDocs objects."""
|
|
25
2
|
|
|
26
3
|
__author__ = "Dr. Marc Diefenbruch"
|
|
27
|
-
__copyright__ = "Copyright 2024, OpenText"
|
|
4
|
+
__copyright__ = "Copyright (C) 2024-2025, OpenText"
|
|
28
5
|
__credits__ = ["Kai-Philip Gatzweiler"]
|
|
29
6
|
__maintainer__ = "Dr. Marc Diefenbruch"
|
|
30
7
|
__email__ = "mdiefenb@opentext.com"
|
|
31
8
|
|
|
32
9
|
import json
|
|
33
10
|
import logging
|
|
11
|
+
import os
|
|
12
|
+
|
|
34
13
|
import requests
|
|
35
14
|
from requests.auth import HTTPBasicAuth
|
|
36
15
|
from requests_toolbelt.multipart.encoder import MultipartEncoder
|
|
37
16
|
|
|
38
|
-
|
|
17
|
+
default_logger = logging.getLogger("pyxecm.otpd")
|
|
39
18
|
|
|
40
|
-
|
|
19
|
+
request_headers = {
|
|
41
20
|
"accept": "application/json;charset=utf-8",
|
|
42
21
|
"Connection": "keep-alive",
|
|
43
22
|
"Content-Type": "application/json",
|
|
@@ -45,7 +24,9 @@ requestHeaders = {
|
|
|
45
24
|
|
|
46
25
|
|
|
47
26
|
class OTPD:
|
|
48
|
-
"""
|
|
27
|
+
"""Class OTPD is used to automate stettings in OpenText Extended ECM PowerDocs."""
|
|
28
|
+
|
|
29
|
+
logger: logging.Logger = default_logger
|
|
49
30
|
|
|
50
31
|
_config = None
|
|
51
32
|
_jsessionid = None
|
|
@@ -57,17 +38,31 @@ class OTPD:
|
|
|
57
38
|
port: int,
|
|
58
39
|
username: str,
|
|
59
40
|
password: str,
|
|
60
|
-
|
|
61
|
-
|
|
41
|
+
logger: logging.Logger = default_logger,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""Initialize the OTPD object.
|
|
62
44
|
|
|
63
45
|
Args:
|
|
64
|
-
protocol (str):
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
46
|
+
protocol (str):
|
|
47
|
+
Either http or https.
|
|
48
|
+
hostname (str):
|
|
49
|
+
The hostname of the PowerDocs Server Manager to communicate with.
|
|
50
|
+
port (int):
|
|
51
|
+
The port number used to talk to the PowerDocs Server Manager.
|
|
52
|
+
username (str):
|
|
53
|
+
The admin user name of PowerDocs Server Manager.
|
|
54
|
+
password (str):
|
|
55
|
+
The admin password of PowerDocs Server Manager.
|
|
56
|
+
logger (logging.logger):
|
|
57
|
+
The logger object to use. Defaults to "default_logger".
|
|
58
|
+
|
|
69
59
|
"""
|
|
70
60
|
|
|
61
|
+
if logger != default_logger:
|
|
62
|
+
self.logger = logger.getChild("otpd")
|
|
63
|
+
for logfilter in logger.filters:
|
|
64
|
+
self.logger.addFilter(logfilter)
|
|
65
|
+
|
|
71
66
|
otpd_config = {}
|
|
72
67
|
|
|
73
68
|
if hostname:
|
|
@@ -110,82 +105,121 @@ class OTPD:
|
|
|
110
105
|
|
|
111
106
|
self._config = otpd_config
|
|
112
107
|
|
|
108
|
+
# end method definition
|
|
109
|
+
|
|
113
110
|
def config(self) -> dict:
|
|
114
|
-
"""
|
|
111
|
+
"""Return the configuration dictionary.
|
|
115
112
|
|
|
116
113
|
Returns:
|
|
117
114
|
dict: Configuration dictionary
|
|
115
|
+
|
|
118
116
|
"""
|
|
117
|
+
|
|
119
118
|
return self._config
|
|
120
119
|
|
|
120
|
+
# end method definition
|
|
121
|
+
|
|
121
122
|
def credentials(self) -> dict:
|
|
122
|
-
"""Get credentials (username + password)
|
|
123
|
+
"""Get credentials (username + password).
|
|
123
124
|
|
|
124
125
|
Returns:
|
|
125
126
|
dict: dictionary with username and password
|
|
127
|
+
|
|
126
128
|
"""
|
|
127
129
|
return {
|
|
128
130
|
"username": self.config()["username"],
|
|
129
131
|
"password": self.config()["password"],
|
|
130
132
|
}
|
|
131
133
|
|
|
132
|
-
|
|
134
|
+
# end method definition
|
|
135
|
+
|
|
136
|
+
def set_credentials(self, username: str = "admin", password: str = "") -> None:
|
|
133
137
|
"""Set the credentials for PowerDocs for the based on user name and password.
|
|
134
138
|
|
|
135
139
|
Args:
|
|
136
|
-
username (str, optional):
|
|
137
|
-
|
|
140
|
+
username (str, optional):
|
|
141
|
+
The username. Defaults to "admin".
|
|
142
|
+
password (str, optional):
|
|
143
|
+
The password of the user. Defaults to "".
|
|
144
|
+
|
|
138
145
|
"""
|
|
146
|
+
|
|
139
147
|
self.config()["username"] = username
|
|
140
148
|
self.config()["password"] = password
|
|
141
149
|
|
|
150
|
+
# end method definition
|
|
151
|
+
|
|
142
152
|
def hostname(self) -> str:
|
|
143
|
-
"""
|
|
153
|
+
"""Return the hostname of PowerDocs (e.g. "otpd").
|
|
144
154
|
|
|
145
155
|
Returns:
|
|
146
156
|
string: hostname
|
|
157
|
+
|
|
147
158
|
"""
|
|
159
|
+
|
|
148
160
|
return self.config()["hostname"]
|
|
149
161
|
|
|
150
|
-
|
|
151
|
-
|
|
162
|
+
# end method definition
|
|
163
|
+
|
|
164
|
+
def set_hostname(self, hostname: str) -> None:
|
|
165
|
+
"""Set the hostname of PowerDocs.
|
|
152
166
|
|
|
153
167
|
Args:
|
|
154
|
-
hostname (str):
|
|
168
|
+
hostname (str):
|
|
169
|
+
The new hostname.
|
|
170
|
+
|
|
155
171
|
"""
|
|
172
|
+
|
|
156
173
|
self.config()["hostname"] = hostname
|
|
157
174
|
|
|
158
|
-
|
|
159
|
-
|
|
175
|
+
# end method definition
|
|
176
|
+
|
|
177
|
+
def base_url(self) -> str:
|
|
178
|
+
"""Return the base URL of PowerDocs.
|
|
160
179
|
|
|
161
180
|
Returns:
|
|
162
|
-
string:
|
|
181
|
+
string:
|
|
182
|
+
The base URL.
|
|
183
|
+
|
|
163
184
|
"""
|
|
185
|
+
|
|
164
186
|
return self.config()["baseUrl"]
|
|
165
187
|
|
|
166
|
-
|
|
167
|
-
|
|
188
|
+
# end method definition
|
|
189
|
+
|
|
190
|
+
def rest_url(self) -> str:
|
|
191
|
+
"""Return the REST URL of PowerDocs.
|
|
168
192
|
|
|
169
193
|
Returns:
|
|
170
|
-
string:
|
|
194
|
+
string:
|
|
195
|
+
The REST URL.
|
|
196
|
+
|
|
171
197
|
"""
|
|
198
|
+
|
|
172
199
|
return self.config()["restUrl"]
|
|
173
200
|
|
|
201
|
+
# end method definition
|
|
202
|
+
|
|
174
203
|
def parse_request_response(
|
|
175
204
|
self,
|
|
176
205
|
response_object: object,
|
|
177
206
|
additional_error_message: str = "",
|
|
178
207
|
show_error: bool = True,
|
|
179
208
|
) -> dict | None:
|
|
180
|
-
"""
|
|
181
|
-
that also handles exceptions.
|
|
209
|
+
"""Convert the request response to a dict in a safe way that handles exceptions.
|
|
182
210
|
|
|
183
211
|
Args:
|
|
184
|
-
response_object (object):
|
|
185
|
-
|
|
186
|
-
|
|
212
|
+
response_object (object):
|
|
213
|
+
Reponse object delivered by the request call.
|
|
214
|
+
additional_error_message (str, optional):
|
|
215
|
+
If provided, print a custom error message.
|
|
216
|
+
show_error (bool, optional):
|
|
217
|
+
If True, log an error, if False log a warning.
|
|
218
|
+
|
|
187
219
|
Returns:
|
|
188
|
-
dict
|
|
220
|
+
dict | None:
|
|
221
|
+
A python dict object or None in case of an error.
|
|
222
|
+
|
|
189
223
|
"""
|
|
190
224
|
|
|
191
225
|
if not response_object:
|
|
@@ -196,16 +230,17 @@ class OTPD:
|
|
|
196
230
|
except json.JSONDecodeError as exception:
|
|
197
231
|
if additional_error_message:
|
|
198
232
|
message = "Cannot decode response as JSon. {}; error -> {}".format(
|
|
199
|
-
additional_error_message,
|
|
233
|
+
additional_error_message,
|
|
234
|
+
exception,
|
|
200
235
|
)
|
|
201
236
|
else:
|
|
202
237
|
message = "Cannot decode response as JSon; error -> {}".format(
|
|
203
|
-
exception
|
|
238
|
+
exception,
|
|
204
239
|
)
|
|
205
240
|
if show_error:
|
|
206
|
-
logger.error(message)
|
|
241
|
+
self.logger.error(message)
|
|
207
242
|
else:
|
|
208
|
-
logger.warning(message)
|
|
243
|
+
self.logger.warning(message)
|
|
209
244
|
return None
|
|
210
245
|
else:
|
|
211
246
|
return dict_object
|
|
@@ -216,14 +251,18 @@ class OTPD:
|
|
|
216
251
|
# It cannot handle the Request - ServerManager returns an
|
|
217
252
|
# error stating that JavaScript is not enabled...
|
|
218
253
|
def authenticate(self, revalidate: bool = False) -> dict:
|
|
219
|
-
"""
|
|
254
|
+
"""Authenticate at PowerDocs and retrieve session ID.
|
|
220
255
|
|
|
221
256
|
Args:
|
|
222
|
-
revalidate (bool):
|
|
223
|
-
|
|
257
|
+
revalidate (bool):
|
|
258
|
+
Determine, if a re-athentication is enforced
|
|
259
|
+
(e.g. if session has timed out with 401 error).
|
|
260
|
+
|
|
224
261
|
Returns:
|
|
225
|
-
dict:
|
|
226
|
-
|
|
262
|
+
dict:
|
|
263
|
+
Cookie information of None in case of an error.
|
|
264
|
+
Also stores cookie information in self._cookie
|
|
265
|
+
|
|
227
266
|
"""
|
|
228
267
|
|
|
229
268
|
# Already authenticated and session still valid?
|
|
@@ -243,108 +282,172 @@ class OTPD:
|
|
|
243
282
|
|
|
244
283
|
request_url = self.config()["settingsUrl"]
|
|
245
284
|
|
|
246
|
-
|
|
285
|
+
# Fetching session id will be three step process:
|
|
247
286
|
# Step1: intiate a dummy request to tomcat
|
|
248
|
-
# Step2: fetch session id from the response,
|
|
249
|
-
#
|
|
287
|
+
# Step2: fetch session id from the response,
|
|
288
|
+
# and hit j_security_check with proper authentication
|
|
289
|
+
# Step3: get session id from the response, add to self.
|
|
290
|
+
# It can be used for other transactions
|
|
250
291
|
session = requests.Session()
|
|
251
|
-
logger.debug(
|
|
292
|
+
self.logger.debug(
|
|
293
|
+
"Initiating dummy rest call to Tomcat to get initial session ID.",
|
|
294
|
+
)
|
|
252
295
|
response = session.put(request_url, json=payload)
|
|
253
|
-
logger.info(response.text)
|
|
296
|
+
self.logger.info(response.text)
|
|
254
297
|
if response.ok:
|
|
255
|
-
logger.debug(
|
|
298
|
+
self.logger.debug(
|
|
299
|
+
"Url to authenticate Tomcat for Session id -> %s",
|
|
300
|
+
auth_url,
|
|
301
|
+
)
|
|
256
302
|
session_response = session.post(auth_url)
|
|
257
303
|
if session_response.ok:
|
|
258
|
-
logger.debug(
|
|
259
|
-
"Response for -> %s is -> %s",
|
|
304
|
+
self.logger.debug(
|
|
305
|
+
"Response for -> %s is -> %s",
|
|
306
|
+
auth_url,
|
|
307
|
+
str(session_response),
|
|
260
308
|
)
|
|
261
309
|
session_dict = session.cookies.get_dict()
|
|
262
|
-
logger.debug(
|
|
310
|
+
self.logger.debug(
|
|
263
311
|
"Session id to perform Rest API calls to Tomcat -> %s",
|
|
264
312
|
session_dict["JSESSIONID"],
|
|
265
313
|
)
|
|
266
|
-
# store session ID an write it into the global
|
|
314
|
+
# store session ID an write it into the global request_headers variable:
|
|
267
315
|
self._jsessionid = session_dict["JSESSIONID"]
|
|
268
|
-
|
|
316
|
+
request_headers["Cookie"] = "JSESSIONID=" + self._jsessionid
|
|
269
317
|
return session_response
|
|
270
318
|
else:
|
|
271
|
-
logger.error(
|
|
272
|
-
"Fetching session id from -> %s failed
|
|
319
|
+
self.logger.error(
|
|
320
|
+
"Fetching session id from -> %s failed! Response -> %s",
|
|
273
321
|
auth_url,
|
|
274
322
|
session_response.text,
|
|
275
323
|
)
|
|
276
324
|
return None
|
|
277
325
|
else:
|
|
278
|
-
logger.error(
|
|
279
|
-
"Fetching session id from -> %s failed
|
|
326
|
+
self.logger.error(
|
|
327
|
+
"Fetching session id from -> %s failed! Response -> %s",
|
|
280
328
|
request_url,
|
|
281
329
|
response.text,
|
|
282
330
|
)
|
|
283
|
-
|
|
331
|
+
return None
|
|
284
332
|
|
|
285
333
|
# end method definition
|
|
286
334
|
|
|
287
|
-
def import_database(self,
|
|
288
|
-
"""Import PowerDocs database backup from a zip file
|
|
335
|
+
def import_database(self, file_path: str) -> dict | None:
|
|
336
|
+
"""Import PowerDocs database backup from a zip file.
|
|
289
337
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
# fields attribute is set according to the other party's interface description
|
|
294
|
-
m = MultipartEncoder(fields={"name": file, "zipfile": file_tup})
|
|
338
|
+
Args:
|
|
339
|
+
file_path (str):
|
|
340
|
+
The path to the database file to import.
|
|
295
341
|
|
|
296
|
-
|
|
342
|
+
Returns:
|
|
343
|
+
dict | None:
|
|
344
|
+
The request response or None in case of an error.
|
|
297
345
|
|
|
298
|
-
|
|
299
|
-
"Importing PowerDocs database backup -> %s, into PowerDocs ServerManager on -> %s",
|
|
300
|
-
filename,
|
|
301
|
-
request_url,
|
|
302
|
-
)
|
|
303
|
-
response = requests.post(
|
|
304
|
-
request_url, data=m, headers={"content-type": m.content_type}, timeout=60
|
|
305
|
-
)
|
|
346
|
+
"""
|
|
306
347
|
|
|
307
|
-
if
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
"Failed to import PowerDocs database backup -> %s into -> %s; error -> %s",
|
|
312
|
-
filename,
|
|
313
|
-
request_url,
|
|
314
|
-
response.text,
|
|
348
|
+
if not file_path or not os.path.isfile(file_path):
|
|
349
|
+
self.logger.error(
|
|
350
|
+
"Cannot import PowerDocs database from non-existent file -> %s",
|
|
351
|
+
file_path,
|
|
315
352
|
)
|
|
316
353
|
return None
|
|
317
354
|
|
|
355
|
+
try:
|
|
356
|
+
# Extract the filename
|
|
357
|
+
file_name = os.path.basename(file_path)
|
|
358
|
+
|
|
359
|
+
# Open the file safely
|
|
360
|
+
with open(file_path, "rb") as file:
|
|
361
|
+
file_tuple = (file_name, file, "application/zip")
|
|
362
|
+
|
|
363
|
+
# Prepare the multipart encoder
|
|
364
|
+
multipart = MultipartEncoder(
|
|
365
|
+
fields={"name": file_name, "zipfile": file_tuple},
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
# Retrieve the request URL
|
|
369
|
+
request_url = self.config().get("otpdImportDatabaseUrl")
|
|
370
|
+
|
|
371
|
+
if not request_url:
|
|
372
|
+
self.logger.error("Import database URL is not configured.")
|
|
373
|
+
return None
|
|
374
|
+
|
|
375
|
+
self.logger.info(
|
|
376
|
+
"Importing PowerDocs database backup from -> %s; calling -> %s",
|
|
377
|
+
file_path,
|
|
378
|
+
request_url,
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
# Send the request
|
|
382
|
+
response = requests.post(
|
|
383
|
+
url=request_url,
|
|
384
|
+
data=multipart,
|
|
385
|
+
headers={"content-type": multipart.content_type},
|
|
386
|
+
timeout=60,
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
# Handle the response
|
|
390
|
+
if response.ok:
|
|
391
|
+
self.logger.info("Database backup imported successfully.")
|
|
392
|
+
return response.json()
|
|
393
|
+
else:
|
|
394
|
+
self.logger.error(
|
|
395
|
+
"Failed to import PowerDocs database backup from -> %s into -> %s; error -> %s",
|
|
396
|
+
file_path,
|
|
397
|
+
request_url,
|
|
398
|
+
response.text,
|
|
399
|
+
)
|
|
400
|
+
return None
|
|
401
|
+
|
|
402
|
+
except FileNotFoundError:
|
|
403
|
+
self.logger.error("File -> '%s' not found!", file_path)
|
|
404
|
+
except requests.RequestException:
|
|
405
|
+
self.logger.error("HTTP request to -> '%s' failed", request_url)
|
|
406
|
+
except Exception:
|
|
407
|
+
self.logger.error("An unexpected error occurred!")
|
|
408
|
+
|
|
409
|
+
return None
|
|
410
|
+
|
|
318
411
|
# end method definition
|
|
319
412
|
|
|
320
413
|
def apply_setting(
|
|
321
|
-
self,
|
|
414
|
+
self,
|
|
415
|
+
setting_name: str,
|
|
416
|
+
setting_value: str,
|
|
417
|
+
tenant_name: str = "",
|
|
322
418
|
) -> dict | None:
|
|
323
|
-
"""
|
|
419
|
+
"""Apply a setting to the PowerDocs Server Manager.
|
|
324
420
|
|
|
325
421
|
Args:
|
|
326
|
-
setting_name (str):
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
422
|
+
setting_name (str):
|
|
423
|
+
The name of the setting.
|
|
424
|
+
setting_value (str):
|
|
425
|
+
The new value of the setting.
|
|
426
|
+
tenant_name (str):
|
|
427
|
+
The name of the PowerDocs tenant.
|
|
428
|
+
The tenant name is optional as some settings are not tenant-specific!
|
|
429
|
+
|
|
430
|
+
Returns:
|
|
431
|
+
dict | None:
|
|
432
|
+
Request response or None if the REST call fails.
|
|
433
|
+
|
|
331
434
|
"""
|
|
332
435
|
|
|
333
|
-
|
|
436
|
+
settings_put_body = {
|
|
334
437
|
"settingname": setting_name,
|
|
335
438
|
"settingvalue": setting_value,
|
|
336
439
|
}
|
|
337
440
|
|
|
338
441
|
if tenant_name:
|
|
339
|
-
|
|
442
|
+
settings_put_body["tenantName"] = tenant_name
|
|
340
443
|
|
|
341
444
|
request_url = self.config()["settingsUrl"]
|
|
342
445
|
|
|
343
|
-
logger.debug(
|
|
344
|
-
"Update PowerDocs setting -> %s with value -> %s
|
|
446
|
+
self.logger.debug(
|
|
447
|
+
"Update PowerDocs setting -> '%s' with value -> '%s'%s; calling -> %s",
|
|
345
448
|
setting_name,
|
|
346
449
|
setting_value,
|
|
347
|
-
tenant_name,
|
|
450
|
+
" (tenant -> '%s')" if tenant_name else "",
|
|
348
451
|
request_url,
|
|
349
452
|
)
|
|
350
453
|
|
|
@@ -352,27 +455,28 @@ class OTPD:
|
|
|
352
455
|
while True:
|
|
353
456
|
response = requests.put(
|
|
354
457
|
url=request_url,
|
|
355
|
-
json=
|
|
356
|
-
headers=
|
|
458
|
+
json=settings_put_body,
|
|
459
|
+
headers=request_headers,
|
|
357
460
|
auth=HTTPBasicAuth(
|
|
358
|
-
self.config()["username"],
|
|
461
|
+
self.config()["username"],
|
|
462
|
+
self.config()["password"],
|
|
359
463
|
),
|
|
360
|
-
verify=False, # for localhost deployments this will fail
|
|
464
|
+
verify=False, # for localhost deployments this will fail otherwis e# noqa: S501
|
|
361
465
|
timeout=None,
|
|
362
466
|
)
|
|
363
467
|
if response.ok:
|
|
364
468
|
return self.parse_request_response(response)
|
|
365
469
|
# Check if Session has expired - then re-authenticate and try once more
|
|
366
|
-
|
|
367
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
368
|
-
self.authenticate(True)
|
|
470
|
+
if response.status_code == 401 and retries == 0:
|
|
471
|
+
self.logger.debug("Session has expired - try to re-authenticate...")
|
|
472
|
+
self.authenticate(revalidate=True)
|
|
369
473
|
retries += 1
|
|
370
474
|
else:
|
|
371
|
-
logger.error(
|
|
372
|
-
"Failed to update PowerDocs setting -> %s with value -> %s
|
|
475
|
+
self.logger.error(
|
|
476
|
+
"Failed to update PowerDocs setting -> '%s' with value -> '%s'%s; error -> %s",
|
|
373
477
|
setting_name,
|
|
374
478
|
setting_value,
|
|
375
|
-
tenant_name,
|
|
479
|
+
" (tenant -> '%s')" if tenant_name else "",
|
|
376
480
|
response.text,
|
|
377
481
|
)
|
|
378
482
|
return None
|