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.

Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ciocore
3
- Version: 8.0.1
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=NUqt24vsbMosc7cU07CLlLBV2gAdKgs8roFBqy0xjlA,5
1
+ ciocore/VERSION,sha256=tLQREuN8_s0dGaKmIQt0W8MTSuMhtDpdcGwzW80I8nk,5
2
2
  ciocore/__init__.py,sha256=aTP7LeeosQA8BZE67gDV4jgfTK5zxmwZRjiTRu_ZWj0,646
3
- ciocore/api_client.py,sha256=TyHXGmK4uTmKV93O_IpAvttZhbexIIZTGP-IVn_WyWM,24599
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=s2FKStLlVIQbfG7U2-nw-7rz4unvd1W0u00YtLBxAKo,758
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=mBXMN84utPFOOhXBKJnq47kV3Zp6NvUz5Xxy7lDOxq8,127
30
- ciocore/docsite/apidoc/api_client/index.html,sha256=0AdyUY-LmL5ZqUeqxIjjzmoZDbupNcImCWf7RFeO5-o,170218
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=ZMAbHLAlwOTujgA32XJTA7SHogRYh9i-ioPFOxjjJ0s,182633
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=tnYkIYvDILGJRatZM0nrtr83x8yBJstMP0Rt151U2gI,6757
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.1.dist-info/METADATA,sha256=798KBccoox0YMHAcd09zV7pIzVkXN_GNoBWhckmK4D4,18440
124
- ciocore-8.0.1.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
125
- ciocore-8.0.1.dist-info/entry_points.txt,sha256=cCqcALMYbC4d8545V9w0Zysfg9MVuKWhzDQ2er4UfGE,47
126
- ciocore-8.0.1.dist-info/top_level.txt,sha256=SvlM5JlqULzAz00JZWfiUhfjhqDzYzSWssA87zdJl0o,14
127
- ciocore-8.0.1.dist-info/RECORD,,
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
- import json
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
+ })