Skip to content

Commit f901b34

Browse files
committed
Merge branch 'feature/add-storage-volumes' into develop
2 parents 3d3c792 + 51733d0 commit f901b34

22 files changed

Lines changed: 1445 additions & 108 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ venv/
114114
ENV/
115115
env.bak/
116116
venv.bak/
117+
datacrunch_env/
117118

118119
# Spyder project settings
119120
.spyderproject

CHANGELOG.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
Changelog
22
=========
33

4+
v1.0.0 (2021-06-16)
5+
-------------------
6+
7+
* Added support for storage volumes
8+
* Breaking change: moved all constants under DataCrunchClient to DataCrunchClient.constants
9+
410
v0.1.0 (2021-01-05)
511
-------------------
612

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ DataCrunch's Public API documentation [is available here](https://datacrunch.sto
111111
- Install Dependencies:
112112

113113
```bash
114-
pip3 install -e
114+
pip3 install -e .[test]
115+
pip3 install -U pytest
115116
```
116117

117118
### Running Tests
@@ -130,6 +131,18 @@ We use pytest for testing.
130131
pytest ./tests/unit_tests/test_file.py
131132
```
132133

134+
### Local Manual Testing
135+
136+
```python
137+
from datacrunch.datacrunch import DataCrunchClient
138+
139+
CLIENT_SECRET = 'secret'
140+
CLIENT_ID = 'Ibk5bdxV64lKAWOqYnvSi'
141+
142+
# Create datcrunch client
143+
datacrunch = DataCrunchClient(CLIENT_ID, CLIENT_SECRET, base_url='http://localhost:3001/v1')
144+
```
145+
133146
### Generating the documentation
134147

135148
```bash

datacrunch/constants.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,17 @@ def __init__(self):
99
return
1010

1111

12+
class VolumeActions:
13+
ATTACH = 'attach'
14+
DETACH = 'detach'
15+
RENAME = 'rename'
16+
INCREASE_SIZE = 'increase-size'
17+
DELETE = 'delete'
18+
19+
def __init__(self):
20+
return
21+
22+
1223
class InstanceStatus:
1324
RUNNING = 'running'
1425
PROVISIONING = 'provisioning'
@@ -22,6 +33,26 @@ def __init__(self):
2233
return
2334

2435

36+
class VolumeStatus:
37+
ORDERED = "ordered"
38+
CREATING = "creating"
39+
ATTACHED = "attached"
40+
DETACHED = "detached"
41+
DELETING = "deleting"
42+
DELETED = "deleted"
43+
44+
def __init__(self):
45+
return
46+
47+
48+
class VolumeTypes:
49+
NVMe = "NVMe"
50+
HDD = "HDD"
51+
52+
def __init__(self):
53+
return
54+
55+
2556
class ErrorCodes:
2657
INVALID_REQUEST = "invalid_request"
2758
UNAUTHORIZED_REQUEST = "unauthorized_request"
@@ -33,3 +64,30 @@ class ErrorCodes:
3364

3465
def __init__(self):
3566
return
67+
68+
69+
class Constants:
70+
def __init__(self, base_url, version):
71+
self.instance_actions: Actions = Actions()
72+
"""Available actions to perform on an instance"""
73+
74+
self.volume_actions: VolumeActions = VolumeActions()
75+
"""Available actions to perform on a volume"""
76+
77+
self.instance_status: InstanceStatus = InstanceStatus()
78+
"""Possible instance statuses"""
79+
80+
self.volume_status: VolumeStatus = VolumeStatus()
81+
"""Possible volume statuses"""
82+
83+
self.volume_types: VolumeTypes = VolumeTypes()
84+
"""Available volume types"""
85+
86+
self.error_codes: ErrorCodes = ErrorCodes()
87+
"""Available error codes"""
88+
89+
self.base_url: str = base_url
90+
"""DataCrunch's Public API URL"""
91+
92+
self.version: str = version
93+
"""Current SDK Version"""

