Skip to content

Commit 3b4f69f

Browse files
committed
Add Pagination to volumes and ssh keys
1 parent 7c0c14f commit 3b4f69f

5 files changed

Lines changed: 91 additions & 23 deletions

File tree

hcloud/ssh_keys/client.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,41 @@ def delete(self):
1717

1818

1919
class SSHKeysClient(ClientEntityBase):
20+
results_list_attribute_name = 'ssh_keys'
2021

2122
def get_by_id(self, id):
2223
# type: (int) -> BoundSSHKey
2324
response = self._client.request(url="/ssh_keys/{ssh_key_id}".format(ssh_key_id=id), method="GET")
2425
return BoundSSHKey(self, response['ssh_key'])
2526

26-
def get_all(self, name=None, fingerprint=None, label_selector=None):
27-
# type: (Optional[str], Optional[str], Optional[str]) -> List[BoundSSHKey]
27+
def get_list(self,
28+
name=None, # type: Optional[str]
29+
fingerprint=None, # type: Optional[str]
30+
label_selector=None, # type: Optional[str]
31+
page=None, # type: Optional[int]
32+
per_page=None # type: Optional[int]
33+
):
34+
# type: (...) -> PageResults[List[BoundSSHKey], Meta]
2835
params = {}
29-
if name is not None:
36+
if name:
3037
params['name'] = name
31-
if fingerprint is not None:
38+
if fingerprint:
3239
params['fingerprint'] = fingerprint
33-
if label_selector is not None:
40+
if label_selector:
3441
params['label_selector'] = label_selector
42+
if page:
43+
params['page'] = page
44+
if per_page:
45+
params['per_page'] = per_page
3546

3647
response = self._client.request(url="/ssh_keys", method="GET", params=params)
37-
return [BoundSSHKey(self, location_data) for location_data in response['ssh_keys']]
48+
49+
ass_ssh_keys = [BoundSSHKey(self, server_data) for server_data in response['ssh_keys']]
50+
return self.add_meta_to_result(ass_ssh_keys, response)
51+
52+
def get_all(self, name=None, fingerprint=None, label_selector=None):
53+
# type: (Optional[str], Optional[str], Optional[str]) -> List[BoundSSHKey]
54+
return super(SSHKeysClient, self).get_all(name=name, fingerprint=fingerprint, label_selector=label_selector)
3855

3956
def create(self, name, public_key, labels=None):
4057
# type: (str, str, Optional[Dict[str, str]]) -> BoundSSHKey

hcloud/volumes/client.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from hcloud.core.client import ClientEntityBase, BoundModelBase
33

44
from hcloud.actions.client import BoundAction
5+
from hcloud.core.domain import add_meta_to_result
56
from hcloud.volumes.domain import Volume, CreateVolumeResponse
67
from hcloud.locations.client import BoundLocation
78

@@ -15,6 +16,10 @@ def __init__(self, client, data, complete=True):
1516
data['location'] = BoundLocation(client._client.locations, location)
1617
super(BoundVolume, self).__init__(client, data, complete)
1718

19+
def get_actions_list(self, sort=None, page=None, per_page=None):
20+
# type: (Optional[List[str]], Optional[int], Optional[int]) -> PageResults[List[BoundAction, Meta]]
21+
return self._client.get_actions_list(self, sort, page, per_page)
22+
1823
def get_actions(self, sort=None):
1924
# type: (Optional[List[str]]) -> List[BoundAction]
2025
return self._client.get_actions(self, sort)
@@ -112,14 +117,23 @@ def create(self,
112117
)
113118
return result
114119

115-
def get_actions(self, volume, sort=None):
116-
# type: (Union[Volume, BoundVolume], Optional[List[str]]) -> List[BoundAction]
120+
def get_actions_list(self, volume, sort=None, page=None, per_page=None):
121+
# type: (Volume, Optional[List[str]], Optional[int], Optional[int]) -> PageResults[List[BoundAction], Meta]
117122
params = {}
118-
119123
if sort is not None:
120-
params.update({"sort": sort})
124+
params["sort"] = sort
125+
if page is not None:
126+
params["page"] = page
127+
if per_page is not None:
128+
params["per_page"] = per_page
129+
121130
response = self._client.request(url="/volumes/{volume_id}/actions".format(volume_id=volume.id), method="GET", params=params)
122-
return [BoundAction(self._client.actions, action_data) for action_data in response['actions']]
131+
actions = [BoundAction(self._client.actions, action_data) for action_data in response['actions']]
132+
return add_meta_to_result(actions, response, 'actions')
133+
134+
def get_actions(self, volume, sort=None):
135+
# type: (Union[Volume, BoundVolume], Optional[List[str]]) -> List[BoundAction]
136+
return super(VolumesClient, self).get_actions(volume, sort=sort)
123137

124138
def update(self, volume, name=None, labels=None):
125139
# type:(Union[Volume, BoundVolume], Optional[str], Optional[Dict[str, str]]) -> BoundVolume

tests/integration/ssh_keys/test_ssh_keys.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def test_get_by_id(self, hetzner_client):
3030
assert ssh_key.fingerprint == "b7:2f:30:a0:2f:6c:58:6c:21:04:58:61:ba:06:3b:2f"
3131
assert ssh_key.public_key == "ssh-rsa AAAjjk76kgf...Xt"
3232

33-
def test_get_all(self, hetzner_client):
33+
def test_get_list(self, hetzner_client):
3434
ssh_keys = hetzner_client.ssh_keys.get_all()
3535
assert ssh_keys[0].id == 2323
3636
assert ssh_keys[0].name == "My ssh key"

