ciocore 8.0.1__py2.py3-none-any.whl → 8.1.0__py2.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 ciocore might be problematic. Click here for more details.
- ciocore/VERSION +1 -1
- ciocore/api_client.py +223 -1
- ciocore/docsite/apidoc/api_client/index.html +266 -0
- ciocore/docsite/objects.inv +0 -0
- ciocore/docsite/search/search_index.json +1 -1
- ciocore/docsite/sitemap.xml.gz +0 -0
- {ciocore-8.0.1.dist-info → ciocore-8.1.0.dist-info}/METADATA +5 -1
- {ciocore-8.0.1.dist-info → ciocore-8.1.0.dist-info}/RECORD +12 -12
- tests/test_api_client.py +174 -1
- {ciocore-8.0.1.dist-info → ciocore-8.1.0.dist-info}/WHEEL +0 -0
- {ciocore-8.0.1.dist-info → ciocore-8.1.0.dist-info}/entry_points.txt +0 -0
- {ciocore-8.0.1.dist-info → ciocore-8.1.0.dist-info}/top_level.txt +0 -0
ciocore/docsite/sitemap.xml.gz
CHANGED
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ciocore
|
|
3
|
-
Version: 8.0
|
|
3
|
+
Version: 8.1.0
|
|
4
4
|
Summary: Core functionality for Conductor's client tools
|
|
5
5
|
Home-page: https://github.com/ConductorTechnologies/ciocore
|
|
6
6
|
Author: conductor
|
|
@@ -51,6 +51,10 @@ See [CONTRIBUTING](CONTRIBUTING.md)
|
|
|
51
51
|
|
|
52
52
|
## Changelog
|
|
53
53
|
|
|
54
|
+
## Version:8.1.0 -- 10 Jun 2024
|
|
55
|
+
|
|
56
|
+
* Adds two new calls to the API to get usage; get_compute_usage() and get_storage_usage()
|
|
57
|
+
|
|
54
58
|
## Version:8.0.1 -- 22 Apr 2024
|
|
55
59
|
|
|
56
60
|
* The uploader now sends all error messages to the dashboard - not just the first error.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
ciocore/VERSION,sha256=
|
|
1
|
+
ciocore/VERSION,sha256=tLQREuN8_s0dGaKmIQt0W8MTSuMhtDpdcGwzW80I8nk,5
|
|
2
2
|
ciocore/__init__.py,sha256=aTP7LeeosQA8BZE67gDV4jgfTK5zxmwZRjiTRu_ZWj0,646
|
|
3
|
-
ciocore/api_client.py,sha256=
|
|
3
|
+
ciocore/api_client.py,sha256=SBxEwAiwn2XtH7T_ipefUbWhczXjoNdNbQBur1RV-Bw,32810
|
|
4
4
|
ciocore/cli.py,sha256=jZ1lOKQiUcrMhsVmD9SVmPMFwHtgDF4SaoAf2-PBS54,15449
|
|
5
5
|
ciocore/client_db.py,sha256=tTz3bl2xeDPPcYSDS3g3QgV_xYihJMx0Kj6OeN2klK0,12978
|
|
6
6
|
ciocore/common.py,sha256=mBIS6KiYoQsjWe6aIFUGRRvCMl8BIN2kmLZ4J8icap8,14982
|
|
@@ -24,10 +24,10 @@ ciocore/auth/server.py,sha256=8btX9-EokUl6q55V8muDmEV2tvvbTBD0BHeWFbwkzUc,3892
|
|
|
24
24
|
ciocore/docsite/404.html,sha256=zUCnDe9r5yFZh8MXcTmzDaFyYBuRHz1gvuyJS2rYiTI,17207
|
|
25
25
|
ciocore/docsite/index.html,sha256=xz215H_KHWBYI1HT7IRpAZ4d1ptUiO8Y4DlOmbEPgPk,20945
|
|
26
26
|
ciocore/docsite/logo.png,sha256=gArgFFWdw8w985-0TkuGIgU_pW9sziEMZdqytXb5WLo,2825
|
|
27
|
-
ciocore/docsite/objects.inv,sha256=
|
|
27
|
+
ciocore/docsite/objects.inv,sha256=XwmLactPEWWC4fAWqHNPBXGsluRxLLTrwDLQqq51ONY,775
|
|
28
28
|
ciocore/docsite/sitemap.xml,sha256=M_V85zl0y2adRvzJAnoCxlZH_Hl7TLnIb1A-6l_xGmI,109
|
|
29
|
-
ciocore/docsite/sitemap.xml.gz,sha256=
|
|
30
|
-
ciocore/docsite/apidoc/api_client/index.html,sha256=
|
|
29
|
+
ciocore/docsite/sitemap.xml.gz,sha256=rZcI755TcvgYJvqQWgKtBrKCVKxIJd1pLTDyxi4NFv8,127
|
|
30
|
+
ciocore/docsite/apidoc/api_client/index.html,sha256=mh9VwU1J3Ks6MWvo5a-PcUt5GYdm8s7KsIVDWfnOeXY,188372
|
|
31
31
|
ciocore/docsite/apidoc/apidoc/index.html,sha256=KGsHBY6GBF380w338GfOIMWnwAyyLvw2i1RQFORdwlE,26171
|
|
32
32
|
ciocore/docsite/apidoc/config/index.html,sha256=n3koKPRUza5-uHUt8hK8H8XyH6HG_U2CsGobdaN4KfY,72559
|
|
33
33
|
ciocore/docsite/apidoc/data/index.html,sha256=QhqiXUd_3qk_jGRYB5JiqlJTem8Jg7aKa5mPPDT1978,50850
|
|
@@ -81,7 +81,7 @@ ciocore/docsite/cmdline/downloader/index.html,sha256=917XE3waukGnIXI9qxl0zYEf3vH
|
|
|
81
81
|
ciocore/docsite/cmdline/packages/index.html,sha256=Ssb2R7eSubBNR824oc3jjhJfrG3JKOPojA-uiAczgeQ,20923
|
|
82
82
|
ciocore/docsite/cmdline/uploader/index.html,sha256=TtLbHNlu4ofZ4bQBqam87RelWdHnVDSL7_rw_YqBbC8,25123
|
|
83
83
|
ciocore/docsite/how-to-guides/index.html,sha256=rF-DMyk4k_jGUJRF3dKtMMiOgXS8OvBqAn-zxWy3AGs,20100
|
|
84
|
-
ciocore/docsite/search/search_index.json,sha256=
|
|
84
|
+
ciocore/docsite/search/search_index.json,sha256=vBLU-rkC0pxOPX0O3MNKXRKGfgsaS1-91KsV17Gf9SY,189092
|
|
85
85
|
ciocore/docsite/stylesheets/extra.css,sha256=_Cxe9Dhg1BBi6Kqaz_iZD9z9VyqxA9vtONRjP4PVic0,354
|
|
86
86
|
ciocore/docsite/stylesheets/tables.css,sha256=LE_zwGRxGcdPIy-9QiVPecOzlEBSqZb_WP5vDkFE0ZM,3235
|
|
87
87
|
ciocore/downloader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -103,7 +103,7 @@ tests/extra_env_fixtures.py,sha256=8qvU4d8SXGKzRVNR5whVqKCQOwOVMiFVfbKBAjxa2gE,1
|
|
|
103
103
|
tests/instance_type_fixtures.py,sha256=uIzQduqKQVgjllMuyXaYnRC-pwqk5lnTx3NY2M5Nujo,4320
|
|
104
104
|
tests/package_fixtures.py,sha256=CsJnhB7oYzIxJH7b1tCOPyvnnVSCqEbSPhtCnsHL-nA,5070
|
|
105
105
|
tests/project_fixtures.py,sha256=iBm_th_JtAw76vlNu7Jjhh9tLH4oOaNi-MgtPzCV7yQ,138
|
|
106
|
-
tests/test_api_client.py,sha256=
|
|
106
|
+
tests/test_api_client.py,sha256=4jhj-YrBPcLj7XZn3ngguau2DPxpCYGMSuqPJ3hW0GQ,14497
|
|
107
107
|
tests/test_base_downloader.py,sha256=SS7tWKv2ZZhpUDk4UCg1TkrNrpntjSewgzLl1mEubSE,3603
|
|
108
108
|
tests/test_cli.py,sha256=_WTs2SWlEgd6wtg1hmOBlFnbWVdFLvqp0KqNhy-y2e8,5532
|
|
109
109
|
tests/test_common.py,sha256=tY_-SY-JmJX09UehFs9RIDqZ785AmhfTl6eVKJeIUFY,763
|
|
@@ -120,8 +120,8 @@ tests/test_uploader.py,sha256=B1llTJt_fqR6e_V_Jxfw9z73QgkFlEPU87xLYGzt-TQ,2914
|
|
|
120
120
|
tests/test_validator.py,sha256=2fY66ayNc08PGyj2vTI-V_1yeCWJDngkj2zkUM5TTCI,1526
|
|
121
121
|
tests/mocks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
122
122
|
tests/mocks/glob.py,sha256=J2MH7nqi6NJOHuGdVWxhfeBd700_Ckj6cLh_8jSNkfg,215
|
|
123
|
-
ciocore-8.0.
|
|
124
|
-
ciocore-8.0.
|
|
125
|
-
ciocore-8.0.
|
|
126
|
-
ciocore-8.0.
|
|
127
|
-
ciocore-8.0.
|
|
123
|
+
ciocore-8.1.0.dist-info/METADATA,sha256=lXpW_6Xfu_wAL__6D_ePH3DcB7oyBRtIMNvv_3sK3bo,18564
|
|
124
|
+
ciocore-8.1.0.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
|
|
125
|
+
ciocore-8.1.0.dist-info/entry_points.txt,sha256=cCqcALMYbC4d8545V9w0Zysfg9MVuKWhzDQ2er4UfGE,47
|
|
126
|
+
ciocore-8.1.0.dist-info/top_level.txt,sha256=SvlM5JlqULzAz00JZWfiUhfjhqDzYzSWssA87zdJl0o,14
|
|
127
|
+
ciocore-8.1.0.dist-info/RECORD,,
|
tests/test_api_client.py
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
isort:skip_file
|
|
4
4
|
"""
|
|
5
|
+
import datetime
|
|
6
|
+
import json
|
|
5
7
|
import sys
|
|
6
8
|
import unittest
|
|
7
|
-
|
|
9
|
+
|
|
8
10
|
try:
|
|
9
11
|
from unittest import mock
|
|
10
12
|
except ImportError:
|
|
@@ -13,6 +15,8 @@ except ImportError:
|
|
|
13
15
|
from ciocore import api_client
|
|
14
16
|
|
|
15
17
|
from ciocore.api_client import request_extra_environment
|
|
18
|
+
from ciocore.api_client import _get_compute_usage, get_compute_usage
|
|
19
|
+
from ciocore.api_client import _get_storage_usage, get_storage_usage
|
|
16
20
|
|
|
17
21
|
class ApiClientTest(unittest.TestCase):
|
|
18
22
|
@staticmethod
|
|
@@ -164,3 +168,172 @@ class TestRequestExtraEnvironment(unittest.TestCase):
|
|
|
164
168
|
|
|
165
169
|
self.assertEqual("Error: Could not get account environment!", str(context.exception))
|
|
166
170
|
mock_ApiClient.assert_called_once()
|
|
171
|
+
|
|
172
|
+
class TestGetComputeUsage(unittest.TestCase):
|
|
173
|
+
|
|
174
|
+
def setUp(self):
|
|
175
|
+
|
|
176
|
+
# Precison is rounded to 4 places to avoid FP issues.
|
|
177
|
+
self.compute_response_data = {
|
|
178
|
+
"data": [
|
|
179
|
+
{
|
|
180
|
+
"cores": 0.5,
|
|
181
|
+
"instance_cost": 0.0200,
|
|
182
|
+
"license_cost": 0.0200,
|
|
183
|
+
"minutes": 6.9700,
|
|
184
|
+
"self_link": 0,
|
|
185
|
+
"start_time": "Tue, 09 Jan 2024 18:00:00 GMT"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"cores": 0.4,
|
|
189
|
+
"instance_cost": 0.0200,
|
|
190
|
+
"license_cost": 0.0200,
|
|
191
|
+
"minutes": 6.9600,
|
|
192
|
+
"self_link": 1,
|
|
193
|
+
"start_time": "Tue, 09 Jan 2024 19:00:00 GMT"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"cores": 0.9613,
|
|
197
|
+
"instance_cost": 0.0400,
|
|
198
|
+
"license_cost": 0.0800,
|
|
199
|
+
"minutes": 7.2100,
|
|
200
|
+
"self_link": 2,
|
|
201
|
+
"start_time": "Tue, 16 Jan 2024 17:00:00 GMT"
|
|
202
|
+
},
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
self.response_ok = mock.MagicMock(status_code=200, text=json.dumps(self.compute_response_data))
|
|
207
|
+
self.response_error = mock.MagicMock(status_code=500, text=json.dumps({"error": "Internal Server Error"}))
|
|
208
|
+
|
|
209
|
+
@mock.patch("ciocore.api_client.ApiClient")
|
|
210
|
+
@mock.patch("ciocore.api_client.read_conductor_credentials")
|
|
211
|
+
@mock.patch("ciocore.api_client.account_id_from_jwt")
|
|
212
|
+
def test_query_raw_compute_usage(self, mock_account_id_from_jwt, mock_read_conductor_credentials, mock_ApiClient):
|
|
213
|
+
# Set up mocks for successful execution
|
|
214
|
+
mock_read_conductor_credentials.return_value = "valid_token"
|
|
215
|
+
mock_account_id_from_jwt.return_value = "123"
|
|
216
|
+
mock_api_instance = mock_ApiClient.return_value
|
|
217
|
+
mock_api_instance.make_request.return_value = (self.response_ok.text, self.response_ok.status_code)
|
|
218
|
+
|
|
219
|
+
start_time = datetime.datetime(2024, 1, 1)
|
|
220
|
+
end_time = datetime.datetime(2024, 3, 20)
|
|
221
|
+
|
|
222
|
+
result = _get_compute_usage(start_time, end_time)
|
|
223
|
+
|
|
224
|
+
self.assertEqual(result, self.compute_response_data['data'])
|
|
225
|
+
|
|
226
|
+
@mock.patch("ciocore.api_client.ApiClient")
|
|
227
|
+
@mock.patch("ciocore.api_client.read_conductor_credentials")
|
|
228
|
+
@mock.patch("ciocore.api_client.account_id_from_jwt")
|
|
229
|
+
def test_compute_usage(self, mock_account_id_from_jwt, mock_read_conductor_credentials, mock_ApiClient):
|
|
230
|
+
# Set up mocks for successful execution
|
|
231
|
+
mock_read_conductor_credentials.return_value = "valid_token"
|
|
232
|
+
mock_account_id_from_jwt.return_value = "123"
|
|
233
|
+
mock_api_instance = mock_ApiClient.return_value
|
|
234
|
+
mock_api_instance.make_request.return_value = (self.response_ok.text, self.response_ok.status_code)
|
|
235
|
+
|
|
236
|
+
start_time = datetime.datetime(2024, 1, 1)
|
|
237
|
+
end_time = datetime.datetime(2024, 3, 20)
|
|
238
|
+
|
|
239
|
+
result = get_compute_usage(start_time=start_time, end_time=end_time)
|
|
240
|
+
|
|
241
|
+
self.assertEqual(result, { '2024-01-09': {'cost': 0.08,
|
|
242
|
+
'corehours': 0.9,
|
|
243
|
+
'walltime': 13.93},
|
|
244
|
+
'2024-01-16': { 'cost': 0.12,
|
|
245
|
+
'corehours': 0.9613,
|
|
246
|
+
'walltime': 7.21}})
|
|
247
|
+
|
|
248
|
+
@mock.patch("ciocore.api_client.ApiClient")
|
|
249
|
+
def test_get_compute_usage_api_failure(self, mock_ApiClient):
|
|
250
|
+
# Set up mock for API failure
|
|
251
|
+
mock_api_instance = mock_ApiClient.return_value
|
|
252
|
+
mock_api_instance.make_request.return_value = (self.response_error.text, self.response_error.status_code)
|
|
253
|
+
|
|
254
|
+
start_time = datetime.datetime(2024, 1, 1)
|
|
255
|
+
end_time = datetime.datetime(2024, 3, 20)
|
|
256
|
+
|
|
257
|
+
# Assert exception raised when the API call fails
|
|
258
|
+
with self.assertRaises(Exception) as context:
|
|
259
|
+
get_compute_usage(start_time, end_time)
|
|
260
|
+
|
|
261
|
+
self.assertIn('Failed to query compute usage', str(context.exception))
|
|
262
|
+
mock_ApiClient.assert_called_once()
|
|
263
|
+
class TestGetStorageUsage(unittest.TestCase):
|
|
264
|
+
|
|
265
|
+
def setUp(self):
|
|
266
|
+
|
|
267
|
+
self.storage_response_data = {
|
|
268
|
+
"data": [
|
|
269
|
+
{
|
|
270
|
+
"cost": "28.96",
|
|
271
|
+
"cost_per_day": [
|
|
272
|
+
4.022,
|
|
273
|
+
4.502,
|
|
274
|
+
4.502,
|
|
275
|
+
5.102,
|
|
276
|
+
5.102,
|
|
277
|
+
5.732
|
|
278
|
+
],
|
|
279
|
+
"currency": "USD",
|
|
280
|
+
"daily_price": "0.006",
|
|
281
|
+
"end_date": "2024-01-07",
|
|
282
|
+
"gibs_per_day": [
|
|
283
|
+
679.714,
|
|
284
|
+
750.34,
|
|
285
|
+
750.34,
|
|
286
|
+
850.36,
|
|
287
|
+
850.35,
|
|
288
|
+
955.32
|
|
289
|
+
],
|
|
290
|
+
"gibs_used": "806.07",
|
|
291
|
+
"monthly_price": "0.18",
|
|
292
|
+
"start_date": "2024-01-01",
|
|
293
|
+
"storage_unit": "GiB"
|
|
294
|
+
}
|
|
295
|
+
]
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
self.response_ok = mock.MagicMock(status_code=200, text=json.dumps(self.storage_response_data))
|
|
299
|
+
self.response_error = mock.MagicMock(status_code=500, text=json.dumps({"error": "Internal Server Error"}))
|
|
300
|
+
|
|
301
|
+
@mock.patch("ciocore.api_client.ApiClient")
|
|
302
|
+
@mock.patch("ciocore.api_client.read_conductor_credentials")
|
|
303
|
+
@mock.patch("ciocore.api_client.account_id_from_jwt")
|
|
304
|
+
def test_query_raw_storage_usage(self, mock_account_id_from_jwt, mock_read_conductor_credentials, mock_ApiClient):
|
|
305
|
+
# Set up mocks for successful execution
|
|
306
|
+
mock_read_conductor_credentials.return_value = "valid_token"
|
|
307
|
+
mock_account_id_from_jwt.return_value = "123"
|
|
308
|
+
mock_api_instance = mock_ApiClient.return_value
|
|
309
|
+
mock_api_instance.make_request.return_value = (self.response_ok.text, self.response_ok.status_code)
|
|
310
|
+
|
|
311
|
+
start_time = datetime.datetime(2024, 5, 1)
|
|
312
|
+
end_time = datetime.datetime(2024, 5, 17)
|
|
313
|
+
|
|
314
|
+
result = _get_storage_usage(start_time, end_time)
|
|
315
|
+
|
|
316
|
+
self.assertEqual(result, self.storage_response_data['data'][0])
|
|
317
|
+
|
|
318
|
+
@mock.patch("ciocore.api_client.ApiClient")
|
|
319
|
+
@mock.patch("ciocore.api_client.read_conductor_credentials")
|
|
320
|
+
@mock.patch("ciocore.api_client.account_id_from_jwt")
|
|
321
|
+
def test_storage_usage(self, mock_account_id_from_jwt, mock_read_conductor_credentials, mock_ApiClient):
|
|
322
|
+
# Set up mocks for successful execution
|
|
323
|
+
mock_read_conductor_credentials.return_value = "valid_token"
|
|
324
|
+
mock_account_id_from_jwt.return_value = "123"
|
|
325
|
+
mock_api_instance = mock_ApiClient.return_value
|
|
326
|
+
mock_api_instance.make_request.return_value = (self.response_ok.text, self.response_ok.status_code)
|
|
327
|
+
|
|
328
|
+
start_time = datetime.datetime(2024, 1, 1)
|
|
329
|
+
end_time = datetime.datetime(2024, 1, 7)
|
|
330
|
+
|
|
331
|
+
result = get_storage_usage(start_time=start_time, end_time=end_time)
|
|
332
|
+
|
|
333
|
+
self.assertEqual(result, { '2024-01-01': {'cost': 4.022, 'GiB': 679.714},
|
|
334
|
+
'2024-01-02': {'cost': 4.502, 'GiB': 750.34},
|
|
335
|
+
'2024-01-03': {'cost': 4.502, 'GiB': 750.34},
|
|
336
|
+
'2024-01-04': {'cost': 5.102, 'GiB': 850.36},
|
|
337
|
+
'2024-01-05': {'cost': 5.102, 'GiB': 850.35},
|
|
338
|
+
'2024-01-06': {'cost': 5.732, 'GiB': 955.32}
|
|
339
|
+
})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|