pyxecm 2.0.4__py3-none-any.whl → 3.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.

Files changed (94) hide show
  1. pyxecm/coreshare.py +5 -3
  2. pyxecm/helper/data.py +4 -4
  3. pyxecm/helper/otel_config.py +26 -0
  4. pyxecm/helper/web.py +1 -2
  5. pyxecm/otca.py +1356 -16
  6. pyxecm/otcs.py +2354 -593
  7. pyxecm/otds.py +1 -1
  8. pyxecm/otmm.py +4 -5
  9. pyxecm/py.typed +0 -0
  10. pyxecm-3.0.0.dist-info/METADATA +48 -0
  11. pyxecm-3.0.0.dist-info/RECORD +96 -0
  12. {pyxecm-2.0.4.dist-info → pyxecm-3.0.0.dist-info}/WHEEL +1 -2
  13. pyxecm-3.0.0.dist-info/entry_points.txt +4 -0
  14. {pyxecm/customizer/api → pyxecm_api}/__main__.py +1 -1
  15. pyxecm_api/agents/__init__.py +7 -0
  16. pyxecm_api/agents/app.py +13 -0
  17. pyxecm_api/agents/functions.py +119 -0
  18. pyxecm_api/agents/models.py +10 -0
  19. pyxecm_api/agents/otcm_knowledgegraph/functions.py +85 -0
  20. pyxecm_api/agents/otcm_knowledgegraph/models.py +61 -0
  21. pyxecm_api/agents/otcm_knowledgegraph/router.py +74 -0
  22. pyxecm_api/agents/otcm_user_agent/models.py +20 -0
  23. pyxecm_api/agents/otcm_user_agent/router.py +65 -0
  24. pyxecm_api/agents/otcm_workspace_agent/models.py +40 -0
  25. pyxecm_api/agents/otcm_workspace_agent/router.py +200 -0
  26. pyxecm_api/app.py +221 -0
  27. {pyxecm/customizer/api → pyxecm_api}/auth/functions.py +10 -2
  28. {pyxecm/customizer/api → pyxecm_api}/auth/router.py +4 -3
  29. {pyxecm/customizer/api → pyxecm_api}/common/functions.py +39 -9
  30. {pyxecm/customizer/api → pyxecm_api}/common/metrics.py +1 -2
  31. {pyxecm/customizer/api → pyxecm_api}/common/router.py +7 -8
  32. {pyxecm/customizer/api → pyxecm_api}/settings.py +21 -6
  33. {pyxecm/customizer/api → pyxecm_api}/terminal/router.py +1 -1
  34. {pyxecm/customizer/api → pyxecm_api}/v1_csai/router.py +39 -10
  35. pyxecm_api/v1_csai/statics/bindings/utils.js +189 -0
  36. pyxecm_api/v1_csai/statics/tom-select/tom-select.complete.min.js +356 -0
  37. pyxecm_api/v1_csai/statics/tom-select/tom-select.css +334 -0
  38. pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.css +1 -0
  39. pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.min.js +27 -0
  40. pyxecm_api/v1_maintenance/__init__.py +1 -0
  41. {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/functions.py +3 -3
  42. {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/router.py +8 -8
  43. pyxecm_api/v1_otcs/__init__.py +1 -0
  44. {pyxecm/customizer/api → pyxecm_api}/v1_otcs/functions.py +7 -5
  45. {pyxecm/customizer/api → pyxecm_api}/v1_otcs/router.py +8 -7
  46. pyxecm_api/v1_payload/__init__.py +1 -0
  47. {pyxecm/customizer/api → pyxecm_api}/v1_payload/functions.py +10 -7
  48. {pyxecm/customizer/api → pyxecm_api}/v1_payload/router.py +11 -10
  49. {pyxecm/customizer → pyxecm_customizer}/__init__.py +8 -0
  50. {pyxecm/customizer → pyxecm_customizer}/__main__.py +15 -21
  51. {pyxecm/customizer → pyxecm_customizer}/browser_automation.py +414 -103
  52. {pyxecm/customizer → pyxecm_customizer}/customizer.py +178 -116
  53. {pyxecm/customizer → pyxecm_customizer}/guidewire.py +60 -20
  54. {pyxecm/customizer → pyxecm_customizer}/k8s.py +4 -4
  55. pyxecm_customizer/knowledge_graph.py +719 -0
  56. pyxecm_customizer/log.py +35 -0
  57. {pyxecm/customizer → pyxecm_customizer}/m365.py +41 -33
  58. {pyxecm/customizer → pyxecm_customizer}/payload.py +2265 -1933
  59. {pyxecm/customizer/api/common → pyxecm_customizer}/payload_list.py +18 -55
  60. {pyxecm/customizer → pyxecm_customizer}/salesforce.py +1 -1
  61. {pyxecm/customizer → pyxecm_customizer}/sap.py +6 -2
  62. {pyxecm/customizer → pyxecm_customizer}/servicenow.py +2 -4
  63. {pyxecm/customizer → pyxecm_customizer}/settings.py +7 -6
  64. {pyxecm/customizer → pyxecm_customizer}/successfactors.py +40 -28
  65. {pyxecm/customizer → pyxecm_customizer}/translate.py +1 -1
  66. {pyxecm/maintenance_page → pyxecm_maintenance_page}/__main__.py +1 -1
  67. {pyxecm/maintenance_page → pyxecm_maintenance_page}/app.py +14 -8
  68. pyxecm/customizer/api/app.py +0 -157
  69. pyxecm/customizer/log.py +0 -107
  70. pyxecm/customizer/nhc.py +0 -1169
  71. pyxecm/customizer/openapi.py +0 -258
  72. pyxecm/customizer/pht.py +0 -1357
  73. pyxecm-2.0.4.dist-info/METADATA +0 -119
  74. pyxecm-2.0.4.dist-info/RECORD +0 -78
  75. pyxecm-2.0.4.dist-info/licenses/LICENSE +0 -202
  76. pyxecm-2.0.4.dist-info/top_level.txt +0 -1
  77. {pyxecm/customizer/api → pyxecm_api}/__init__.py +0 -0
  78. {pyxecm/customizer/api/auth → pyxecm_api/agents/otcm_knowledgegraph}/__init__.py +0 -0
  79. {pyxecm/customizer/api/common → pyxecm_api/agents/otcm_user_agent}/__init__.py +0 -0
  80. {pyxecm/customizer/api/v1_csai → pyxecm_api/agents/otcm_workspace_agent}/__init__.py +0 -0
  81. {pyxecm/customizer/api/v1_maintenance → pyxecm_api/auth}/__init__.py +0 -0
  82. {pyxecm/customizer/api → pyxecm_api}/auth/models.py +0 -0
  83. {pyxecm/customizer/api/v1_otcs → pyxecm_api/common}/__init__.py +0 -0
  84. {pyxecm/customizer/api → pyxecm_api}/common/models.py +0 -0
  85. {pyxecm/customizer/api → pyxecm_api}/terminal/__init__.py +0 -0
  86. {pyxecm/customizer/api/v1_payload → pyxecm_api/v1_csai}/__init__.py +0 -0
  87. {pyxecm/customizer/api → pyxecm_api}/v1_csai/models.py +0 -0
  88. {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/models.py +0 -0
  89. {pyxecm/customizer/api → pyxecm_api}/v1_payload/models.py +0 -0
  90. {pyxecm/customizer → pyxecm_customizer}/exceptions.py +0 -0
  91. {pyxecm/maintenance_page → pyxecm_maintenance_page}/__init__.py +0 -0
  92. {pyxecm/maintenance_page → pyxecm_maintenance_page}/settings.py +0 -0
  93. {pyxecm/maintenance_page → pyxecm_maintenance_page}/static/favicon.avif +0 -0
  94. {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 datetime, timezone
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.customizer.k8s import K8s
24
- from pyxecm.customizer.m365 import M365
25
- from pyxecm.customizer.payload import Payload
26
- from pyxecm.customizer.settings import Settings
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("pyxecm.customizer")
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 (Extended ECM):")
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="cs", resource=otcs_resource)
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
- self.settings.k8s.sts_otcs_frontend_replicas = otcs_frontend_scale.spec.replicas
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(timezone.utc)
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
- self.log_header("Start processing of payload -> '{}'".format(cust_payload))
1793
-
1794
- # Set startTime for duration calculation
1795
- start_time = datetime.now(timezone.utc)
1796
-
1797
- # Create payload object:
1798
- payload_object = Payload(
1799
- payload_source=cust_payload,
1800
- custom_settings_dir=self.settings.cust_settings_dir,
1801
- k8s_object=self.k8s_object,
1802
- otds_object=self.otds_object,
1803
- otac_object=self.otac_object,
1804
- otcs_backend_object=self.otcs_backend_object,
1805
- otcs_frontend_object=self.otcs_frontend_object,
1806
- otcs_restart_callback=self.restart_otcs_service,
1807
- otiv_object=self.otiv_object,
1808
- otpd_object=self.otpd_object,
1809
- m365_object=self.m365_object,
1810
- core_share_object=self.core_share_object,
1811
- browser_headless=self.settings.headless_browser,
1812
- placeholder_values=self.settings.placeholder_values, # this dict includes placeholder replacements for the Ressource IDs of OTAWP and OTCS
1813
- log_header_callback=self.log_header,
1814
- stop_on_error=self.settings.stop_on_error,
1815
- aviator_enabled=self.settings.aviator.enabled,
1816
- upload_status_files=self.settings.otcs.upload_status_files,
1817
- otawp_object=self.otawp_object,
1818
- otca_object=self.otca_object,
1819
- otkd_object=self.otkd_object,
1820
- avts_object=self.avts_object,
1821
- logger=self.logger,
1822
- )
1823
- # Load the payload file and initialize the payload sections:
1824
- if not payload_object.init_payload():
1825
- self.logger.error(
1826
- "Failed to initialize payload -> '%s' - skipping payload file...",
1827
- cust_payload,
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
- success = False
1830
- continue
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
- # Now process the payload in the defined ordering:
1833
- payload_object.process_payload()
1890
+ t.add_event("Payload initialized", timestamp=time.time_ns())
1834
1891
 
1835
- self.log_header("Consolidate OTDS Resources")
1836
- self.consolidate_otds()
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
- # Upload payload file for later review to Enterprise Workspace
1839
- if self.settings.otcs.upload_config_files:
1840
- self.log_header("Upload Payload file to OpenText Content Management")
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
- # Check if the payload file has been uploaded before.
1869
- # This can happen if we re-run the python container.
1870
- # In this case we add a version to the existing document:
1871
- response = self.otcs_backend_object.get_node_by_parent_and_name(
1872
- parent_id=int(target_folder_id),
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
- else:
1888
- response = self.otcs_backend_object.upload_file_to_parent(
1889
- file_url=cust_payload,
1890
- file_name=os.path.basename(cust_payload),
1891
- mime_type="text/plain",
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
- duration = datetime.now(timezone.utc) - start_time
1896
- self.log_header(
1897
- "Customizer completed processing of payload -> {} in {}".format(
1898
- cust_payload,
1899
- duration,
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 disbaled -> not needed anymore, will be done via "kubernetes" payload section
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(timezone.utc)
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: The unique identifier of the group.
519
+ group_id:
520
+ The unique identifier of the group.
484
521
 
485
522
  Returns:
486
- dict: JSON response containing group details.
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: The unique identifier of the account to delete.
1122
+ account_id (str):
1123
+ The unique identifier of the account to delete.
1085
1124
 
1086
1125
  Returns:
1087
- dict: JSON response indicating deletion success.
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 datetime, timezone
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("pyxecm.customizer.k8s")
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(timezone.utc).isoformat(timespec="seconds") + "Z"
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(timezone.utc).isoformat(timespec="seconds") + "Z"
1471
+ now = datetime.now(UTC).isoformat(timespec="seconds") + "Z"
1472
1472
 
1473
1473
  body = {
1474
1474
  "spec": {