datacrunch/datacrunch.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
from datacrunch.instances.instances import InstancesService
77
from datacrunch.ssh_keys.ssh_keys import SSHKeysService
88
from datacrunch.startup_scripts.startup_scripts import StartupScriptsService
9-
from datacrunch.constants import Actions, InstanceStatus, ErrorCodes
9+
from datacrunch.volume_types.volume_types import VolumeTypesService
10+
from datacrunch.volumes.volumes import VolumesService
11+
from datacrunch.constants import Constants
1012
from datacrunch.__version__ import VERSION
1113

1214

@@ -25,26 +27,14 @@ def __init__(self, client_id: str, client_secret: str, base_url: str = "https://
2527
"""
2628

2729
# Constants
28-
self.actions: Actions = Actions()
29-
"""Available actions to perform on an instance"""
30-
31-
self.instance_status: InstanceStatus = InstanceStatus()
32-
"""Possible instance statuses"""
33-
34-
self.error_codes: ErrorCodes = ErrorCodes()
35-
"""Available error codes"""
36-
37-
self.base_url: str = base_url
38-
"""DataCrunch's Public API URL"""
39-
40-
self.version: str = VERSION
41-
"""Current SDK Version"""
30+
self.constants: Constants = Constants(base_url, VERSION)
31+
"""Constants"""
4232

4333
# Services
4434
self._authentication: AuthenticationService = AuthenticationService(
45-
client_id, client_secret, self.base_url)
35+
client_id, client_secret, self.constants.base_url)
4636
self._http_client: HTTPClient = HTTPClient(
47-
self._authentication, self.base_url)
37+
self._authentication, self.constants.base_url)
4838

