datacrunch 1.14.0__py3-none-any.whl → 1.16.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.
Files changed (58) hide show
  1. datacrunch/InferenceClient/inference_client.py +200 -65
  2. datacrunch/__init__.py +2 -0
  3. datacrunch/_version.py +6 -0
  4. datacrunch/authentication/authentication.py +7 -14
  5. datacrunch/balance/balance.py +1 -3
  6. datacrunch/constants.py +19 -17
  7. datacrunch/containers/containers.py +151 -123
  8. datacrunch/datacrunch.py +18 -18
  9. datacrunch/helpers.py +7 -2
  10. datacrunch/http_client/http_client.py +14 -14
  11. datacrunch/images/images.py +9 -3
  12. datacrunch/instance_types/instance_types.py +42 -35
  13. datacrunch/instances/instances.py +74 -53
  14. datacrunch/locations/locations.py +1 -2
  15. datacrunch/ssh_keys/ssh_keys.py +3 -4
  16. datacrunch/startup_scripts/startup_scripts.py +10 -8
  17. datacrunch/volume_types/volume_types.py +10 -8
  18. datacrunch/volumes/volumes.py +60 -73
  19. {datacrunch-1.14.0.dist-info → datacrunch-1.16.0.dist-info}/METADATA +46 -72
  20. datacrunch-1.16.0.dist-info/RECORD +35 -0
  21. datacrunch-1.16.0.dist-info/WHEEL +4 -0
  22. datacrunch/__version__.py +0 -1
  23. datacrunch-1.14.0.dist-info/RECORD +0 -69
  24. datacrunch-1.14.0.dist-info/WHEEL +0 -5
  25. datacrunch-1.14.0.dist-info/licenses/LICENSE +0 -21
  26. datacrunch-1.14.0.dist-info/top_level.txt +0 -2
  27. tests/__init__.py +0 -0
  28. tests/integration_tests/__init__.py +0 -0
  29. tests/integration_tests/conftest.py +0 -20
  30. tests/integration_tests/test_instances.py +0 -36
  31. tests/integration_tests/test_locations.py +0 -65
  32. tests/integration_tests/test_volumes.py +0 -94
  33. tests/unit_tests/__init__.py +0 -0
  34. tests/unit_tests/authentication/__init__.py +0 -0
  35. tests/unit_tests/authentication/test_authentication.py +0 -202
  36. tests/unit_tests/balance/__init__.py +0 -0
  37. tests/unit_tests/balance/test_balance.py +0 -25
  38. tests/unit_tests/conftest.py +0 -21
  39. tests/unit_tests/containers/__init__.py +0 -1
  40. tests/unit_tests/containers/test_containers.py +0 -959
  41. tests/unit_tests/http_client/__init__.py +0 -0
  42. tests/unit_tests/http_client/test_http_client.py +0 -193
  43. tests/unit_tests/images/__init__.py +0 -0
  44. tests/unit_tests/images/test_images.py +0 -41
  45. tests/unit_tests/instance_types/__init__.py +0 -0
  46. tests/unit_tests/instance_types/test_instance_types.py +0 -87
  47. tests/unit_tests/instances/__init__.py +0 -0
  48. tests/unit_tests/instances/test_instances.py +0 -483
  49. tests/unit_tests/ssh_keys/__init__.py +0 -0
  50. tests/unit_tests/ssh_keys/test_ssh_keys.py +0 -198
  51. tests/unit_tests/startup_scripts/__init__.py +0 -0
  52. tests/unit_tests/startup_scripts/test_startup_scripts.py +0 -196
  53. tests/unit_tests/test_datacrunch.py +0 -65
  54. tests/unit_tests/test_exceptions.py +0 -33
  55. tests/unit_tests/volume_types/__init__.py +0 -0
  56. tests/unit_tests/volume_types/test_volume_types.py +0 -50
  57. tests/unit_tests/volumes/__init__.py +0 -0
  58. tests/unit_tests/volumes/test_volumes.py +0 -641
