cgcsdk 1.2.4__tar.gz → 1.2.6__tar.gz

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.
Files changed (102) hide show
  1. {cgcsdk-1.2.4/cgcsdk.egg-info → cgcsdk-1.2.6}/PKG-INFO +76 -76
  2. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/.env +1 -1
  3. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/CHANGELOG.md +16 -0
  4. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/auth/auth_cmd.py +2 -0
  5. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/compute/compute_responses.py +18 -0
  6. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/compute/compute_utils.py +12 -2
  7. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/debug/debug_cmd.py +18 -18
  8. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/resource/resource_cmd.py +58 -0
  9. cgcsdk-1.2.6/cgc/tests/test.py +110 -0
  10. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/click_group.py +13 -0
  11. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/custom_exceptions.py +13 -1
  12. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/response_utils.py +10 -3
  13. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/version_control.py +1 -1
  14. {cgcsdk-1.2.4 → cgcsdk-1.2.6/cgcsdk.egg-info}/PKG-INFO +76 -76
  15. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgcsdk.egg-info/SOURCES.txt +1 -1
  16. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/setup.cfg +4 -4
  17. cgcsdk-1.2.4/cgc/server.crt +0 -24
  18. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/LICENSE +0 -0
  19. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/MANIFEST.in +0 -0
  20. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/README.md +0 -0
  21. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/__init__.py +0 -0
  22. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/cgc.py +0 -0
  23. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/__init__.py +0 -0
  24. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/auth/__init__.py +0 -0
  25. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/auth/auth_logic.py +0 -0
  26. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/auth/auth_responses.py +0 -0
  27. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/auth/auth_utils.py +0 -0
  28. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/cgc_cmd.py +0 -0
  29. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/cgc_cmd_responses.py +0 -0
  30. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/cgc_helpers.py +0 -0
  31. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/cgc_models.py +0 -0
  32. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/compute/__init__.py +0 -0
  33. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/compute/billing/__init__.py +0 -0
  34. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/compute/billing/billing_cmd.py +0 -0
  35. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/compute/billing/billing_responses.py +0 -0
  36. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/compute/billing/billing_utils.py +0 -0
  37. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/compute/compute_cmd.py +0 -0
  38. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/compute/compute_models.py +0 -0
  39. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/db/__init__.py +0 -0
  40. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/db/db_cmd.py +0 -0
  41. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/db/db_models.py +0 -0
  42. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/debug/__init__.py +0 -0
  43. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/exceptions.py +0 -0
  44. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/jobs/__init__.py +0 -0
  45. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/jobs/job_utils.py +0 -0
  46. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/jobs/jobs_cmd.py +0 -0
  47. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/jobs/jobs_responses.py +0 -0
  48. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/resource/__init__.py +0 -0
  49. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/resource/resource_responses.py +0 -0
  50. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/user/__init__.py +0 -0
  51. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/user/keys_cmd.py +0 -0
  52. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/user/keys_models.py +0 -0
  53. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/user/keys_responses.py +0 -0
  54. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/user/keys_utils.py +0 -0
  55. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/user/secret_cmd.py +0 -0
  56. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/user/secret_models.py +0 -0
  57. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/user/secret_responses.py +0 -0
  58. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/user/secret_utils.py +0 -0
  59. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/volume/__init__.py +0 -0
  60. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/volume/data_model.py +0 -0
  61. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/volume/volume_cmd.py +0 -0
  62. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/volume/volume_models.py +0 -0
  63. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/volume/volume_responses.py +0 -0
  64. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/commands/volume/volume_utils.py +0 -0
  65. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/config.py +0 -0
  66. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/sdk/__init__.py +0 -0
  67. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/sdk/exceptions.py +0 -0
  68. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/sdk/job.py +0 -0
  69. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/sdk/postgresql.py +0 -0
  70. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/sdk/resource.py +0 -0
  71. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/telemetry/__init__.py +0 -0
  72. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/telemetry/basic.py +0 -0
  73. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/tests/__init__.py +0 -0
  74. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/tests/desired_responses/test_billing_invoice.txt +0 -0
  75. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/tests/desired_responses/test_billing_status.txt +0 -0
  76. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/tests/desired_responses/test_billing_stop_events_compute.txt +0 -0
  77. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/tests/desired_responses/test_billing_stop_events_volume.txt +0 -0
  78. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/tests/desired_responses/test_compute_list.txt +0 -0
  79. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/tests/desired_responses/test_compute_list_no_labels.txt +0 -0
  80. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/tests/desired_responses/test_tabulate_response.txt +0 -0
  81. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/tests/desired_responses/test_volume_list.txt +0 -0
  82. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/tests/responses_tests.py +0 -0
  83. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/__init__.py +0 -0
  84. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/config_utils.py +0 -0
  85. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/consts/__init__.py +0 -0
  86. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/consts/env_consts.py +0 -0
  87. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/consts/message_consts.py +0 -0
  88. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/cryptography/__init__.py +0 -0
  89. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/cryptography/aes_crypto.py +0 -0
  90. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/cryptography/encryption_module.py +0 -0
  91. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/cryptography/rsa_crypto.py +0 -0
  92. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/get_headers_data.py +0 -0
  93. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/message_utils.py +0 -0
  94. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/prepare_headers.py +0 -0
  95. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/requests_helper.py +0 -0
  96. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgc/utils/update.py +0 -0
  97. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgcsdk.egg-info/dependency_links.txt +0 -0
  98. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgcsdk.egg-info/entry_points.txt +0 -0
  99. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgcsdk.egg-info/requires.txt +0 -0
  100. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/cgcsdk.egg-info/top_level.txt +0 -0
  101. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/pyproject.toml +0 -0
  102. {cgcsdk-1.2.4 → cgcsdk-1.2.6}/setup.py +0 -0
