pyxecm 2.0.4__py3-none-any.whl → 3.0.1__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/coreshare.py +5 -3
- pyxecm/helper/data.py +4 -4
- pyxecm/helper/otel_config.py +26 -0
- pyxecm/helper/web.py +1 -2
- pyxecm/otca.py +1356 -16
- pyxecm/otcs.py +2354 -593
- pyxecm/otds.py +1 -1
- pyxecm/otmm.py +4 -5
- pyxecm/py.typed +0 -0
- pyxecm-3.0.1.dist-info/METADATA +126 -0
- pyxecm-3.0.1.dist-info/RECORD +96 -0
- {pyxecm-2.0.4.dist-info → pyxecm-3.0.1.dist-info}/WHEEL +1 -2
- pyxecm-3.0.1.dist-info/entry_points.txt +4 -0
- {pyxecm/customizer/api → pyxecm_api}/__main__.py +1 -1
- pyxecm_api/agents/__init__.py +7 -0
- pyxecm_api/agents/app.py +13 -0
- pyxecm_api/agents/functions.py +119 -0
- pyxecm_api/agents/models.py +10 -0
- pyxecm_api/agents/otcm_knowledgegraph/functions.py +85 -0
- pyxecm_api/agents/otcm_knowledgegraph/models.py +61 -0
- pyxecm_api/agents/otcm_knowledgegraph/router.py +74 -0
- pyxecm_api/agents/otcm_user_agent/models.py +20 -0
- pyxecm_api/agents/otcm_user_agent/router.py +65 -0
- pyxecm_api/agents/otcm_workspace_agent/models.py +40 -0
- pyxecm_api/agents/otcm_workspace_agent/router.py +200 -0
- pyxecm_api/app.py +221 -0
- {pyxecm/customizer/api → pyxecm_api}/auth/functions.py +10 -2
- {pyxecm/customizer/api → pyxecm_api}/auth/router.py +4 -3
- {pyxecm/customizer/api → pyxecm_api}/common/functions.py +39 -9
- {pyxecm/customizer/api → pyxecm_api}/common/metrics.py +1 -2
- {pyxecm/customizer/api → pyxecm_api}/common/router.py +7 -8
- {pyxecm/customizer/api → pyxecm_api}/settings.py +21 -6
- {pyxecm/customizer/api → pyxecm_api}/terminal/router.py +1 -1
- {pyxecm/customizer/api → pyxecm_api}/v1_csai/router.py +39 -10
- pyxecm_api/v1_csai/statics/bindings/utils.js +189 -0
- pyxecm_api/v1_csai/statics/tom-select/tom-select.complete.min.js +356 -0
- pyxecm_api/v1_csai/statics/tom-select/tom-select.css +334 -0
- pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.css +1 -0
- pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.min.js +27 -0
- pyxecm_api/v1_maintenance/__init__.py +1 -0
- {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/functions.py +3 -3
- {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/router.py +8 -8
- pyxecm_api/v1_otcs/__init__.py +1 -0
- {pyxecm/customizer/api → pyxecm_api}/v1_otcs/functions.py +7 -5
- {pyxecm/customizer/api → pyxecm_api}/v1_otcs/router.py +8 -7
- pyxecm_api/v1_payload/__init__.py +1 -0
- {pyxecm/customizer/api → pyxecm_api}/v1_payload/functions.py +10 -7
- {pyxecm/customizer/api → pyxecm_api}/v1_payload/router.py +11 -10
- {pyxecm/customizer → pyxecm_customizer}/__init__.py +8 -0
- {pyxecm/customizer → pyxecm_customizer}/__main__.py +15 -21
- {pyxecm/customizer → pyxecm_customizer}/browser_automation.py +414 -103
- {pyxecm/customizer → pyxecm_customizer}/customizer.py +178 -116
- {pyxecm/customizer → pyxecm_customizer}/guidewire.py +60 -20
- {pyxecm/customizer → pyxecm_customizer}/k8s.py +4 -4
- pyxecm_customizer/knowledge_graph.py +719 -0
- pyxecm_customizer/log.py +35 -0
- {pyxecm/customizer → pyxecm_customizer}/m365.py +41 -33
- {pyxecm/customizer → pyxecm_customizer}/payload.py +2265 -1933
- {pyxecm/customizer/api/common → pyxecm_customizer}/payload_list.py +18 -55
- {pyxecm/customizer → pyxecm_customizer}/salesforce.py +1 -1
- {pyxecm/customizer → pyxecm_customizer}/sap.py +6 -2
- {pyxecm/customizer → pyxecm_customizer}/servicenow.py +2 -4
- {pyxecm/customizer → pyxecm_customizer}/settings.py +7 -6
- {pyxecm/customizer → pyxecm_customizer}/successfactors.py +40 -28
- {pyxecm/customizer → pyxecm_customizer}/translate.py +1 -1
- {pyxecm/maintenance_page → pyxecm_maintenance_page}/__main__.py +1 -1
- {pyxecm/maintenance_page → pyxecm_maintenance_page}/app.py +14 -8
- pyxecm/customizer/api/app.py +0 -157
- pyxecm/customizer/log.py +0 -107
- pyxecm/customizer/nhc.py +0 -1169
- pyxecm/customizer/openapi.py +0 -258
- pyxecm/customizer/pht.py +0 -1357
- pyxecm-2.0.4.dist-info/METADATA +0 -119
- pyxecm-2.0.4.dist-info/RECORD +0 -78
- pyxecm-2.0.4.dist-info/licenses/LICENSE +0 -202
- pyxecm-2.0.4.dist-info/top_level.txt +0 -1
- {pyxecm/customizer/api → pyxecm_api}/__init__.py +0 -0
- {pyxecm/customizer/api/auth → pyxecm_api/agents/otcm_knowledgegraph}/__init__.py +0 -0
- {pyxecm/customizer/api/common → pyxecm_api/agents/otcm_user_agent}/__init__.py +0 -0
- {pyxecm/customizer/api/v1_csai → pyxecm_api/agents/otcm_workspace_agent}/__init__.py +0 -0
- {pyxecm/customizer/api/v1_maintenance → pyxecm_api/auth}/__init__.py +0 -0
- {pyxecm/customizer/api → pyxecm_api}/auth/models.py +0 -0
- {pyxecm/customizer/api/v1_otcs → pyxecm_api/common}/__init__.py +0 -0
- {pyxecm/customizer/api → pyxecm_api}/common/models.py +0 -0
- {pyxecm/customizer/api → pyxecm_api}/terminal/__init__.py +0 -0
- {pyxecm/customizer/api/v1_payload → pyxecm_api/v1_csai}/__init__.py +0 -0
- {pyxecm/customizer/api → pyxecm_api}/v1_csai/models.py +0 -0
- {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/models.py +0 -0
- {pyxecm/customizer/api → pyxecm_api}/v1_payload/models.py +0 -0
- {pyxecm/customizer → pyxecm_customizer}/exceptions.py +0 -0
- {pyxecm/maintenance_page → pyxecm_maintenance_page}/__init__.py +0 -0
- {pyxecm/maintenance_page → pyxecm_maintenance_page}/settings.py +0 -0
- {pyxecm/maintenance_page → pyxecm_maintenance_page}/static/favicon.avif +0 -0
- {pyxecm/maintenance_page → pyxecm_maintenance_page}/templates/maintenance.html +0 -0
|
@@ -11,21 +11,22 @@ import os
|
|
|
11
11
|
import sys
|
|
12
12
|
import tempfile
|
|
13
13
|
import time
|
|
14
|
-
from datetime import
|
|
14
|
+
from datetime import UTC, datetime
|
|
15
15
|
|
|
16
16
|
import requests
|
|
17
17
|
|
|
18
18
|
# OpenText specific modules:
|
|
19
19
|
import yaml
|
|
20
20
|
from pydantic import HttpUrl
|
|
21
|
-
|
|
22
21
|
from pyxecm import AVTS, OTAC, OTAWP, OTCA, OTCS, OTDS, OTIV, OTKD, OTPD, CoreShare
|
|
23
|
-
from pyxecm.
|
|
24
|
-
|
|
25
|
-
from
|
|
26
|
-
from
|
|
22
|
+
from pyxecm.helper.otel_config import tracer
|
|
23
|
+
|
|
24
|
+
from .k8s import K8s
|
|
25
|
+
from .m365 import M365
|
|
26
|
+
from .payload import Payload
|
|
27
|
+
from .settings import Settings
|
|
27
28
|
|
|
28
|
-
default_logger = logging.getLogger("
|
|
29
|
+
default_logger = logging.getLogger("pyxecm_customizer")
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
class Customizer:
|
|
@@ -410,11 +411,23 @@ class Customizer:
|
|
|
410
411
|
self.settings.aviator.oauth_secret,
|
|
411
412
|
)
|
|
412
413
|
|
|
414
|
+
content_system = None
|
|
415
|
+
|
|
416
|
+
# Read the Content_System from the ConfigMaps - This controls the authentication system for OTCA
|
|
417
|
+
if self.k8s_object:
|
|
418
|
+
content_system = {}
|
|
419
|
+
for service in ["chat", "embed"]:
|
|
420
|
+
cm = self.k8s_object.get_config_map(f"csai-{service}-svc")
|
|
421
|
+
if cm:
|
|
422
|
+
content_system[service] = cm.data.get("CONTENT_SYSTEM", "none")
|
|
423
|
+
|
|
413
424
|
return OTCA(
|
|
414
425
|
chat_url=str(self.settings.aviator.chat_svc_url),
|
|
415
426
|
embed_url=str(self.settings.aviator.embed_svc_url),
|
|
427
|
+
studio_url=str(self.settings.aviator.studio_url),
|
|
416
428
|
client_id=self.settings.avts.client_id,
|
|
417
429
|
client_secret=self.settings.avts.client_secret,
|
|
430
|
+
content_system=content_system,
|
|
418
431
|
otds_url=str(self.settings.otds.url),
|
|
419
432
|
otcs_object=self.otcs_backend_object,
|
|
420
433
|
logger=self.logger,
|
|
@@ -819,7 +832,7 @@ class Customizer:
|
|
|
819
832
|
|
|
820
833
|
"""
|
|
821
834
|
|
|
822
|
-
self.logger.info("Connection parameters OTCS
|
|
835
|
+
self.logger.info("Connection parameters OTCS:")
|
|
823
836
|
self.logger.info("OTCS URL = %s", str(self.settings.otcs.url))
|
|
824
837
|
self.logger.info(
|
|
825
838
|
"OTCS Frontend URL = %s",
|
|
@@ -921,7 +934,7 @@ class Customizer:
|
|
|
921
934
|
)
|
|
922
935
|
otcs_resource["logoutMethod"] = "GET"
|
|
923
936
|
|
|
924
|
-
self.otds_object.update_resource(name=
|
|
937
|
+
self.otds_object.update_resource(name=self.settings.otcs.resource_name, resource=otcs_resource)
|
|
925
938
|
|
|
926
939
|
# Allow impersonation of the resource for all users:
|
|
927
940
|
self.otds_object.impersonate_resource(self.settings.otcs.resource_name)
|
|
@@ -1136,7 +1149,7 @@ class Customizer:
|
|
|
1136
1149
|
self.logger.info("Found Content Server OTDS resource ID -> %s", otcs_resource_id)
|
|
1137
1150
|
|
|
1138
1151
|
# make sure code is idempotent and only try to add ressource if it doesn't exist already:
|
|
1139
|
-
awp_resource = self.otds_object.get_resource(self.settings.otawp.resource_name)
|
|
1152
|
+
awp_resource = self.otds_object.get_resource(name=self.settings.otawp.resource_name)
|
|
1140
1153
|
if not awp_resource:
|
|
1141
1154
|
self.logger.info(
|
|
1142
1155
|
"OTDS resource -> '%s' for AppWorks Platform does not yet exist. Creating...",
|
|
@@ -1331,6 +1344,41 @@ class Customizer:
|
|
|
1331
1344
|
|
|
1332
1345
|
self.logger.info("Restart OTCS frontend and backend pods...")
|
|
1333
1346
|
|
|
1347
|
+
# Get number of replicas or update it for da as it might change with dynamic scaling:
|
|
1348
|
+
otcs_da_scale = self.k8s_object.get_stateful_set_scale(
|
|
1349
|
+
sts_name=self.settings.k8s.sts_otcs_da,
|
|
1350
|
+
)
|
|
1351
|
+
if not otcs_da_scale:
|
|
1352
|
+
self.logger.warning(
|
|
1353
|
+
"Cannot find Kubernetes Stateful Set -> '%s' for OTCS DA!",
|
|
1354
|
+
self.settings.k8s.sts_otcs_da,
|
|
1355
|
+
)
|
|
1356
|
+
self.settings.k8s.sts_otcs_da_replicas = 0
|
|
1357
|
+
else:
|
|
1358
|
+
self.settings.k8s.sts_otcs_da_replicas = otcs_da_scale.spec.replicas
|
|
1359
|
+
|
|
1360
|
+
# Restart all da:
|
|
1361
|
+
for x in range(self.settings.k8s.sts_otcs_da_replicas):
|
|
1362
|
+
pod_name = self.settings.k8s.sts_otcs_da + "-" + str(x)
|
|
1363
|
+
|
|
1364
|
+
self.logger.info("Deactivate Liveness probe for pod -> '%s'", pod_name)
|
|
1365
|
+
self.k8s_object.exec_pod_command(
|
|
1366
|
+
pod_name,
|
|
1367
|
+
["/bin/sh", "-c", "touch /tmp/keepalive"],
|
|
1368
|
+
container="otcs-da-container",
|
|
1369
|
+
)
|
|
1370
|
+
self.logger.info("Restarting OTCS in pod -> '%s'", pod_name)
|
|
1371
|
+
self.k8s_object.exec_pod_command(
|
|
1372
|
+
pod_name,
|
|
1373
|
+
["/bin/sh", "-c", "/opt/opentext/cs/stop_csserver"],
|
|
1374
|
+
container="otcs-da-container",
|
|
1375
|
+
)
|
|
1376
|
+
self.k8s_object.exec_pod_command(
|
|
1377
|
+
pod_name,
|
|
1378
|
+
["/bin/sh", "-c", "/opt/opentext/cs/start_csserver"],
|
|
1379
|
+
container="otcs-da-container",
|
|
1380
|
+
)
|
|
1381
|
+
|
|
1334
1382
|
# Get number of replicas or update it for frontends as it might change with dynamic scaling:
|
|
1335
1383
|
otcs_frontend_scale = self.k8s_object.get_stateful_set_scale(
|
|
1336
1384
|
sts_name=self.settings.k8s.sts_otcs_frontend,
|
|
@@ -1340,8 +1388,9 @@ class Customizer:
|
|
|
1340
1388
|
"Cannot find Kubernetes Stateful Set -> '%s' for OTCS Frontends!",
|
|
1341
1389
|
self.settings.k8s.sts_otcs_frontend,
|
|
1342
1390
|
)
|
|
1343
|
-
|
|
1344
|
-
|
|
1391
|
+
self.settings.k8s.sts_otcs_frontend_replicas = 0
|
|
1392
|
+
else:
|
|
1393
|
+
self.settings.k8s.sts_otcs_frontend_replicas = otcs_frontend_scale.spec.replicas
|
|
1345
1394
|
|
|
1346
1395
|
# Restart all frontends:
|
|
1347
1396
|
for x in range(self.settings.k8s.sts_otcs_frontend_replicas):
|
|
@@ -1577,6 +1626,7 @@ class Customizer:
|
|
|
1577
1626
|
|
|
1578
1627
|
# end method definition
|
|
1579
1628
|
|
|
1629
|
+
@tracer.start_as_current_span("init_customizer")
|
|
1580
1630
|
def init_customizer(self) -> bool:
|
|
1581
1631
|
"""Initialize all objects used by the customizer.
|
|
1582
1632
|
|
|
@@ -1734,13 +1784,14 @@ class Customizer:
|
|
|
1734
1784
|
|
|
1735
1785
|
# end method definition
|
|
1736
1786
|
|
|
1787
|
+
@tracer.start_as_current_span("customization_run")
|
|
1737
1788
|
def customization_run(self) -> bool:
|
|
1738
1789
|
"""Central method to initiate the customization."""
|
|
1739
1790
|
|
|
1740
1791
|
success = True
|
|
1741
1792
|
|
|
1742
1793
|
# Set Timer for duration calculation
|
|
1743
|
-
self.customizer_start_time = datetime.now(
|
|
1794
|
+
self.customizer_start_time = datetime.now(UTC)
|
|
1744
1795
|
|
|
1745
1796
|
if not self.init_customizer():
|
|
1746
1797
|
self.logger.error("Initialization of customizer failed!")
|
|
@@ -1789,122 +1840,133 @@ class Customizer:
|
|
|
1789
1840
|
)
|
|
1790
1841
|
|
|
1791
1842
|
for cust_payload in cust_payload_list:
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1843
|
+
with tracer.start_as_current_span("customizer_run_payload") as t:
|
|
1844
|
+
t.set_attributes(
|
|
1845
|
+
{
|
|
1846
|
+
"payload": cust_payload,
|
|
1847
|
+
}
|
|
1848
|
+
)
|
|
1849
|
+
self.log_header("Start processing of payload -> '{}'".format(cust_payload))
|
|
1850
|
+
|
|
1851
|
+
# Set startTime for duration calculation
|
|
1852
|
+
start_time = datetime.now(UTC)
|
|
1853
|
+
|
|
1854
|
+
# Create payload object:
|
|
1855
|
+
payload_object = Payload(
|
|
1856
|
+
payload_source=cust_payload,
|
|
1857
|
+
custom_settings_dir=self.settings.cust_settings_dir,
|
|
1858
|
+
k8s_object=self.k8s_object,
|
|
1859
|
+
otds_object=self.otds_object,
|
|
1860
|
+
otac_object=self.otac_object,
|
|
1861
|
+
otcs_backend_object=self.otcs_backend_object,
|
|
1862
|
+
otcs_frontend_object=self.otcs_frontend_object,
|
|
1863
|
+
otcs_restart_callback=self.restart_otcs_service,
|
|
1864
|
+
otiv_object=self.otiv_object,
|
|
1865
|
+
otpd_object=self.otpd_object,
|
|
1866
|
+
m365_object=self.m365_object,
|
|
1867
|
+
core_share_object=self.core_share_object,
|
|
1868
|
+
browser_headless=self.settings.headless_browser,
|
|
1869
|
+
placeholder_values=self.settings.placeholder_values, # this dict includes placeholder replacements for the Ressource IDs of OTAWP and OTCS
|
|
1870
|
+
log_header_callback=self.log_header,
|
|
1871
|
+
stop_on_error=self.settings.stop_on_error,
|
|
1872
|
+
aviator_enabled=self.settings.aviator.enabled,
|
|
1873
|
+
upload_status_files=self.settings.otcs.upload_status_files,
|
|
1874
|
+
otawp_object=self.otawp_object,
|
|
1875
|
+
otca_object=self.otca_object,
|
|
1876
|
+
otkd_object=self.otkd_object,
|
|
1877
|
+
avts_object=self.avts_object,
|
|
1878
|
+
logger=self.logger,
|
|
1828
1879
|
)
|
|
1829
|
-
|
|
1830
|
-
|
|
1880
|
+
# Load the payload file and initialize the payload sections:
|
|
1881
|
+
t.add_event("Payload file loaded", timestamp=time.time_ns())
|
|
1882
|
+
if not payload_object.init_payload():
|
|
1883
|
+
self.logger.error(
|
|
1884
|
+
"Failed to initialize payload -> '%s' - skipping payload file...",
|
|
1885
|
+
cust_payload,
|
|
1886
|
+
)
|
|
1887
|
+
success = False
|
|
1888
|
+
continue
|
|
1831
1889
|
|
|
1832
|
-
|
|
1833
|
-
payload_object.process_payload()
|
|
1890
|
+
t.add_event("Payload initialized", timestamp=time.time_ns())
|
|
1834
1891
|
|
|
1835
|
-
|
|
1836
|
-
|
|
1892
|
+
# Now process the payload in the defined ordering:
|
|
1893
|
+
payload_object.process_payload()
|
|
1894
|
+
t.add_event("Payload processsed", timestamp=time.time_ns())
|
|
1837
1895
|
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
response = self.otcs_backend_object.get_node_from_nickname(
|
|
1842
|
-
nickname=self.settings.cust_target_folder_nickname,
|
|
1843
|
-
)
|
|
1844
|
-
target_folder_id = self.otcs_backend_object.get_result_value(
|
|
1845
|
-
response=response,
|
|
1846
|
-
key="id",
|
|
1847
|
-
)
|
|
1848
|
-
if not target_folder_id:
|
|
1849
|
-
target_folder_id = 2000 # use Enterprise Workspace as fallback
|
|
1850
|
-
# Write YAML file with upadated payload (including IDs, etc.).
|
|
1851
|
-
# We need to write to a temporary location as initial location is read-only:
|
|
1852
|
-
payload_file = os.path.basename(cust_payload)
|
|
1853
|
-
payload_file = payload_file.removesuffix(".gz.b64")
|
|
1854
|
-
payload_file = payload_file.replace(".tfvars", ".yaml").replace(
|
|
1855
|
-
".tf",
|
|
1856
|
-
".yaml",
|
|
1857
|
-
)
|
|
1858
|
-
cust_payload = os.path.join(tempfile.gettempdir(), payload_file)
|
|
1859
|
-
|
|
1860
|
-
with open(cust_payload, "w", encoding="utf-8") as file:
|
|
1861
|
-
yaml.dump(
|
|
1862
|
-
data=payload_object.get_payload(
|
|
1863
|
-
drop_bulk_datasources_data=True,
|
|
1864
|
-
),
|
|
1865
|
-
stream=file,
|
|
1866
|
-
)
|
|
1896
|
+
self.log_header("Consolidate OTDS Resources")
|
|
1897
|
+
self.consolidate_otds()
|
|
1898
|
+
t.add_event("OTCS consolidated", timestamp=time.time_ns())
|
|
1867
1899
|
|
|
1868
|
-
#
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
name=os.path.basename(cust_payload),
|
|
1874
|
-
)
|
|
1875
|
-
target_document_id = self.otcs_backend_object.get_result_value(
|
|
1876
|
-
response=response,
|
|
1877
|
-
key="id",
|
|
1878
|
-
)
|
|
1879
|
-
if target_document_id:
|
|
1880
|
-
response = self.otcs_backend_object.add_document_version(
|
|
1881
|
-
node_id=int(target_document_id),
|
|
1882
|
-
file_url=cust_payload,
|
|
1883
|
-
file_name=os.path.basename(cust_payload),
|
|
1884
|
-
mime_type="text/plain",
|
|
1885
|
-
description="Updated payload file after re-run of customization",
|
|
1900
|
+
# Upload payload file for later review to Enterprise Workspace
|
|
1901
|
+
if self.settings.otcs.upload_config_files:
|
|
1902
|
+
self.log_header("Upload Payload file to OpenText Content Management")
|
|
1903
|
+
response = self.otcs_backend_object.get_node_from_nickname(
|
|
1904
|
+
nickname=self.settings.cust_target_folder_nickname,
|
|
1886
1905
|
)
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1906
|
+
target_folder_id = self.otcs_backend_object.get_result_value(
|
|
1907
|
+
response=response,
|
|
1908
|
+
key="id",
|
|
1909
|
+
)
|
|
1910
|
+
if not target_folder_id:
|
|
1911
|
+
target_folder_id = 2000 # use Enterprise Workspace as fallback
|
|
1912
|
+
# Write YAML file with upadated payload (including IDs, etc.).
|
|
1913
|
+
# We need to write to a temporary location as initial location is read-only:
|
|
1914
|
+
payload_file = os.path.basename(cust_payload)
|
|
1915
|
+
payload_file = payload_file.removesuffix(".gz.b64")
|
|
1916
|
+
payload_file = payload_file.replace(".tfvars", ".yaml").replace(
|
|
1917
|
+
".tf",
|
|
1918
|
+
".yaml",
|
|
1919
|
+
)
|
|
1920
|
+
cust_payload = os.path.join(tempfile.gettempdir(), payload_file)
|
|
1921
|
+
|
|
1922
|
+
with open(cust_payload, "w", encoding="utf-8") as file:
|
|
1923
|
+
yaml.dump(
|
|
1924
|
+
data=payload_object.get_payload(
|
|
1925
|
+
drop_bulk_datasources_data=True,
|
|
1926
|
+
),
|
|
1927
|
+
stream=file,
|
|
1928
|
+
)
|
|
1929
|
+
|
|
1930
|
+
# Check if the payload file has been uploaded before.
|
|
1931
|
+
# This can happen if we re-run the python container.
|
|
1932
|
+
# In this case we add a version to the existing document:
|
|
1933
|
+
response = self.otcs_backend_object.get_node_by_parent_and_name(
|
|
1892
1934
|
parent_id=int(target_folder_id),
|
|
1935
|
+
name=os.path.basename(cust_payload),
|
|
1936
|
+
)
|
|
1937
|
+
target_document_id = self.otcs_backend_object.get_result_value(
|
|
1938
|
+
response=response,
|
|
1939
|
+
key="id",
|
|
1893
1940
|
)
|
|
1941
|
+
if target_document_id:
|
|
1942
|
+
response = self.otcs_backend_object.add_document_version(
|
|
1943
|
+
node_id=int(target_document_id),
|
|
1944
|
+
file_url=cust_payload,
|
|
1945
|
+
file_name=os.path.basename(cust_payload),
|
|
1946
|
+
mime_type="text/plain",
|
|
1947
|
+
description="Updated payload file after re-run of customization",
|
|
1948
|
+
)
|
|
1949
|
+
else:
|
|
1950
|
+
response = self.otcs_backend_object.upload_file_to_parent(
|
|
1951
|
+
file_url=cust_payload,
|
|
1952
|
+
file_name=os.path.basename(cust_payload),
|
|
1953
|
+
mime_type="text/plain",
|
|
1954
|
+
parent_id=int(target_folder_id),
|
|
1955
|
+
)
|
|
1894
1956
|
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1957
|
+
duration = datetime.now(UTC) - start_time
|
|
1958
|
+
self.log_header(
|
|
1959
|
+
"Customizer completed processing of payload -> {} in {}".format(
|
|
1960
|
+
cust_payload,
|
|
1961
|
+
duration,
|
|
1962
|
+
),
|
|
1963
|
+
)
|
|
1902
1964
|
# end for cust_payload in cust_payload_list
|
|
1903
1965
|
|
|
1904
1966
|
if self.settings.otcs.maintenance_mode:
|
|
1905
1967
|
self.set_maintenance_mode(enable=False)
|
|
1906
1968
|
|
|
1907
|
-
# Code below
|
|
1969
|
+
# Code below disabled -> not needed anymore, will be done via "kubernetes" payload section
|
|
1908
1970
|
#
|
|
1909
1971
|
# # Restart AppWorksPlatform pod if it is deployed (to make settings effective):
|
|
1910
1972
|
# if self.settings.otawp.enabled: # is AppWorks Platform deployed?
|
|
@@ -1984,7 +2046,7 @@ class Customizer:
|
|
|
1984
2046
|
description="Initial Python Log after first run of customization",
|
|
1985
2047
|
)
|
|
1986
2048
|
|
|
1987
|
-
self.customizer_end_time = datetime.now(
|
|
2049
|
+
self.customizer_end_time = datetime.now(UTC)
|
|
1988
2050
|
self.log_header(
|
|
1989
2051
|
"Customizer completed in {}".format(
|
|
1990
2052
|
self.customizer_end_time - self.customizer_start_time,
|
|
@@ -143,7 +143,7 @@ class Guidewire:
|
|
|
143
143
|
"""Authenticate with the Guidewire API using either client credentials or username/password.
|
|
144
144
|
|
|
145
145
|
Args:
|
|
146
|
-
auth_type (str | None):
|
|
146
|
+
auth_type (str | None, optional):
|
|
147
147
|
The Authorization type. This can be "basic" or "oauth".
|
|
148
148
|
|
|
149
149
|
Returns:
|
|
@@ -340,7 +340,7 @@ class Guidewire:
|
|
|
340
340
|
"""Retrieve a list of Guidewire groups.
|
|
341
341
|
|
|
342
342
|
Args:
|
|
343
|
-
fields (list):
|
|
343
|
+
fields (list | None, optional):
|
|
344
344
|
The list of fields in the results. If None, all default
|
|
345
345
|
fields are returned.
|
|
346
346
|
Fields for Guidewire accounts:
|
|
@@ -357,7 +357,7 @@ class Guidewire:
|
|
|
357
357
|
- parent
|
|
358
358
|
- securityZone
|
|
359
359
|
- supervisor
|
|
360
|
-
filters (list):
|
|
360
|
+
filters (list | None, optional):
|
|
361
361
|
List of dictionaries with three keys each:
|
|
362
362
|
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
363
363
|
- "op" - operator:
|
|
@@ -444,6 +444,42 @@ class Guidewire:
|
|
|
444
444
|
for group in groups:
|
|
445
445
|
logger.info("Traversing Guidewire group -> '%s'...", group.get("attributes", {}).get("displayName"))
|
|
446
446
|
|
|
447
|
+
Args:
|
|
448
|
+
fields (list | None, optional):
|
|
449
|
+
The list of fields in the results. If None, all default
|
|
450
|
+
fields are returned.
|
|
451
|
+
Fields for Guidewire accounts:
|
|
452
|
+
- *all = return all fields
|
|
453
|
+
- *default = return just the default list of fields
|
|
454
|
+
- *summary = return the fields defined for giving a summary
|
|
455
|
+
- *detail = details
|
|
456
|
+
- displayName
|
|
457
|
+
- groupType
|
|
458
|
+
- id
|
|
459
|
+
- loadFactor
|
|
460
|
+
- name
|
|
461
|
+
- organization
|
|
462
|
+
- parent
|
|
463
|
+
- securityZone
|
|
464
|
+
- supervisor
|
|
465
|
+
filters (list | None, optional):
|
|
466
|
+
List of dictionaries with three keys each:
|
|
467
|
+
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
468
|
+
- "op" - operator:
|
|
469
|
+
* eq - equal
|
|
470
|
+
* ne - not equal
|
|
471
|
+
* lt - less than - also usable for dates (before)
|
|
472
|
+
* gt - greater than - also usable for dates (after)
|
|
473
|
+
* le - less or equal
|
|
474
|
+
* ge - greater or equal
|
|
475
|
+
* in - is in list
|
|
476
|
+
* ni - is NOT in list
|
|
477
|
+
* sw - starts with
|
|
478
|
+
* cn - contains
|
|
479
|
+
- "value": the value to filter for. Either literal or list of values
|
|
480
|
+
page_size (int, optional):
|
|
481
|
+
The maximum number of groups to return.
|
|
482
|
+
|
|
447
483
|
Returns:
|
|
448
484
|
iter:
|
|
449
485
|
A generator yielding one Guidewire group per iteration.
|
|
@@ -480,10 +516,12 @@ class Guidewire:
|
|
|
480
516
|
"""Retrieve details of a specific group.
|
|
481
517
|
|
|
482
518
|
Args:
|
|
483
|
-
group_id:
|
|
519
|
+
group_id:
|
|
520
|
+
The unique identifier of the group.
|
|
484
521
|
|
|
485
522
|
Returns:
|
|
486
|
-
dict:
|
|
523
|
+
dict:
|
|
524
|
+
JSON response containing group details.
|
|
487
525
|
|
|
488
526
|
Example response;
|
|
489
527
|
{
|
|
@@ -543,7 +581,7 @@ class Guidewire:
|
|
|
543
581
|
"""Retrieve a list of Guidewire users.
|
|
544
582
|
|
|
545
583
|
Args:
|
|
546
|
-
fields (list):
|
|
584
|
+
fields (list | None, optional):
|
|
547
585
|
The list of fields in the results. If None, all default
|
|
548
586
|
fields are returned.
|
|
549
587
|
Fields for Guidewire accounts:
|
|
@@ -560,7 +598,7 @@ class Guidewire:
|
|
|
560
598
|
- parent
|
|
561
599
|
- securityZone
|
|
562
600
|
- supervisor
|
|
563
|
-
filters (list):
|
|
601
|
+
filters (list | None, optional):
|
|
564
602
|
List of dictionaries with three keys each:
|
|
565
603
|
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
566
604
|
- "op" - operator:
|
|
@@ -577,7 +615,7 @@ class Guidewire:
|
|
|
577
615
|
- "value": the value to filter for. Either literal or list of values
|
|
578
616
|
page_size (int, optional):
|
|
579
617
|
The maximum number of groups to return.
|
|
580
|
-
next_page_url (str, optional):
|
|
618
|
+
next_page_url (str | None, optional):
|
|
581
619
|
The Guidewire URL to retrieve the next page of Guidewire groups (pagination).
|
|
582
620
|
This is used for the iterator get_groups_iterator() below.
|
|
583
621
|
|
|
@@ -696,7 +734,7 @@ class Guidewire:
|
|
|
696
734
|
logger.info("Traversing Guidewire user -> '%s'...", user.get("attributes", {}).get("displayName"))
|
|
697
735
|
|
|
698
736
|
Args:
|
|
699
|
-
fields (list):
|
|
737
|
+
fields (list | None, optional):
|
|
700
738
|
The list of fields in the results. If None, all default
|
|
701
739
|
fields are returned.
|
|
702
740
|
Fields for Guidewire accounts:
|
|
@@ -714,7 +752,7 @@ class Guidewire:
|
|
|
714
752
|
- useOrgAddress
|
|
715
753
|
- useProducerCodeSecurity
|
|
716
754
|
- username
|
|
717
|
-
filters (list):
|
|
755
|
+
filters (list | None, optional):
|
|
718
756
|
List of dictionaries with three keys each:
|
|
719
757
|
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
720
758
|
- "op" - operator:
|
|
@@ -866,7 +904,7 @@ class Guidewire:
|
|
|
866
904
|
"""Retrieve a list of accounts.
|
|
867
905
|
|
|
868
906
|
Args:
|
|
869
|
-
fields (list):
|
|
907
|
+
fields (list | None, optional):
|
|
870
908
|
The list of fields in the results. If None, all default
|
|
871
909
|
fields are returned.
|
|
872
910
|
Fields for Guidewire accounts:
|
|
@@ -889,7 +927,7 @@ class Guidewire:
|
|
|
889
927
|
- primaryLocale
|
|
890
928
|
- primaryLocation
|
|
891
929
|
- producerCodes
|
|
892
|
-
filters (list):
|
|
930
|
+
filters (list | None, optional):
|
|
893
931
|
List of dictionaries with three keys each:
|
|
894
932
|
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
895
933
|
- "op" - operator:
|
|
@@ -943,7 +981,7 @@ class Guidewire:
|
|
|
943
981
|
logger.info("Traversing Guidewire account -> '%s'...", account.get("attributes", {}).get("displayName"))
|
|
944
982
|
|
|
945
983
|
Args:
|
|
946
|
-
fields (list):
|
|
984
|
+
fields (list | None, optional):
|
|
947
985
|
The list of fields in the results. If None, all default
|
|
948
986
|
fields are returned.
|
|
949
987
|
Fields for Guidewire accounts:
|
|
@@ -966,7 +1004,7 @@ class Guidewire:
|
|
|
966
1004
|
- primaryLocale
|
|
967
1005
|
- primaryLocation
|
|
968
1006
|
- producerCodes
|
|
969
|
-
filters (list):
|
|
1007
|
+
filters (list | None, optional):
|
|
970
1008
|
List of dictionaries with three keys each:
|
|
971
1009
|
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
972
1010
|
- "op" - operator:
|
|
@@ -1081,10 +1119,12 @@ class Guidewire:
|
|
|
1081
1119
|
"""Delete an account.
|
|
1082
1120
|
|
|
1083
1121
|
Args:
|
|
1084
|
-
account_id:
|
|
1122
|
+
account_id (str):
|
|
1123
|
+
The unique identifier of the account to delete.
|
|
1085
1124
|
|
|
1086
1125
|
Returns:
|
|
1087
|
-
dict:
|
|
1126
|
+
dict:
|
|
1127
|
+
JSON response indicating deletion success.
|
|
1088
1128
|
|
|
1089
1129
|
"""
|
|
1090
1130
|
|
|
@@ -1104,7 +1144,7 @@ class Guidewire:
|
|
|
1104
1144
|
"""Retrieve a list of claims.
|
|
1105
1145
|
|
|
1106
1146
|
Args:
|
|
1107
|
-
fields (list):
|
|
1147
|
+
fields (list | None, optional):
|
|
1108
1148
|
The list of fields in the results. If None, all default
|
|
1109
1149
|
fields are returned.
|
|
1110
1150
|
Fields for Guidewire accounts:
|
|
@@ -1121,7 +1161,7 @@ class Guidewire:
|
|
|
1121
1161
|
- parent
|
|
1122
1162
|
- securityZone
|
|
1123
1163
|
- supervisor
|
|
1124
|
-
filters (list):
|
|
1164
|
+
filters (list | None, optional):
|
|
1125
1165
|
List of dictionaries with three keys each:
|
|
1126
1166
|
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
1127
1167
|
- "op" - operator:
|
|
@@ -1173,7 +1213,7 @@ class Guidewire:
|
|
|
1173
1213
|
logger.info("Traversing Guidewire claim -> '%s'...", claim.get("attributes", {}).get("displayName"))
|
|
1174
1214
|
|
|
1175
1215
|
Args:
|
|
1176
|
-
fields (list):
|
|
1216
|
+
fields (list | None, optional):
|
|
1177
1217
|
The list of fields in the results. If None, all default
|
|
1178
1218
|
fields are returned.
|
|
1179
1219
|
Fields for Guidewire accounts:
|
|
@@ -1190,7 +1230,7 @@ class Guidewire:
|
|
|
1190
1230
|
- parent
|
|
1191
1231
|
- securityZone
|
|
1192
1232
|
- supervisor
|
|
1193
|
-
filters (list):
|
|
1233
|
+
filters (list | None, optional):
|
|
1194
1234
|
List of dictionaries with three keys each:
|
|
1195
1235
|
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
1196
1236
|
- "op" - operator:
|
|
@@ -16,7 +16,7 @@ __email__ = "mdiefenb@opentext.com"
|
|
|
16
16
|
import logging
|
|
17
17
|
import os
|
|
18
18
|
import time
|
|
19
|
-
from datetime import
|
|
19
|
+
from datetime import UTC, datetime
|
|
20
20
|
|
|
21
21
|
from kubernetes import client, config
|
|
22
22
|
from kubernetes.client import (
|
|
@@ -36,7 +36,7 @@ from kubernetes.client.exceptions import ApiException
|
|
|
36
36
|
from kubernetes.config.config_exception import ConfigException
|
|
37
37
|
from kubernetes.stream import stream
|
|
38
38
|
|
|
39
|
-
default_logger = logging.getLogger("
|
|
39
|
+
default_logger = logging.getLogger("pyxecm_customizer.k8s")
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
class K8s:
|
|
@@ -1331,7 +1331,7 @@ class K8s:
|
|
|
1331
1331
|
success = True
|
|
1332
1332
|
|
|
1333
1333
|
if not force:
|
|
1334
|
-
now = datetime.now(
|
|
1334
|
+
now = datetime.now(UTC).isoformat(timespec="seconds") + "Z"
|
|
1335
1335
|
|
|
1336
1336
|
body = {
|
|
1337
1337
|
"spec": {
|
|
@@ -1468,7 +1468,7 @@ class K8s:
|
|
|
1468
1468
|
|
|
1469
1469
|
success = True
|
|
1470
1470
|
|
|
1471
|
-
now = datetime.now(
|
|
1471
|
+
now = datetime.now(UTC).isoformat(timespec="seconds") + "Z"
|
|
1472
1472
|
|
|
1473
1473
|
body = {
|
|
1474
1474
|
"spec": {
|