@@ -1,65 +0,0 @@
1
- import os
2
- import pytest
3
- from datacrunch.datacrunch import DataCrunchClient
4
- from datacrunch.constants import Locations
5
-
6
- IN_GITHUB_ACTIONS = os.getenv("GITHUB_ACTIONS") == "true"
7
-
8
- location_codes = [Locations.FIN_01, Locations.ICE_01]
9
-
10
-
11
- @pytest.mark.skipif(IN_GITHUB_ACTIONS, reason="Test doesn't work in Github Actions.")
12
- @pytest.mark.withoutresponses
13
- class TestLocations():
14
-
15
- def test_specific_instance_availability_in_specific_location(self, datacrunch_client: DataCrunchClient):
16
- # call the instance availability endpoint, for a specific location
17
- availability = datacrunch_client.instances.is_available(
18
- 'CPU.4V', location_code=Locations.FIN_01)
19
-
20
- assert availability is not None
21
- assert isinstance(availability, bool)
22
-
23
- def test_all_availabilies_in_specific_location(self, datacrunch_client: DataCrunchClient):
24
-
25
- # call the instance availability endpoint, for a specific location
26
- availabilities = datacrunch_client.instances.get_availabilities(
27
- location_code=Locations.FIN_01)
28
-
29
- assert availabilities is not None
30
- assert isinstance(availabilities, list)
31
- assert len(availabilities) == 1
32
- assert availabilities[0]['location_code'] in location_codes
33
- assert isinstance(availabilities[0]['availabilities'], list)
34
- assert len(availabilities[0]['availabilities']) > 0
35
-
36
- def test_all_availabilites(self, datacrunch_client: DataCrunchClient):
37
- # call the instance availability endpoint, for all locations
38
- all_availabilities = datacrunch_client.instances.get_availabilities()
39
-
40
- assert all_availabilities is not None
41
- assert isinstance(all_availabilities, list)
42
- assert len(all_availabilities) > 1
43
- assert all_availabilities[0]['location_code'] in location_codes
44
- assert all_availabilities[1]['location_code'] in location_codes
45
- assert isinstance(all_availabilities[0]['availabilities'], list)
46
- assert len(all_availabilities[0]['availabilities']) > 0
47
-
48
- def test_get_all_locations(self, datacrunch_client: DataCrunchClient):
49
- # call the locations endpoint
50
- locations = datacrunch_client.locations.get()
51
-
52
- assert locations is not None
53
- assert isinstance(locations, list)
54
-
55
- assert locations[0]['code'] in location_codes
56
- assert locations[1]['code'] in location_codes
57
- assert locations[0]['code'] != locations[1]['code']
58
-
59
- assert locations[0]['name'] is not None
60
- assert locations[1]['name'] is not None
61
- assert locations[0]['name'] != locations[1]['name']
62
-
63
- assert locations[0]['country_code'] is not None
64
- assert locations[1]['country_code'] is not None
65
- assert locations[0]['country_code'] != locations[1]['country_code']
@@ -1,94 +0,0 @@
1
- import os
2
- import time
3
- import pytest
4
- from datacrunch.datacrunch import DataCrunchClient
5
- from datacrunch.constants import Locations, VolumeTypes, VolumeStatus
6
-
7
- IN_GITHUB_ACTIONS = os.getenv("GITHUB_ACTIONS") == "true"
8
-
9
-
10
- NVMe = VolumeTypes.NVMe
11
-
12
-
13
- @pytest.mark.skipif(IN_GITHUB_ACTIONS, reason="Test doesn't work in Github Actions.")
14
- @pytest.mark.withoutresponses
15
- class TestVolumes():
16
-
17
- def test_get_volumes_from_trash(self, datacrunch_client: DataCrunchClient):
18
- # create new volume
19
- volume = datacrunch_client.volumes.create(
20
- type=NVMe, name="test_volume", size=100)
21
-
22
- # delete volume
23
- datacrunch_client.volumes.delete(volume.id)
24
-
25
- # get volumes from trash
26
- volumes = datacrunch_client.volumes.get_in_trash()
27
-
28
- # assert volume is in trash
29
- assert volume.id in [v.id for v in volumes]
30
-
31
- # cleaning: permanently delete the volume
32
- datacrunch_client.volumes.delete(volume.id, is_permanent=True)
33
-
34
- def test_permanently_delete_detached_volumes(seld, datacrunch_client):
35
- # create new volume
36
- volume = datacrunch_client.volumes.create(
37
- type=NVMe, name="test_volume", size=100)
38
-
39
- # permanently delete the detached volume
40
- datacrunch_client.volumes.delete(volume.id, is_permanent=True)
41
-
42
- # sleep for 2 seconds
43
- time.sleep(2)
44
-
45
- # make sure the volume is not in trash
46
- volumes = datacrunch_client.volumes.get_in_trash()
47
-
48
- # assert volume is not in trash
49
- assert volume.id not in [v.id for v in volumes]
50
-
51
- # get the volume
52
- volume = datacrunch_client.volumes.get_by_id(volume.id)
53
-
54
- # assert volume status is deleted
55
- assert volume.status == datacrunch_client.constants.volume_status.DELETED
56
-
57
- def test_permanently_delete_a_deleted_volume_from_trash(self, datacrunch_client):
58
- # create new volume
59
- volume = datacrunch_client.volumes.create(
60
- type=NVMe, name="test_volume", size=100)
61
-
62
- # delete volume
63
- datacrunch_client.volumes.delete(volume.id)
64
-
65
- # sleep for 2 seconds
66
- time.sleep(2)
67
-
68
- # permanently delete the volume
69
- datacrunch_client.volumes.delete(volume.id, is_permanent=True)
70
-
71
- # get the volume
72
- volume = datacrunch_client.volumes.get_by_id(volume.id)
73
-
74
- # assert volume status is deleted
75
- assert volume.status == datacrunch_client.constants.volume_status.DELETED
76
-
77
- # make sure the volume is not in trash
78
- volumes = datacrunch_client.volumes.get_in_trash()
79
-
80
- # assert volume is not in trash
81
- assert volume.id not in [v.id for v in volumes]
82
-
83
- def test_create_volume(self, datacrunch_client):
84
- # create new volume
85
- volume = datacrunch_client.volumes.create(
86
- type=NVMe, name="test_volume", size=100, location=Locations.FIN_01)
87
-
88
- # assert volume is created
89
- assert volume.id is not None
90
- assert volume.location == Locations.FIN_01
91
- assert volume.status == VolumeStatus.ORDERED or volume.status == VolumeStatus.DETACHED
92
-
93
- # cleaning: delete volume
94
- datacrunch_client.volumes.delete(volume.id, is_permanent=True)
File without changes
File without changes
@@ -1,202 +0,0 @@
1
- import pytest
2
- import responses # https://github.com/getsentry/responses
3
- from responses import matchers
4
- import time
5
-
6
- from datacrunch.exceptions import APIException
7
- from datacrunch.authentication.authentication import AuthenticationService
8
-
9
- INVALID_REQUEST = 'invalid_request'
10
- INVALID_REQUEST_MESSAGE = 'Your existence is invalid'
11
-
12
- BASE_URL = "https://api-testing.datacrunch.io/v1"
13
- CLIENT_ID = "0123456789xyz"
14
- CLIENT_SECRET = 'zyx987654321'
15
-
16
- ACCESS_TOKEN = 'access'
17
- REFRESH_TOKEN = 'refresh'
18
- SCOPE = 'fullAccess'
19
- TOKEN_TYPE = 'Bearer'
20
- EXPIRES_IN = 3600
21
-
22
- ACCESS_TOKEN2 = 'access2'
23
- REFRESH_TOKEN2 = 'refresh2'
24
-
25
-
26
- class TestAuthenticationService:
27
-
28
- @pytest.fixture
29
- def authentication_service(self):
30
- return AuthenticationService(CLIENT_ID, CLIENT_SECRET, BASE_URL)
31
-
32
- @pytest.fixture
33
- def endpoint(self, http_client):
34
- return http_client._base_url + "/oauth2/token"
35
-
36
- def test_authenticate_successful(self, authentication_service, endpoint):
37
- # arrange - add response mock
38
- responses.add(
39
- responses.POST,
40
- endpoint,
41
- json={
42
- 'access_token': ACCESS_TOKEN,
43
- 'refresh_token': REFRESH_TOKEN,
44
- 'scope': SCOPE,
45
- 'token_type': TOKEN_TYPE,
46
- 'expires_in': EXPIRES_IN
47
- },
48
- status=200
49
- )
50
-
51
- # act
52
- auth_data = authentication_service.authenticate()
53
-
54
- # assert
55
- assert type(auth_data) == dict
56
- assert authentication_service._access_token == ACCESS_TOKEN
57
- assert authentication_service._refresh_token == REFRESH_TOKEN
58
- assert authentication_service._scope == SCOPE
59
- assert authentication_service._token_type == TOKEN_TYPE
60
- assert authentication_service._expires_at != None
61
- assert responses.assert_call_count(endpoint, 1) is True
62
-
63
- def test_authenticate_failed(self, authentication_service, endpoint):
64
- # arrange - add response mock
65
- responses.add(
66
- responses.POST,
67
- endpoint,
68
- json={"code": INVALID_REQUEST, "message": INVALID_REQUEST_MESSAGE},
69
- status=400
70
- )
71
-
72
- # act
73
- with pytest.raises(APIException) as excinfo:
74
- authentication_service.authenticate()
75
-
76
- x = responses.calls[0].request
77
-
78
- # assert
79
- assert excinfo.value.code == INVALID_REQUEST
80
- assert excinfo.value.message == INVALID_REQUEST_MESSAGE
81
- assert responses.assert_call_count(endpoint, 1) is True
82
- assert responses.calls[0].request.body == f'{{"grant_type": "client_credentials", "client_id": "{CLIENT_ID}", "client_secret": "{CLIENT_SECRET}"}}'.encode(
83
- )
84
-
85
- def test_refresh_successful(self, authentication_service, endpoint):
86
- # add a response for the client credentials grant
87
- responses.add(
88
- responses.POST,
89
- endpoint,
90
- json={
91
- 'access_token': ACCESS_TOKEN,
92
- 'refresh_token': REFRESH_TOKEN,
93
- 'scope': SCOPE,
94
- 'token_type': TOKEN_TYPE,
95
- 'expires_in': EXPIRES_IN
96
- },
97
- match=[matchers.json_params_matcher(
98
- {"grant_type": "client_credentials", "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET})],
99
- status=200
100
- )
101
-
102
- # add another response for the refresh token grant
103
- responses.add(
104
- responses.POST,
105
- endpoint,
106
- json={
107
- 'access_token': ACCESS_TOKEN2,
108
- 'refresh_token': REFRESH_TOKEN2,
109
- 'scope': SCOPE,
110
- 'token_type': TOKEN_TYPE,
111
- 'expires_in': EXPIRES_IN
112
- },
113
- match=[matchers.json_params_matcher(
114
- {"grant_type": "refresh_token", "refresh_token": REFRESH_TOKEN})],
115
- status=200
116
- )
117
-
118
- # act
119
- auth_data = authentication_service.authenticate() # authenticate first
120
-
121
- # assert
122
- assert type(auth_data) == dict
123
- assert authentication_service._access_token == ACCESS_TOKEN
124
- assert authentication_service._refresh_token == REFRESH_TOKEN
125
- assert authentication_service._scope == SCOPE
126
- assert authentication_service._token_type == TOKEN_TYPE
127
- assert authentication_service._expires_at != None
128
- assert responses.calls[0].request.body == f'{{"grant_type": "client_credentials", "client_id": "{CLIENT_ID}", "client_secret": "{CLIENT_SECRET}"}}'.encode(
129
- )
130
-
131
- auth_data2 = authentication_service.refresh() # refresh
132
-
133
- assert type(auth_data2) == dict
134
- assert authentication_service._access_token == ACCESS_TOKEN2
135
- assert authentication_service._refresh_token == REFRESH_TOKEN2
136
- assert authentication_service._scope == SCOPE
137
- assert authentication_service._token_type == TOKEN_TYPE
138
- assert authentication_service._expires_at != None
139
- assert responses.calls[1].request.body == f'{{"grant_type": "refresh_token", "refresh_token": "{REFRESH_TOKEN}"}}'.encode(
140
- )
141
- assert responses.assert_call_count(endpoint, 2) is True
142
-
143
- def test_refresh_failed(self, authentication_service, endpoint):
144
- # arrange - add responses mock
145
- # first response for authentication - ok
146
- responses.add(
147
- responses.POST,
148
- endpoint,
149
- json={
150
- 'access_token': ACCESS_TOKEN,
151
- 'refresh_token': REFRESH_TOKEN,
152
- 'scope': SCOPE,
153
- 'token_type': TOKEN_TYPE,
154
- 'expires_in': EXPIRES_IN
155
- },
156
- match=[matchers.json_params_matcher(
157
- {"grant_type": "client_credentials", "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET})],
158
- status=200
159
- )
160
-
161
- # second response for the refresh - failed
162
- responses.add(
163
- responses.POST,
164
- endpoint,
165
- json={"code": INVALID_REQUEST, "message": INVALID_REQUEST_MESSAGE},
166
- match=[matchers.json_params_matcher(
167
- {"grant_type": "refresh_token", "refresh_token": REFRESH_TOKEN})],
168
- status=500
169
- )
170
-
171
- # act
172
- authentication_service.authenticate() # authenticate first
173
-
174
- with pytest.raises(APIException) as excinfo:
175
- authentication_service.refresh()
176
-
177
- # assert
178
- assert excinfo.value.code == INVALID_REQUEST
179
- assert excinfo.value.message == INVALID_REQUEST_MESSAGE
180
- assert responses.assert_call_count(endpoint, 2) is True
181
- assert responses.calls[0].request.body == f'{{"grant_type": "client_credentials", "client_id": "{CLIENT_ID}", "client_secret": "{CLIENT_SECRET}"}}'.encode(
182
- )
183
- assert responses.calls[1].request.body == f'{{"grant_type": "refresh_token", "refresh_token": "{REFRESH_TOKEN}"}}'.encode(
184
- )
185
-
186
- def test_is_expired(self, authentication_service, endpoint):
187
- # arrange
188
- current_time = time.time()
189
- future_time = current_time + 3600
190
-
191
- # act
192
- # set the expired_at as current time
193
- authentication_service._expires_at = current_time
194
- is_expired_current = authentication_service.is_expired()
195
-
196
- # set the expired_at as future time
197
- authentication_service._expires_at = future_time
198
- is_expired_future = authentication_service.is_expired()
199
-
200
- # assert
201
- assert is_expired_current == True
202
- assert is_expired_future == False
File without changes
@@ -1,25 +0,0 @@
1
- import responses # https://github.com/getsentry/responses
2
-
3
- from datacrunch.balance.balance import BalanceService, Balance
4
-
5
-
6
- def test_balance(http_client):
7
- # arrange - add response mock
8
- responses.add(
9
- responses.GET,
10
- http_client._base_url + "/balance",
11
- json={"amount": 50.5, "currency": "usd"},
12
- status=200
13
- )
14
-
15
- balance_service = BalanceService(http_client)
16
-
17
- # act
18
- balance = balance_service.get()
19
-
20
- # assert
21
- assert type(balance) == Balance
22
- assert type(balance.amount) == float
23
- assert type(balance.currency) == str
24
- assert balance.amount == 50.5
25
- assert balance.currency == "usd"
@@ -1,21 +0,0 @@
1
- import pytest
2
- from unittest.mock import Mock
3
- from datacrunch.http_client.http_client import HTTPClient
4
-
5
-
6
- BASE_URL = "https://api-testing.datacrunch.io/v1"
7
- ACCESS_TOKEN = "test-token"
8
- CLIENT_ID = "0123456789xyz"
9
- CLIENT_SECRET = "0123456789xyz"
10
-
11
-
12
- @pytest.fixture
13
- def http_client():
14
- auth_service = Mock()
15
- auth_service._access_token = ACCESS_TOKEN
16
- auth_service.is_expired = Mock(return_value=True)
17
- auth_service.refresh = Mock(return_value=None)
18
- auth_service._client_id = CLIENT_ID
19
- auth_service._client_secret = CLIENT_SECRET
20
-
21
- return HTTPClient(auth_service, BASE_URL)
@@ -1 +0,0 @@
1
-