tests/unit/ssh_keys/test_client.py

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,19 @@ def test_get_by_id(self, ssh_keys_client, ssh_key_response):
5252
assert ssh_key.id == 2323
5353
assert ssh_key.name == "My ssh key"
5454

55-
def test_get_all_no_params(self, ssh_keys_client, two_ssh_keys_response):
55+
@pytest.mark.parametrize(
56+
"params",
57+
[
58+
{'name': "My ssh key", "fingerprint": "b7:2f:30:a0:2f:6c:58:6c:21:04:58:61:ba:06:3b:2f", "label_selector": "k==v", 'page': 1, 'per_page': 10},
59+
{}
60+
]
61+
)
62+
def test_get_list(self, ssh_keys_client, two_ssh_keys_response, params):
5663
ssh_keys_client._client.request.return_value = two_ssh_keys_response
57-
ssh_keys = ssh_keys_client.get_all()
58-
ssh_keys_client._client.request.assert_called_with(url="/ssh_keys", method="GET", params={})
64+
result = ssh_keys_client.get_list(**params)
65+
ssh_keys_client._client.request.assert_called_with(url="/ssh_keys", method="GET", params=params)
5966

67+
ssh_keys = result.ssh_keys
6068
assert len(ssh_keys) == 2
6169

6270
ssh_keys1 = ssh_keys[0]
@@ -70,11 +78,33 @@ def test_get_all_no_params(self, ssh_keys_client, two_ssh_keys_response):
7078
assert ssh_keys2.id == 2324
7179
assert ssh_keys2.name == "SSH-Key"
7280

73-
def test_get_all_with_params(self, ssh_keys_client):
74-
params = {'name': "My ssh key", "fingerprint": "b7:2f:30:a0:2f:6c:58:6c:21:04:58:61:ba:06:3b:2f", "label_selector": "k==v"}
75-
ssh_keys_client.get_all(**params)
81+
@pytest.mark.parametrize(
82+
"params",
83+
[
84+
{'name': "My ssh key", 'label_selector': "label1"},
85+
{}
86+
]
87+
)
88+
def test_get_all(self, ssh_keys_client, two_ssh_keys_response, params):
89+
ssh_keys_client._client.request.return_value = two_ssh_keys_response
90+
ssh_keys = ssh_keys_client.get_all(**params)
91+
92+
params.update({'page': 1, 'per_page': 50})
7693
ssh_keys_client._client.request.assert_called_with(url="/ssh_keys", method="GET", params=params)
7794

95+
assert len(ssh_keys) == 2
96+
97+
ssh_keys1 = ssh_keys[0]
98+
ssh_keys2 = ssh_keys[1]
99+
100+
assert ssh_keys1._client is ssh_keys_client
101+
assert ssh_keys1.id == 2323
102+
assert ssh_keys1.name == "SSH-Key"
103+
104+
assert ssh_keys2._client is ssh_keys_client
105+
assert ssh_keys2.id == 2324
106+
assert ssh_keys2.name == "SSH-Key"
107+
78108
def test_create(self, ssh_keys_client, ssh_key_response):
79109
ssh_keys_client._client.request.return_value = ssh_key_response
80110
ssh_key = ssh_keys_client.create(name="My ssh key", public_key="ssh-rsa AAAjjk76kgf...Xt")

tests/unit/volumes/test_client.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def test_bound_volume_init(self, volume_response):
4545
def test_get_actions(self, hetzner_client, bound_volume, response_get_actions):
4646
hetzner_client.request.return_value = response_get_actions
4747
actions = bound_volume.get_actions(sort="id")
48-
hetzner_client.request.assert_called_with(url="/volumes/14/actions", method="GET", params={"sort": "id"})
48+
hetzner_client.request.assert_called_with(url="/volumes/14/actions", method="GET", params={"page": 1, "per_page": 50, "sort": "id"})
4949

5050
assert len(actions) == 1
5151
assert isinstance(actions[0], BoundAction)
@@ -137,7 +137,13 @@ def test_get_by_id(self, volumes_client, volume_response):
137137
assert bound_volume.id == 1
138138
assert bound_volume.name == "database-storage"
139139

140-
@pytest.mark.parametrize("params", [{'label_selector': "label1", 'page': 1, 'per_page': 10}])
140+
@pytest.mark.parametrize(
141+
"params",
142+
[
143+
{'label_selector': "label1", 'page': 1, 'per_page': 10},
144+
{}
145+
]
146+
)
141147
def test_get_list(self, volumes_client, two_volumes_response, params):
142148
volumes_client._client.request.return_value = two_volumes_response
143149
result = volumes_client.get_list(**params)
@@ -258,11 +264,12 @@ def test_create_wrong_location_server_combination(self, volumes_client, location
258264
volumes_client._client.request.assert_not_called()
259265

260266
@pytest.mark.parametrize("volume", [Volume(id=1), BoundVolume(mock.MagicMock(), dict(id=1))])
261-
def test_get_actions(self, volumes_client, volume, response_get_actions):
267+
def test_get_actions_list(self, volumes_client, volume, response_get_actions):
262268
volumes_client._client.request.return_value = response_get_actions
263-
actions = volumes_client.get_actions(volume)
264-
volumes_client._client.request.assert_called_with(url="/volumes/1/actions", method="GET", params={})
269+
result = volumes_client.get_actions_list(volume, sort="id")
270+
volumes_client._client.request.assert_called_with(url="/volumes/1/actions", method="GET", params={"sort": "id"})
265271

272+
actions = result.actions
266273
assert len(actions) == 1
267274
assert isinstance(actions[0], BoundAction)
268275

0 commit comments

Comments
 (0)