datacrunch 1.15.0__py3-none-any.whl → 1.17.1__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.
- datacrunch/__init__.py +53 -1
- datacrunch/datacrunch.py +44 -81
- datacrunch-1.17.1.dist-info/METADATA +30 -0
- datacrunch-1.17.1.dist-info/RECORD +5 -0
- datacrunch-1.17.1.dist-info/WHEEL +4 -0
- datacrunch/InferenceClient/__init__.py +0 -3
- datacrunch/InferenceClient/inference_client.py +0 -379
- datacrunch/__version__.py +0 -1
- datacrunch/authentication/__init__.py +0 -0
- datacrunch/authentication/authentication.py +0 -112
- datacrunch/balance/__init__.py +0 -0
- datacrunch/balance/balance.py +0 -52
- datacrunch/constants.py +0 -107
- datacrunch/containers/__init__.py +0 -33
- datacrunch/containers/containers.py +0 -1081
- datacrunch/exceptions.py +0 -29
- datacrunch/helpers.py +0 -13
- datacrunch/http_client/__init__.py +0 -0
- datacrunch/http_client/http_client.py +0 -241
- datacrunch/images/__init__.py +0 -0
- datacrunch/images/images.py +0 -87
- datacrunch/instance_types/__init__.py +0 -0
- datacrunch/instance_types/instance_types.py +0 -188
- datacrunch/instances/__init__.py +0 -0
- datacrunch/instances/instances.py +0 -247
- datacrunch/locations/__init__.py +0 -0
- datacrunch/locations/locations.py +0 -16
- datacrunch/ssh_keys/__init__.py +0 -0
- datacrunch/ssh_keys/ssh_keys.py +0 -112
- datacrunch/startup_scripts/__init__.py +0 -0
- datacrunch/startup_scripts/startup_scripts.py +0 -113
- datacrunch/volume_types/__init__.py +0 -0
- datacrunch/volume_types/volume_types.py +0 -66
- datacrunch/volumes/__init__.py +0 -0
- datacrunch/volumes/volumes.py +0 -398
- datacrunch-1.15.0.dist-info/METADATA +0 -208
- datacrunch-1.15.0.dist-info/RECORD +0 -69
- datacrunch-1.15.0.dist-info/WHEEL +0 -5
- datacrunch-1.15.0.dist-info/licenses/LICENSE +0 -21
- datacrunch-1.15.0.dist-info/top_level.txt +0 -2
- tests/__init__.py +0 -0
- tests/integration_tests/__init__.py +0 -0
- tests/integration_tests/conftest.py +0 -20
- tests/integration_tests/test_instances.py +0 -36
- tests/integration_tests/test_locations.py +0 -65
- tests/integration_tests/test_volumes.py +0 -94
- tests/unit_tests/__init__.py +0 -0
- tests/unit_tests/authentication/__init__.py +0 -0
- tests/unit_tests/authentication/test_authentication.py +0 -202
- tests/unit_tests/balance/__init__.py +0 -0
- tests/unit_tests/balance/test_balance.py +0 -25
- tests/unit_tests/conftest.py +0 -21
- tests/unit_tests/containers/__init__.py +0 -1
- tests/unit_tests/containers/test_containers.py +0 -959
- tests/unit_tests/http_client/__init__.py +0 -0
- tests/unit_tests/http_client/test_http_client.py +0 -193
- tests/unit_tests/images/__init__.py +0 -0
- tests/unit_tests/images/test_images.py +0 -41
- tests/unit_tests/instance_types/__init__.py +0 -0
- tests/unit_tests/instance_types/test_instance_types.py +0 -87
- tests/unit_tests/instances/__init__.py +0 -0
- tests/unit_tests/instances/test_instances.py +0 -483
- tests/unit_tests/ssh_keys/__init__.py +0 -0
- tests/unit_tests/ssh_keys/test_ssh_keys.py +0 -198
- tests/unit_tests/startup_scripts/__init__.py +0 -0
- tests/unit_tests/startup_scripts/test_startup_scripts.py +0 -196
- tests/unit_tests/test_datacrunch.py +0 -65
- tests/unit_tests/test_exceptions.py +0 -33
- tests/unit_tests/volume_types/__init__.py +0 -0
- tests/unit_tests/volume_types/test_volume_types.py +0 -50
- tests/unit_tests/volumes/__init__.py +0 -0
- tests/unit_tests/volumes/test_volumes.py +0 -641
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2020 DataCrunch Oy
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
tests/__init__.py
DELETED
|
File without changes
|
|
File without changes
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import pytest
|
|
3
|
-
from dotenv import load_dotenv
|
|
4
|
-
from datacrunch.datacrunch import DataCrunchClient
|
|
5
|
-
|
|
6
|
-
"""
|
|
7
|
-
Make sure to run the server and the account has enough balance before running the tests
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
BASE_URL = "http://localhost:3010/v1"
|
|
11
|
-
|
|
12
|
-
# Load env variables, make sure there's an env file with valid client credentials
|
|
13
|
-
load_dotenv()
|
|
14
|
-
CLIENT_SECRET = os.getenv('DATACRUNCH_CLIENT_SECRET')
|
|
15
|
-
CLIENT_ID = os.getenv('DATACRUNCH_CLIENT_ID')
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@pytest.fixture
|
|
19
|
-
def datacrunch_client():
|
|
20
|
-
return DataCrunchClient(CLIENT_ID, CLIENT_SECRET, BASE_URL)
|
|
@@ -1,36 +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
|
-
|
|
9
|
-
@pytest.mark.skipif(IN_GITHUB_ACTIONS, reason="Test doesn't work in Github Actions.")
|
|
10
|
-
@pytest.mark.withoutresponses
|
|
11
|
-
class TestInstances():
|
|
12
|
-
|
|
13
|
-
def test_create_instance(self, datacrunch_client: DataCrunchClient):
|
|
14
|
-
# get ssh key
|
|
15
|
-
ssh_key = datacrunch_client.ssh_keys.get()[0]
|
|
16
|
-
|
|
17
|
-
# create instance
|
|
18
|
-
instance = datacrunch_client.instances.create(
|
|
19
|
-
hostname="test-instance",
|
|
20
|
-
location=Locations.FIN_01,
|
|
21
|
-
instance_type='CPU.4V',
|
|
22
|
-
description="test instance",
|
|
23
|
-
image="ubuntu-18.04",
|
|
24
|
-
ssh_key_ids=[ssh_key.id])
|
|
25
|
-
|
|
26
|
-
# assert instance is created
|
|
27
|
-
assert instance.id is not None
|
|
28
|
-
assert instance.status == datacrunch_client.constants.instance_status.PROVISIONING
|
|
29
|
-
|
|
30
|
-
# delete instance
|
|
31
|
-
datacrunch_client.instances.action(instance.id, "delete")
|
|
32
|
-
|
|
33
|
-
# permanently delete all volumes in trash
|
|
34
|
-
trash = datacrunch_client.volumes.get_in_trash()
|
|
35
|
-
for volume in trash:
|
|
36
|
-
datacrunch_client.volumes.delete(volume.id, is_permanent=True)
|
|
@@ -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)
|
tests/unit_tests/__init__.py
DELETED
|
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"
|
tests/unit_tests/conftest.py
DELETED
|
@@ -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
|
-
|