4939
self.balance: BalanceService = BalanceService(self._http_client)
5040
"""Balance service. Get client balance"""
@@ -65,3 +55,10 @@ def __init__(self, client_id: str, client_secret: str, base_url: str = "https://
6555
self.startup_scripts: StartupScriptsService = StartupScriptsService(
6656
self._http_client)
6757
"""Startup Scripts service"""
58+
59+
self.volume_types: VolumeTypesService = VolumeTypesService(
60+
self._http_client)
61+
"""Volume type service"""
62+
63+
self.volumes: VolumesService = VolumesService(self._http_client)
64+
"""Volume service. Create, attach, detach, get, rename, delete volumes"""

datacrunch/http_client/http_client.py

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def __init__(self, auth_service, base_url: str) -> None:
3333
self._auth_service.authenticate()
3434

3535
def post(self, url: str, json: dict = None, **kwargs) -> requests.Response:
36-
"""Sends a POST request.
36+
"""Sends a POST request.
3737
3838
A wrapper for the requests.post method.
3939
@@ -59,16 +59,43 @@ def post(self, url: str, json: dict = None, **kwargs) -> requests.Response:
5959

6060
return response
6161

62+
def put(self, url: str, json: dict = None, **kwargs) -> requests.Response:
63+
"""Sends a PUT request.
64+
65+
A wrapper for the requests.put method.
66+
67+
Builds the url, uses custom headers, refresh tokens if needed.
68+
69+
:param url: relative url of the API endpoint
70+
:type url: str
71+
:param json: A JSON serializable Python object to send in the body of the Request, defaults to None
72+
:type json: dict, optional
73+
74+
:raises APIException: an api exception with message and error type code
75+
76+
:return: Response object
77+
:rtype: requests.Response
78+
"""
79+
url = self._add_base_url(url)
80+
headers = self._generate_headers()
81+
82+
self._refresh_token_if_expired()
83+
84+
response = requests.put(url, json=json, headers=headers, **kwargs)
85+
handle_error(response)
86+
87+
return response
88+
6289
def get(self, url: str, params: dict = None, **kwargs) -> requests.Response:
63-
"""Sends a GET request.
90+
"""Sends a GET request.
6491
6592
A wrapper for the requests.get method.
6693
6794
Builds the url, uses custom headers, refresh tokens if needed.
6895
6996
:param url: relative url of the API endpoint
7097
:type url: str
71-
:param params: Dictionary, list of tuples or bytes to send in the query string for the Request., defaults to None
98+
:param params: Dictionary, list of tuples or bytes to send in the query string for the Request. defaults to None
7299
:type params: dict, optional
73100
74101
:raises APIException: an api exception with message and error type code
@@ -87,7 +114,7 @@ def get(self, url: str, params: dict = None, **kwargs) -> requests.Response:
87114
return response
88115

89116
def delete(self, url: str, json: dict = None, **kwargs) -> requests.Response:
90-
"""Sends a DELETE request.
117+
"""Sends a DELETE request.
91118
92119
A wrapper for the requests.delete method.
93120
@@ -124,7 +151,7 @@ def _refresh_token_if_expired(self) -> None:
124151
# to to refresh. if refresh token has expired, reauthenticate
125152
try:
126153
self._auth_service.refresh()
127-
except:
154+
except Exception:
128155
self._auth_service.authenticate()
129156

130157
def _generate_headers(self) -> dict:
@@ -141,7 +168,7 @@ def _generate_headers(self) -> dict:
141168
return headers
142169

143170
def _generate_bearer_header(self) -> str:
144-
"""generate the authorization header Bearer string
171+
"""generate the authorization header Bearer string
145172
146173
:return: Authorization header Bearer string
147174
:rtype: str
@@ -162,7 +189,7 @@ def _generate_user_agent(self) -> str:
162189
def _add_base_url(self, url: str) -> str:
163190
"""Adds the base url to the relative url
164191
165-
example:
192+
example:
166193
if the relative url is '/balance'
167194
and the base url is 'https://api.datacrunch.io/v1'
168195
then this method will return 'https://api.datacrunch.io/v1/balance'

datacrunch/instance_types/instance_types.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ def __init__(self,
1313
cpu: dict,
1414
gpu: dict,
1515
memory: dict,
16+
gpu_memory: dict,
1617
storage: dict) -> None:
1718
"""Initialize an instance type object
1819
@@ -29,7 +30,9 @@ def __init__(self,
2930
:param gpu: gpu details
3031
:type gpu: dict
3132
:param memory: memory details
32-
:type storage: dict
33+
:type memory: dict
34+
:param gpu_memory: gpu memory details
35+
:type gpu_memory: dict
3336
:param storage: storage details
3437
:type storage: dict
3538
"""
@@ -40,6 +43,7 @@ def __init__(self,
4043
self._cpu = cpu
4144
self._gpu = gpu
4245
self._memory = memory
46+
self._gpu_memory = gpu_memory
4347
self._storage = storage
4448

4549
@property
@@ -105,6 +109,15 @@ def memory(self) -> dict:
105109
"""
106110
return self._memory
107111

112+
@property
113+
def gpu_memory(self) -> dict:
114+
"""Get the instance type gpu_memory details
115+
116+
:return: gpu_memory details
117+
:rtype: dict
118+
"""
119+
return self._gpu_memory
120+
108121
@property
109122
def storage(self) -> dict:
110123
"""Get the instance type storage details
@@ -114,6 +127,23 @@ def storage(self) -> dict:
114127
"""
115128
return self._storage
116129

130+
def __str__(self) -> str:
131+
"""Prints the instance type
132+
133+
:return: instance type string representation
134+
:rtype: str
135+
"""
136+
return (f'id: {self._id}\n'
137+
f'instance type: {self._instance_type}\n'
138+
f'price_per_hour: ${self._price_per_hour}\n'
139+
f'description: {self._description}\n'
140+
f'cpu: {self._cpu}\n'
141+
f'gpu: {self._gpu}\n'
142+
f'memory :{self._memory}\n'
143+
f'gpu_memory :{self._gpu_memory}\n'
144+
f'storage :{self._storage}\n'
145+
)
146+
117147

118148
class InstanceTypesService:
119149
"""A service for interacting with the instance-types endpoint"""
@@ -136,6 +166,7 @@ def get(self) -> List[InstanceType]:
136166
cpu=instance_type['cpu'],
137167
gpu=instance_type['gpu'],
138168
memory=instance_type['memory'],
169+
gpu_memory=instance_type['gpu_memory'],
139170
storage=instance_type['storage']
140171
), instance_types))
141172

0 commit comments

Comments
 (0)