@@ -1,76 +1,76 @@
1
- Metadata-Version: 2.4
2
- Name: cgcsdk
3
- Version: 1.2.4
4
- Summary: CGC Core REST API client
5
- Home-page: https://cgc.comtegra.cloud/
6
- Author: Comtegra AI Team
7
- Author-email: ai@comtegra.pl
8
- License: BSD 2-clause
9
- Project-URL: Documentation, https://docs.cgc.comtegra.cloud/
10
- Project-URL: GitHub, https://git.comtegra.pl/k8s/cgc-client-k8s-cloud
11
- Project-URL: Changelog, https://git.comtegra.pl/k8s/cgc-client-k8s-cloud/-/blob/main/cgc/CHANGELOG.md
12
- Keywords: cloud,sdk,orchestrator,kubernetes,jupyter-notebook,cgc-core
13
- Classifier: Development Status :: 5 - Production/Stable
14
- Classifier: Intended Audience :: Science/Research
15
- Classifier: License :: OSI Approved :: BSD License
16
- Classifier: Operating System :: POSIX :: Linux
17
- Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3.12
20
- Description-Content-Type: text/markdown
21
- License-File: LICENSE
22
- Requires-Dist: click
23
- Requires-Dist: python-dotenv
24
- Requires-Dist: tabulate
25
- Requires-Dist: pycryptodomex
26
- Requires-Dist: paramiko>=2.11
27
- Requires-Dist: statsd
28
- Requires-Dist: requests
29
- Requires-Dist: setuptools
30
- Requires-Dist: colorama
31
- Requires-Dist: psycopg2-binary
32
- Dynamic: author
33
- Dynamic: author-email
34
- Dynamic: classifier
35
- Dynamic: description
36
- Dynamic: description-content-type
37
- Dynamic: home-page
38
- Dynamic: keywords
39
- Dynamic: license
40
- Dynamic: license-file
41
- Dynamic: project-url
42
- Dynamic: requires-dist
43
- Dynamic: summary
44
-
45
- # Comtegra GPU Cloud CLI Client
46
-
47
- ## Basic info
48
-
49
- CGC Clinet is complete solution to create and manage your compute resources through CLI interface and python code. It incorporates CLI and SDK in one package.
50
-
51
- CGC CLI is a command line interface for Comtegra GPU Cloud. CGC CLI enables management of your Comtegra GPU Cloud resources. Current version of the app provides support for compute, storage and network resurces to be created, listed and deleted. Every compute resource is given to you as an URL, which is accessible from open Internet.
52
-
53
- To enable better access to your storage resources, every account has the ability to spawn free of charge filebrowser which is local implementation of dropbox. Remember to mount newely created volumes to it.
54
-
55
- For now, we provide the ability to spawn compute resources like:
56
-
57
- 1. [Jupyter notebook](https://jupyter.org/) with tensorflow or pytorch installed as default
58
- 2. [Triton inferencing server](https://docs.nvidia.com/deeplearning/triton-inference-server/) for large scale inferencing
59
- 3. [Label studio](https://labelstud.io/) for easy management of your data annotation tasks with variety of modes
60
- 4. [Rapids](https://rapids.ai/) suite of accelerated libraries for data processing
61
-
62
- Notebooks are equiped with all CUDA libraries and GPU drivers which enables the usage of GPU for accelerated computations.
63
- Apart from compute resources, we provide the database engines accessible from within your namespace:
64
-
65
- 1. [PostgreSQL](https://www.postgresql.org/)
66
- 2. [Weaviate](https://weaviate.io/)
67
-
68
- More are coming!
69
- Please follow instructions to get started.
70
-
71
- ## More info
72
-
73
- If you'd like to know more visit:
74
-
75
- - [Comtegra GPU Website](https://cgc.comtegra.cloud)
76
- - [Docs](https://docs.cgc.comtegra.cloud)
1
+ Metadata-Version: 2.4
2
+ Name: cgcsdk
3
+ Version: 1.2.6
4
+ Summary: CGC Core REST API client
5
+ Home-page: https://cgc.comtegra.cloud/
6
+ Author: Comtegra AI Team
7
+ Author-email: ai@comtegra.pl
8
+ License: BSD 2-clause
9
+ Project-URL: Documentation, https://docs.cgc.comtegra.cloud/
10
+ Project-URL: GitHub, https://git.comtegra.pl/k8s/cgc-client-k8s-cloud
11
+ Project-URL: Changelog, https://git.comtegra.pl/k8s/cgc-client-k8s-cloud/-/blob/main/cgc/CHANGELOG.md
12
+ Keywords: cloud,sdk,orchestrator,kubernetes,jupyter-notebook,cgc-core
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: BSD License
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: click
23
+ Requires-Dist: python-dotenv
24
+ Requires-Dist: tabulate
25
+ Requires-Dist: pycryptodomex
26
+ Requires-Dist: paramiko>=2.11
27
+ Requires-Dist: statsd
28
+ Requires-Dist: requests
29
+ Requires-Dist: setuptools
30
+ Requires-Dist: colorama
31
+ Requires-Dist: psycopg2-binary
32
+ Dynamic: author
33
+ Dynamic: author-email
34
+ Dynamic: classifier
35
+ Dynamic: description
36
+ Dynamic: description-content-type
37
+ Dynamic: home-page
38
+ Dynamic: keywords
39
+ Dynamic: license
40
+ Dynamic: license-file
41
+ Dynamic: project-url
42
+ Dynamic: requires-dist
43
+ Dynamic: summary
44
+
45
+ # Comtegra GPU Cloud CLI Client
46
+
47
+ ## Basic info
48
+
49
+ CGC Clinet is complete solution to create and manage your compute resources through CLI interface and python code. It incorporates CLI and SDK in one package.
50
+
51
+ CGC CLI is a command line interface for Comtegra GPU Cloud. CGC CLI enables management of your Comtegra GPU Cloud resources. Current version of the app provides support for compute, storage and network resurces to be created, listed and deleted. Every compute resource is given to you as an URL, which is accessible from open Internet.
52
+
53
+ To enable better access to your storage resources, every account has the ability to spawn free of charge filebrowser which is local implementation of dropbox. Remember to mount newely created volumes to it.
54
+
55
+ For now, we provide the ability to spawn compute resources like:
56
+
57
+ 1. [Jupyter notebook](https://jupyter.org/) with tensorflow or pytorch installed as default
58
+ 2. [Triton inferencing server](https://docs.nvidia.com/deeplearning/triton-inference-server/) for large scale inferencing
59
+ 3. [Label studio](https://labelstud.io/) for easy management of your data annotation tasks with variety of modes
60
+ 4. [Rapids](https://rapids.ai/) suite of accelerated libraries for data processing
61
+
62
+ Notebooks are equiped with all CUDA libraries and GPU drivers which enables the usage of GPU for accelerated computations.
63
+ Apart from compute resources, we provide the database engines accessible from within your namespace:
64
+
65
+ 1. [PostgreSQL](https://www.postgresql.org/)
66
+ 2. [Weaviate](https://weaviate.io/)
67
+
68
+ More are coming!
69
+ Please follow instructions to get started.
70
+
71
+ ## More info
72
+
73
+ If you'd like to know more visit:
74
+
75
+ - [Comtegra GPU Website](https://cgc.comtegra.cloud)
76
+ - [Docs](https://docs.cgc.comtegra.cloud)
@@ -6,4 +6,4 @@ CONFIG_FILE_NAME = cfg.json
6
6
  TMP_DIR = .tmp
7
7
  RELEASE = 1
8
8
  MAJOR_VERSION = 2
9
- MINOR_VERSION = 4
9
+ MINOR_VERSION = 6
@@ -1,5 +1,21 @@
1
1
  # Change Log
2
2
 
3
+ ## 1.2.6
4
+
5
+ Release on Apr 30, 2025
6
+
7
+ * `cgc resource scale up` scales up the resource replicas, with the given name
8
+ * `cgc resource scale down` scales down the resource replicas, with the given name
9
+ * modified error message displayed - uses custom_exceptions
10
+ * listing of `TurnedOff` resources is now available
11
+ * `TurnedOn` available if the resource is not running, but it is scaled up
12
+
13
+ ## 1.2.5
14
+
15
+ Release on Apr 16, 2025
16
+
17
+ * `cgc register` now invokes **version check** within registered cluster, to refresh cluster configuration
18
+
3
19
  ## 1.2.4
4
20
 
5
21
  Release on Apr 11, 2025
@@ -27,6 +27,7 @@ from cgc.utils import (
27
27
  require_confirm_loop,
28
28
  find_first_available_config_name,
29
29
  )
30
+ import cgc.utils.version_control as version_control
30
31
 
31
32
 
32
33
  @click.group("api-keys", cls=CustomGroup, hidden=False)
@@ -87,6 +88,7 @@ def auth_register(config_filename: str = "cfg.json"):
87
88
  cgc_secret,
88
89
  )
89
90
  )
91
+ version_control.check_version()
90
92
 
91
93
 
92
94
  @api_keys_group.command("create", cls=CustomCommand)
@@ -62,6 +62,10 @@ def compute_list_response(detailed: bool, data: dict) -> str:
62
62
  pod_list = data["details"]["pods_list"]
63
63
  setup_gauge(f"{get_namespace()}.compute.count", len(pod_list))
64
64
 
65
+ # disabled resources pod list
66
+ other_pods_list = data["details"].get("other_pods_list", [])
67
+ pod_list.extend(other_pods_list)
68
+
65
69
  if not pod_list:
66
70
  raise NoAppsToList()
67
71
 
@@ -156,6 +160,20 @@ def compute_delete_response(data: dict) -> str:
156
160
  return f"App {name} and its service successfully deleted."
157
161
 
158
162
 
163
+ @key_error_decorator_for_helpers
164
+ def compute_scale_response(data: dict) -> str:
165
+ """Create response string for compute scale command.
166
+
167
+ :param response: dict object from API response.
168
+ :type response: requests.Response
169
+ :return: Response string.
170
+ :rtype: str
171
+ """
172
+ name = data["details"]["template_name"]
173
+ replicas = data["details"]["replicas"]
174
+ return f"App {name} has been successfully scaled to {replicas} replicas."
175
+
176
+
159
177
  @key_error_decorator_for_helpers
160
178
  def compute_restart_response(data: dict) -> str:
161
179
  """Create response string for compute restart command.
@@ -83,6 +83,13 @@ def get_app_list(pod_list: list, detailed: bool) -> list:
83
83
  """
84
84
  output_data = []
85
85
 
86
+ def update_output_data_count(pod_name):
87
+ for pod in output_data:
88
+ if pod["name"] == pod_name:
89
+ pod["count"] += 1
90
+ return True
91
+ return False
92
+
86
93
  for pod in pod_list:
87
94
  try:
88
95
  main_container_name = pod["labels"]["entity"]
@@ -94,7 +101,7 @@ def get_app_list(pod_list: list, detailed: bool) -> list:
94
101
  raise Exception(
95
102
  "Parser was unable to find main container in server output in container list"
96
103
  )
97
- volumes_mounted = list_get_mounted_volumes(main_container["mounts"])
104
+ volumes_mounted = list_get_mounted_volumes(main_container.get("mounts", []))
98
105
  limits = main_container["resources"].get("limits")
99
106
  cpu = limits.get("cpu") if limits is not None else 0
100
107
  ram = limits.get("memory") if limits is not None else "0Gi"
@@ -106,6 +113,7 @@ def get_app_list(pod_list: list, detailed: bool) -> list:
106
113
  "volumes_mounted": volumes_mounted,
107
114
  "cpu": cpu,
108
115
  "ram": ram,
116
+ "count": pod.get("replicas", 1), # first in the list are always pods
109
117
  }
110
118
  # getting rid of unwanted and used values
111
119
  if "pod-template-hash" in pod["labels"].keys():
@@ -139,7 +147,9 @@ def get_app_list(pod_list: list, detailed: bool) -> list:
139
147
 
140
148
  # appending the rest of labels
141
149
  pod_data.update(pod["labels"])
142
- output_data.append(pod_data)
150
+
151
+ if not update_output_data_count(pod_data["name"]):
152
+ output_data.append(pod_data)
143
153
  except KeyError:
144
154
  pass
145
155
 
@@ -1,18 +1,18 @@
1
- import click
2
- from cgc.commands.auth.auth_utils import (
3
- _get_jwt_from_server,
4
- )
5
- from cgc.utils.click_group import CustomCommand, CustomGroup
6
-
7
-
8
- @click.group("debug", cls=CustomGroup, hidden=True)
9
- def debug_group():
10
- """
11
- Debug commands for testing.
12
- """
13
- pass
14
-
15
-
16
- @debug_group.command("get-jwt", cls=CustomCommand)
17
- def get_jwt_from_server():
18
- click.echo(_get_jwt_from_server())
1
+ import click
2
+ from cgc.commands.auth.auth_utils import (
3
+ _get_jwt_from_server,
4
+ )
5
+ from cgc.utils.click_group import CustomCommand, CustomGroup
6
+
7
+
8
+ @click.group("debug", cls=CustomGroup, hidden=True)
9
+ def debug_group():
10
+ """
11
+ Debug commands for testing.
12
+ """
13
+ pass
14
+
15
+
16
+ @debug_group.command("get-jwt", cls=CustomCommand)
17
+ def get_jwt_from_server():
18
+ click.echo(_get_jwt_from_server())
@@ -4,6 +4,7 @@ import json
4
4
  from cgc.commands.db.db_models import DatabasesList
5
5
  from cgc.commands.compute.compute_models import ComputesList
6
6
  from cgc.commands.compute.compute_responses import (
7
+ compute_scale_response,
7
8
  template_list_response,
8
9
  template_get_start_path_response,
9
10
  compute_restart_response,
@@ -82,6 +83,63 @@ def compute_restart(name: str):
82
83
  )
83
84
 
84
85
 
86
+ @resource_group.group(name="scale", cls=CustomGroup, hidden=False)
87
+ def scale_group():
88
+ """
89
+ Management of scaling resources replicas.
90
+ """
91
+
92
+
93
+ @scale_group.command("up", cls=CustomCommand)
94
+ @click.argument("name", type=click.STRING)
95
+ # @click.option(
96
+ # "-s",
97
+ # "--scale",
98
+ # "replicas",
99
+ # type=NonNegativeInteger(),
100
+ # required=True,
101
+ # help="Scale factor - number of replicas (must be 0 or greater)",
102
+ # )
103
+ def compute_scale_up(name: str):
104
+ """Scales the specified app up"""
105
+ api_url, headers = get_api_url_and_prepare_headers()
106
+ url = f"{api_url}/v1/api/resource/scale?replicas=1"
107
+ metric = "resource.scale"
108
+ __payload = {"name": name}
109
+ __res = call_api(
110
+ request=EndpointTypes.post,
111
+ url=url,
112
+ headers=headers,
113
+ data=json.dumps(__payload).encode("utf-8"),
114
+ )
115
+ click.echo(
116
+ compute_scale_response(
117
+ retrieve_and_validate_response_send_metric(__res, metric)
118
+ )
119
+ )
120
+
121
+
122
+ @scale_group.command("down", cls=CustomCommand)
123
+ @click.argument("name", type=click.STRING)
124
+ def compute_scale_down(name: str):
125
+ """Scales the specified app down"""
126
+ api_url, headers = get_api_url_and_prepare_headers()
127
+ url = f"{api_url}/v1/api/resource/scale?replicas=0"
128
+ metric = "resource.scale"
129
+ __payload = {"name": name}
130
+ __res = call_api(
131
+ request=EndpointTypes.post,
132
+ url=url,
133
+ headers=headers,
134
+ data=json.dumps(__payload).encode("utf-8"),
135
+ )
136
+ click.echo(
137
+ compute_scale_response(
138
+ retrieve_and_validate_response_send_metric(__res, metric)
139
+ )
140
+ )
141
+
142
+
85
143
  @resource_group.command("ingress", cls=CustomCommand)
86
144
  @click.argument("name", type=click.STRING)
87
145
  def get_resource_ingress(name: str):
@@ -0,0 +1,110 @@
1
+ def list_get_mounted_volumes(volume_list: list) -> str:
2
+ """Formats and returns list of PVC volumes mounted to an app.
3
+
4
+ :param volume_list: list of all volumes mounted to an app
5
+ :type volume_list: list
6
+ :return: list of PVC volumes
7
+ :rtype: str
8
+ """
9
+ volume_name_list = []
10
+ for volume in volume_list:
11
+ volume_type = volume.get("type")
12
+ if volume_type == "PVC":
13
+ volume_name = volume.get("name")
14
+ volume_name_list.append(volume_name)
15
+ volumes_mounted = (
16
+ ", ".join(volume_name_list) if len(volume_name_list) != 0 else None
17
+ )
18
+ return volumes_mounted
19
+
20
+
21
+ def get_job_json_data(job_list: list):
22
+ """Formats and returns list of jobs to print.
23
+
24
+ :param job_list: list of jobs
25
+ :type job_list: list
26
+ :return: formatted list of jobs
27
+ :rtype: list
28
+ """
29
+ output_data = []
30
+
31
+ for job in job_list:
32
+ try:
33
+ main_container_name = "custom-job"
34
+ try:
35
+ main_container = [
36
+ x
37
+ for x in job.get("containers", [])
38
+ if x.get("name") == main_container_name
39
+ ][0]
40
+ except IndexError:
41
+ raise Exception(
42
+ "Parser was unable to find main container in server output in container list"
43
+ )
44
+ volumes_mounted = list_get_mounted_volumes(main_container.get("mounts", []))
45
+ limits = main_container.get("resources", {}).get("limits")
46
+ cpu = limits.get("cpu") if limits is not None else 0
47
+ ram = limits.get("memory") if limits is not None else "0Gi"
48
+
49
+ job_data = {
50
+ "name": job.get("labels", {}).get("app-name"),
51
+ "status": job.get("status", {}).get("phase", "Unknown"),
52
+ "volumes_mounted": volumes_mounted,
53
+ "cpu": cpu,
54
+ "ram": ram,
55
+ }
56
+ # getting rid of unwanted and used values
57
+ if "pod-template-hash" in job["labels"].keys():
58
+ job["labels"].pop("pod-template-hash")
59
+ job["labels"].pop("entity")
60
+
61
+ # appending the rest of labels
62
+ job_data.update(job["labels"])
63
+ output_data.append(job_data)
64
+ except KeyError:
65
+ pass
66
+
67
+ return output_data
68
+
69
+
70
+ def get_job_list(job_list: list, job_pod_list: list):
71
+ list_of_json_job_data = get_job_json_data(job_list)
72
+
73
+ for i, job_data in enumerate(job_list):
74
+ list_of_json_job_data[i]["name"] = job_data.get("name", "")
75
+ list_of_json_job_data[i]["ttl"] = job_data.get(
76
+ "ttl_seconds_after_finished", "N/A"
77
+ )
78
+ list_of_json_job_data[i]["ads"] = job_data.get("active_deadline_seconds", "N/A")
79
+ for job in list_of_json_job_data:
80
+ for job_pod in job_pod_list:
81
+ job_pod_labels: dict = job_pod.get("labels", {})
82
+ print(job_pod.get("labels"))
83
+ if job_pod_labels.get("app-name", "") == job.get("name"):
84
+ if job["status"] is not None and job["status"] == "Unknown":
85
+ job["status"] = job_pod["status"] # try to get status from pod
86
+ elif job["status"] is None: # support older server versions
87
+ job["status"] = job_pod["status"]
88
+ job["gpu-count"] = job_pod_labels.get("gpu-count", 0)
89
+ job["gpu-label"] = job_pod_labels.get("gpu-label", "N/A")
90
+ break
91
+
92
+ return list_of_json_job_data
93
+
94
+
95
+ def main():
96
+ import json
97
+
98
+ with open("test.json") as f:
99
+ response_data = json.load(f)
100
+
101
+ job_list = response_data.get("details", {}).get("job_list", [])
102
+ job_pod_list = response_data.get("details", {}).get("job_pod_list", [])
103
+
104
+ _list_of_json_job_data = get_job_list(job_list, job_pod_list)
105
+
106
+ # print(list_of_json_job_data)
107
+
108
+
109
+ if __name__ == "__main__":
110
+ main()
@@ -17,3 +17,16 @@ class CustomCommand(click.Command):
17
17
  pieces = self.collect_usage_pieces(ctx)
18
18
  cmd_path = ctx.command_path.removeprefix("python -m ")
19
19
  formatter.write_usage(cmd_path, " ".join(pieces))
20
+
21
+
22
+ class NonNegativeInteger(click.types.IntParamType):
23
+ """A parameter that only accepts non-negative integers."""
24
+
25
+ name = "non-negative-integer"
26
+
27
+ def convert(self, value, param, ctx):
28
+ # First convert using the parent class method
29
+ result = super().convert(value, param, ctx)
30
+ if result < 0:
31
+ self.fail(f"{value} is not a non-negative integer", param, ctx)
32
+ return result
@@ -5,12 +5,15 @@ CUSTOM_EXCEPTIONS = {
5
5
  500: {
6
6
  "UNDEFINED": "undefined exception",
7
7
  "USER_KEY_CREATE_ERROR": "Error while creating key",
8
+ "RESOURCE_SCALE_TEMPLATE_ERROR": "Error while scaling resource - resource not fully compatible CGC",
8
9
  },
9
10
  413: {
10
11
  "PVC_CREATE_STORAGE_LIMIT_EXCEEDED": "This request exceeds your storage limits",
11
12
  "PVC_CREATE_NOT_ENOUGH_STORAGE_IN_CLUSTER": "No more storage available",
12
13
  "REQUEST_RESOURCE_LIMIT_EXCEEDED": "This request exceeds your resources limit",
13
14
  "RESOURCES_NOT_AVAILABLE_IN_CLUSTER": "Requested resources not available",
15
+ "RESOURCE_SCALE_RESOURCES_LIMIT_EXCEEDED": "This request exceeds your resources limit",
16
+ "PVC_CREATE_STORAGE_LIMIT_EXCEEDED": "Storage limit exceeded",
14
17
  },
15
18
  409: {
16
19
  "PVC_NAME_ALREADY_EXISTS": "Volume with this name already exists.",
@@ -19,13 +22,14 @@ CUSTOM_EXCEPTIONS = {
19
22
  "RESOURCE_TEMPLATE_NAME_ALREADY_EXISTS": "Resource with this name already exists.",
20
23
  "JOB_CREATE_ALREADY_EXISTS": "Job with this name already exists.",
21
24
  "USER_KEY_ALREADY_EXISTS": "Key with these data already exists.",
25
+ "AlreadyExists": "Object with this name already exists",
22
26
  },
23
27
  404: {
24
28
  "PVC_CREATE_NO_SC": "Selected disk type and access mode unavailable",
25
29
  "BILLING_STATUS_NO_DATA": "No data to print.",
26
30
  "NOT_DELETED_ANYTHING_IN_COMPUTE_DELETE": "No app with this name to delete.",
27
31
  "API_KEY_DELETE_ERROR": "No api key with this id to delete",
28
- "PVC_MOUNT_NOT_FOUND_TEMPLATE": "No app with this name to mount.",
32
+ "PVC_MOUNT_NOT_FOUND_TEMPLATE": "No volume with this name to mount.",
29
33
  "PVC_UNMOUNT_NOT_MOUNTED": "Volume with this name is not mounted.",
30
34
  "PVC_NOT_FOUND": "Volume with this name not found.",
31
35
  "PVC_DELETE_NOT_FOUND": "App with this name not found.",
@@ -36,6 +40,13 @@ CUSTOM_EXCEPTIONS = {
36
40
  "JOB_NOT_FOUND": "Job with this name not found.",
37
41
  "RESOURCE_NOT_FOUND": "Resource with this name not found.",
38
42
  "USER_KEY_NOT_FOUND": "Key with this id not found.",
43
+ "RESOURCE_SCALE_TEMPLATE_NOT_FOUND": "No app with this name.",
44
+ "NotFound": "Resource not found",
45
+ "USER_SECRET_UPDATE_NOT_FOUND": "Secret not found.",
46
+ "USER_SECRET_DELETE_NOT_FOUND": "Secret not found.",
47
+ "PVC_SC_NOT_FOUND": "Storage class with this name is not defined.",
48
+ "RESOURCE_RESTART_TEMPLATE_NOT_FOUND": "Resource with this name not found",
49
+ "NOT_DELETED_ANYTHING_IN_RESOURCE_DELETE": "There is nothing to delete with this name",
39
50
  },
40
51
  400: {
41
52
  "WRONG_DATE_FORMAT": "Wrong date format.",
@@ -43,5 +54,6 @@ CUSTOM_EXCEPTIONS = {
43
54
  "PVC_MOUNT_ALREADY_MOUNTED": "This volume is already mounted.",
44
55
  "TEMPLATE_NAME_SYSTEM_RESERVED": "You can't create app with this name.",
45
56
  "JOB_LACKS_REQUIRED_PARAMETER": "Job requires container image parameter.",
57
+ "RESOURCE_PORTS_EXCEPTION": "Resource with this name not found",
46
58
  },
47
59
  }
@@ -118,9 +118,12 @@ def retrieve_and_validate_response_send_metric(
118
118
  else:
119
119
  try:
120
120
  response_json = response.json()
121
- if "details" in response_json:
122
- click.echo(prepare_error_message(response_json["details"]))
123
- else:
121
+ status_code = response.status_code
122
+ reason = response_json.get("reason", "")
123
+ if (
124
+ status_code in CUSTOM_EXCEPTIONS
125
+ and reason in CUSTOM_EXCEPTIONS[status_code]
126
+ ):
124
127
  click.echo(
125
128
  prepare_error_message(
126
129
  CUSTOM_EXCEPTIONS[response.status_code][
@@ -128,6 +131,10 @@ def retrieve_and_validate_response_send_metric(
128
131
  ]
129
132
  )
130
133
  )
134
+ elif "details" in response_json:
135
+ click.echo(prepare_error_message(response_json["details"]))
136
+ else:
137
+ raise KeyError("No specific error message or details field found.")
131
138
  except KeyError:
132
139
  error_message = _get_response_json_error_message(response_json)
133
140
  if isinstance(error_message, str):
@@ -38,7 +38,7 @@ def get_server_version():
38
38
 
39
39
 
40
40
  def print_compare_versions(server_version: str, client_version: str):
41
- click.echo(f"Available version: {server_version}")
41
+ click.echo(f"Server version: {server_version}")
42
42
  click.echo(f"Installed version: {client_version}")
43
43
 
44
44
 
@@ -1,76 +1,76 @@
1
- Metadata-Version: 2.4
2
- Name: cgcsdk
3
- Version: 1.2.4
4
- Summary: CGC Core REST API client
5
- Home-page: https://cgc.comtegra.cloud/
6
- Author: Comtegra AI Team
7
- Author-email: ai@comtegra.pl
8
- License: BSD 2-clause
9
- Project-URL: Documentation, https://docs.cgc.comtegra.cloud/
10
- Project-URL: GitHub, https://git.comtegra.pl/k8s/cgc-client-k8s-cloud
11
- Project-URL: Changelog, https://git.comtegra.pl/k8s/cgc-client-k8s-cloud/-/blob/main/cgc/CHANGELOG.md
12
- Keywords: cloud,sdk,orchestrator,kubernetes,jupyter-notebook,cgc-core
13
- Classifier: Development Status :: 5 - Production/Stable
14
- Classifier: Intended Audience :: Science/Research
15
- Classifier: License :: OSI Approved :: BSD License
16
- Classifier: Operating System :: POSIX :: Linux
17
- Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3.12
20
- Description-Content-Type: text/markdown
21
- License-File: LICENSE
22
- Requires-Dist: click
23
- Requires-Dist: python-dotenv
24
- Requires-Dist: tabulate
25
- Requires-Dist: pycryptodomex
26
- Requires-Dist: paramiko>=2.11
27
- Requires-Dist: statsd
28
- Requires-Dist: requests
29
- Requires-Dist: setuptools
30
- Requires-Dist: colorama
31
- Requires-Dist: psycopg2-binary
32
- Dynamic: author
33
- Dynamic: author-email
34
- Dynamic: classifier
35
- Dynamic: description
36
- Dynamic: description-content-type
37
- Dynamic: home-page
38
- Dynamic: keywords
39
- Dynamic: license
40
- Dynamic: license-file
41
- Dynamic: project-url
42
- Dynamic: requires-dist
43
- Dynamic: summary
44
-
45
- # Comtegra GPU Cloud CLI Client
46
-
47
- ## Basic info
48
-
49
- CGC Clinet is complete solution to create and manage your compute resources through CLI interface and python code. It incorporates CLI and SDK in one package.
50
-
51
- CGC CLI is a command line interface for Comtegra GPU Cloud. CGC CLI enables management of your Comtegra GPU Cloud resources. Current version of the app provides support for compute, storage and network resurces to be created, listed and deleted. Every compute resource is given to you as an URL, which is accessible from open Internet.
52
-
53
- To enable better access to your storage resources, every account has the ability to spawn free of charge filebrowser which is local implementation of dropbox. Remember to mount newely created volumes to it.
54
-
55
- For now, we provide the ability to spawn compute resources like:
56
-
57
- 1. [Jupyter notebook](https://jupyter.org/) with tensorflow or pytorch installed as default
58
- 2. [Triton inferencing server](https://docs.nvidia.com/deeplearning/triton-inference-server/) for large scale inferencing
59
- 3. [Label studio](https://labelstud.io/) for easy management of your data annotation tasks with variety of modes
60
- 4. [Rapids](https://rapids.ai/) suite of accelerated libraries for data processing
61
-
62
- Notebooks are equiped with all CUDA libraries and GPU drivers which enables the usage of GPU for accelerated computations.
63
- Apart from compute resources, we provide the database engines accessible from within your namespace:
64
-
65
- 1. [PostgreSQL](https://www.postgresql.org/)
66
- 2. [Weaviate](https://weaviate.io/)
67
-
68
- More are coming!
69
- Please follow instructions to get started.
70
-
71
- ## More info
72
-
73
- If you'd like to know more visit:
74
-
75
- - [Comtegra GPU Website](https://cgc.comtegra.cloud)
76
- - [Docs](https://docs.cgc.comtegra.cloud)
1
+ Metadata-Version: 2.4
2
+ Name: cgcsdk
3
+ Version: 1.2.6
4
+ Summary: CGC Core REST API client
5
+ Home-page: https://cgc.comtegra.cloud/
6
+ Author: Comtegra AI Team
7
+ Author-email: ai@comtegra.pl
8
+ License: BSD 2-clause
9
+ Project-URL: Documentation, https://docs.cgc.comtegra.cloud/
10
+ Project-URL: GitHub, https://git.comtegra.pl/k8s/cgc-client-k8s-cloud
11
+ Project-URL: Changelog, https://git.comtegra.pl/k8s/cgc-client-k8s-cloud/-/blob/main/cgc/CHANGELOG.md
12
+ Keywords: cloud,sdk,orchestrator,kubernetes,jupyter-notebook,cgc-core
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: BSD License
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: click
23
+ Requires-Dist: python-dotenv
24
+ Requires-Dist: tabulate
25
+ Requires-Dist: pycryptodomex
26
+ Requires-Dist: paramiko>=2.11
27
+ Requires-Dist: statsd
28
+ Requires-Dist: requests
29
+ Requires-Dist: setuptools
30
+ Requires-Dist: colorama
31
+ Requires-Dist: psycopg2-binary
32
+ Dynamic: author
33
+ Dynamic: author-email
34
+ Dynamic: classifier
35
+ Dynamic: description
36
+ Dynamic: description-content-type
37
+ Dynamic: home-page
38
+ Dynamic: keywords
39
+ Dynamic: license
40
+ Dynamic: license-file
41
+ Dynamic: project-url
42
+ Dynamic: requires-dist
43
+ Dynamic: summary
44
+
45
+ # Comtegra GPU Cloud CLI Client
46
+
47
+ ## Basic info
48
+
49
+ CGC Clinet is complete solution to create and manage your compute resources through CLI interface and python code. It incorporates CLI and SDK in one package.
50
+
51
+ CGC CLI is a command line interface for Comtegra GPU Cloud. CGC CLI enables management of your Comtegra GPU Cloud resources. Current version of the app provides support for compute, storage and network resurces to be created, listed and deleted. Every compute resource is given to you as an URL, which is accessible from open Internet.
52
+
53
+ To enable better access to your storage resources, every account has the ability to spawn free of charge filebrowser which is local implementation of dropbox. Remember to mount newely created volumes to it.
54
+
55
+ For now, we provide the ability to spawn compute resources like:
56
+
57
+ 1. [Jupyter notebook](https://jupyter.org/) with tensorflow or pytorch installed as default
58
+ 2. [Triton inferencing server](https://docs.nvidia.com/deeplearning/triton-inference-server/) for large scale inferencing
59
+ 3. [Label studio](https://labelstud.io/) for easy management of your data annotation tasks with variety of modes
60
+ 4. [Rapids](https://rapids.ai/) suite of accelerated libraries for data processing
61
+
62
+ Notebooks are equiped with all CUDA libraries and GPU drivers which enables the usage of GPU for accelerated computations.
63
+ Apart from compute resources, we provide the database engines accessible from within your namespace:
64
+
65
+ 1. [PostgreSQL](https://www.postgresql.org/)
66
+ 2. [Weaviate](https://weaviate.io/)
67
+
68
+ More are coming!
69
+ Please follow instructions to get started.
70
+
71
+ ## More info
72
+
73
+ If you'd like to know more visit:
74
+
75
+ - [Comtegra GPU Website](https://cgc.comtegra.cloud)
76
+ - [Docs](https://docs.cgc.comtegra.cloud)
@@ -8,7 +8,6 @@ cgc/CHANGELOG.md
8
8
  cgc/__init__.py
9
9
  cgc/cgc.py
10
10
  cgc/config.py
11
- cgc/server.crt
12
11
  cgc/commands/__init__.py
13
12
  cgc/commands/cgc_cmd.py
14
13
  cgc/commands/cgc_cmd_responses.py
@@ -65,6 +64,7 @@ cgc/telemetry/__init__.py
65
64
  cgc/telemetry/basic.py
66
65
  cgc/tests/__init__.py
67
66
  cgc/tests/responses_tests.py
67
+ cgc/tests/test.py
68
68
  cgc/tests/desired_responses/test_billing_invoice.txt
69
69
  cgc/tests/desired_responses/test_billing_status.txt
70
70
  cgc/tests/desired_responses/test_billing_stop_events_compute.txt
@@ -1,4 +1,4 @@
1
- [egg_info]
2
- tag_build =
3
- tag_date = 0
4
-
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -1,24 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIEAzCCAuugAwIBAgIUUuH/XkkpMqjKlF+XOgEsru7pzvgwDQYJKoZIhvcNAQEL
3
- BQAwgZAxCzAJBgNVBAYTAlBMMRQwEgYDVQQIDAtNYXpvd2llY2tpZTEPMA0GA1UE
4
- BwwGV2Fyc2F3MRYwFAYDVQQKDA1Db210ZWdyYSBTLkEuMQswCQYDVQQLDAJBSTEW
5
- MBQGA1UEAwwNNzcuNzkuMjUxLjE2MzEdMBsGCSqGSIb3DQEJARYOYWlAY29tdGVn
6
- cmEucGwwHhcNMjMwMjA2MTIyNzQ5WhcNMjQwMjA2MTIyNzQ5WjCBkDELMAkGA1UE
7
- BhMCUEwxFDASBgNVBAgMC01hem93aWVja2llMQ8wDQYDVQQHDAZXYXJzYXcxFjAU
8
- BgNVBAoMDUNvbXRlZ3JhIFMuQS4xCzAJBgNVBAsMAkFJMRYwFAYDVQQDDA03Ny43
9
- OS4yNTEuMTYzMR0wGwYJKoZIhvcNAQkBFg5haUBjb210ZWdyYS5wbDCCASIwDQYJ
10
- KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMtup3I3xk700/PCEX09vQTdYRPqOKTo
11
- AeuCafRcG+9BHeLS3JRQh/dBAUhxEDEcVZ9jycuHHOnth5qnbyUSS3P/Xeqmhru8
12
- nUxUHdDjIUY/rMD216gWLjR59NnxGTLWhidZChuJa2pqV/+r+QaeMda+lDZJRImv
13
- jPhbDvFl1rGg86VZD0/5ArEKaAcreMH9zteNJ9cVmMqYMelIqiz84d+2UAQghsip
14
- KIngfyoRBuF8WsefeKCpjPJ+00dprjmVt9ZAZIfGBNVlwfoDLhjnAUp4y4tXfah8
15
- okfIJmmK6tHYqxMgemrvvAjIawaxGf8WnolvYsMF6BhRNYzT92dvYJECAwEAAaNT
16
- MFEwHQYDVR0OBBYEFPvwDwK7QGY5hedW3lm9knWCQomaMB8GA1UdIwQYMBaAFPvw
17
- DwK7QGY5hedW3lm9knWCQomaMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
18
- BQADggEBAByTQ7uOem05VL1nB/8Kjv8egUpzoaVFzDg/Lwy5XWtUzjip1rLNlRkX
19
- dkQbhDizE8DwpnXtjMdyTqvBWABWnKvtTcbRHDAucOJTxSXd1MDd4TAYKPzyL+0L
20
- yDDbvL6tN2tHBJX8XHfk1lilYD13DeAZ58Ou1cXUE45bPt/UAQjY9IlFaxY14drg
21
- Gt5rQGK9MBfYpGfDV7/9s3ANRZ2gI+btXB8B7ixOMLmlWmZavo9hqz++gWT0agXf
22
- TsR1pc6n5fC8tyky6sCSPaeINp+Rj1LNNwebbvIn547608yuoGxt6YPy+RgXnX/t
23
- F4d0ft9YBUNomEaxBpmkQ1nFcV8oe9Q=
24
- -----END CERTIFICATE-----
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes