diff --git a/tests/unit/actions/test_client.py b/tests/unit/actions/test_client.py index f9943087..a6a3ce25 100644 --- a/tests/unit/actions/test_client.py +++ b/tests/unit/actions/test_client.py @@ -4,6 +4,7 @@ import pytest +from hcloud import Client from hcloud.actions import ( Action, ActionFailedException, @@ -16,31 +17,38 @@ class TestBoundAction: @pytest.fixture() - def bound_running_action(self, mocked_requests): - action_client = ActionsClient(client=mocked_requests) + def bound_running_action(self, client: Client): # Speed up tests that run `wait_until_finished` - action_client._client._poll_interval_func = lambda _: 0.0 - action_client._client._poll_max_retries = 3 + client._poll_interval_func = lambda _: 0.0 + client._poll_max_retries = 3 return BoundAction( - client=action_client, + client=client.actions, data=dict(id=14, status=Action.STATUS_RUNNING), ) def test_wait_until_finished( - self, bound_running_action, mocked_requests, running_action, successfully_action + self, + request_mock: mock.MagicMock, + bound_running_action, + running_action, + successfully_action, ): - mocked_requests.request.side_effect = [running_action, successfully_action] + request_mock.side_effect = [running_action, successfully_action] bound_running_action.wait_until_finished() - mocked_requests.request.assert_called_with(url="/actions/2", method="GET") + request_mock.assert_called_with(url="/actions/2", method="GET") assert bound_running_action.status == "success" - assert mocked_requests.request.call_count == 2 + assert request_mock.call_count == 2 def test_wait_until_finished_with_error( - self, bound_running_action, mocked_requests, running_action, failed_action + self, + request_mock: mock.MagicMock, + bound_running_action, + running_action, + failed_action, ): - mocked_requests.request.side_effect = [running_action, failed_action] + request_mock.side_effect = [running_action, failed_action] with pytest.raises(ActionFailedException) as exception_info: bound_running_action.wait_until_finished() @@ -48,9 +56,13 @@ def test_wait_until_finished_with_error( assert exception_info.value.action.id == 2 def test_wait_until_finished_max_retries( - self, bound_running_action, mocked_requests, running_action, successfully_action + self, + request_mock: mock.MagicMock, + bound_running_action, + running_action, + successfully_action, ): - mocked_requests.request.side_effect = [ + request_mock.side_effect = [ running_action, running_action, successfully_action, @@ -60,7 +72,7 @@ def test_wait_until_finished_max_retries( assert bound_running_action.status == "running" assert exception_info.value.action.id == 2 - assert mocked_requests.request.call_count == 1 + assert request_mock.call_count == 1 class TestResourceActionsClient: diff --git a/tests/unit/certificates/test_client.py b/tests/unit/certificates/test_client.py index a4e5ad2e..77a0ad0b 100644 --- a/tests/unit/certificates/test_client.py +++ b/tests/unit/certificates/test_client.py @@ -4,6 +4,7 @@ import pytest +from hcloud import Client from hcloud.actions import BoundAction from hcloud.certificates import ( BoundCertificate, @@ -15,16 +16,21 @@ class TestBoundCertificate: @pytest.fixture() - def bound_certificate(self, hetzner_client): - return BoundCertificate(client=hetzner_client.certificates, data=dict(id=14)) + def bound_certificate(self, client: Client): + return BoundCertificate(client.certificates, data=dict(id=14)) @pytest.mark.parametrize("params", [{"page": 1, "per_page": 10}, {}]) def test_get_actions_list( - self, hetzner_client, bound_certificate, response_get_actions, params + self, + request_mock: mock.MagicMock, + client: Client, + bound_certificate, + response_get_actions, + params, ): - hetzner_client.request.return_value = response_get_actions + request_mock.return_value = response_get_actions result = bound_certificate.get_actions_list(**params) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/certificates/14/actions", method="GET", params=params ) @@ -33,23 +39,29 @@ def test_get_actions_list( assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "change_protection" - def test_get_actions(self, hetzner_client, bound_certificate, response_get_actions): - hetzner_client.request.return_value = response_get_actions + def test_get_actions( + self, + request_mock: mock.MagicMock, + client: Client, + bound_certificate, + response_get_actions, + ): + request_mock.return_value = response_get_actions actions = bound_certificate.get_actions() params = {"page": 1, "per_page": 50} - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/certificates/14/actions", method="GET", params=params ) assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "change_protection" @@ -77,32 +89,41 @@ def test_bound_certificate_init(self, certificate_response): assert bound_certificate.status.error.message == "error message" def test_update( - self, hetzner_client, bound_certificate, response_update_certificate + self, + request_mock: mock.MagicMock, + bound_certificate, + response_update_certificate, ): - hetzner_client.request.return_value = response_update_certificate + request_mock.return_value = response_update_certificate certificate = bound_certificate.update(name="New name") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/certificates/14", method="PUT", json={"name": "New name"} ) assert certificate.id == 2323 assert certificate.name == "New name" - def test_delete(self, hetzner_client, bound_certificate, generic_action): - hetzner_client.request.return_value = generic_action + def test_delete( + self, + request_mock: mock.MagicMock, + bound_certificate, + generic_action, + ): + request_mock.return_value = generic_action delete_success = bound_certificate.delete() - hetzner_client.request.assert_called_with( - url="/certificates/14", method="DELETE" - ) + request_mock.assert_called_with(url="/certificates/14", method="DELETE") assert delete_success is True def test_retry_issuance( - self, hetzner_client, bound_certificate, response_retry_issuance_action + self, + request_mock: mock.MagicMock, + bound_certificate, + response_retry_issuance_action, ): - hetzner_client.request.return_value = response_retry_issuance_action + request_mock.return_value = response_retry_issuance_action action = bound_certificate.retry_issuance() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/certificates/14/actions/retry", method="POST" ) diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index 0dd4df46..fb620c20 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -1,3 +1,5 @@ +# pylint: disable=redefined-outer-name + from __future__ import annotations from unittest import mock @@ -7,12 +9,16 @@ from hcloud import Client -@pytest.fixture(autouse=True, scope="function") -def mocked_requests(): - patcher = mock.patch("hcloud._client.requests") - mocked_requests = patcher.start() - yield mocked_requests - patcher.stop() +@pytest.fixture() +def request_mock() -> mock.MagicMock: + return mock.MagicMock() + + +@pytest.fixture() +def client(request_mock) -> Client: + c = Client(token="TOKEN") + c.request = request_mock + return c @pytest.fixture() diff --git a/tests/unit/firewalls/test_client.py b/tests/unit/firewalls/test_client.py index 1226c61f..bb3f9402 100644 --- a/tests/unit/firewalls/test_client.py +++ b/tests/unit/firewalls/test_client.py @@ -4,6 +4,7 @@ import pytest +from hcloud import Client from hcloud.actions import BoundAction from hcloud.firewalls import ( BoundFirewall, @@ -18,8 +19,8 @@ class TestBoundFirewall: @pytest.fixture() - def bound_firewall(self, hetzner_client): - return BoundFirewall(client=hetzner_client.firewalls, data=dict(id=1)) + def bound_firewall(self, client: Client): + return BoundFirewall(client.firewalls, data=dict(id=1)) def test_bound_firewall_init(self, firewall_response): bound_firewall = BoundFirewall( @@ -75,11 +76,16 @@ def test_bound_firewall_init(self, firewall_response): "params", [{}, {"sort": ["created"], "page": 1, "per_page": 2}] ) def test_get_actions_list( - self, hetzner_client, bound_firewall, response_get_actions, params + self, + request_mock: mock.MagicMock, + client: Client, + bound_firewall, + response_get_actions, + params, ): - hetzner_client.request.return_value = response_get_actions + request_mock.return_value = response_get_actions result = bound_firewall.get_actions_list(**params) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/firewalls/1/actions", method="GET", params=params ) @@ -88,35 +94,45 @@ def test_get_actions_list( assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "set_firewall_rules" @pytest.mark.parametrize("params", [{}, {"sort": ["created"]}]) def test_get_actions( - self, hetzner_client, bound_firewall, response_get_actions, params + self, + request_mock: mock.MagicMock, + client: Client, + bound_firewall, + response_get_actions, + params, ): - hetzner_client.request.return_value = response_get_actions + request_mock.return_value = response_get_actions actions = bound_firewall.get_actions(**params) params.update({"page": 1, "per_page": 50}) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/firewalls/1/actions", method="GET", params=params ) assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "set_firewall_rules" - def test_update(self, hetzner_client, bound_firewall, response_update_firewall): - hetzner_client.request.return_value = response_update_firewall + def test_update( + self, + request_mock: mock.MagicMock, + bound_firewall, + response_update_firewall, + ): + request_mock.return_value = response_update_firewall firewall = bound_firewall.update( name="New Corporate Intranet Protection", labels={} ) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/firewalls/1", method="PUT", json={"name": "New Corporate Intranet Protection", "labels": {}}, @@ -125,14 +141,23 @@ def test_update(self, hetzner_client, bound_firewall, response_update_firewall): assert firewall.id == 38 assert firewall.name == "New Corporate Intranet Protection" - def test_delete(self, hetzner_client, bound_firewall): + def test_delete( + self, + request_mock: mock.MagicMock, + bound_firewall, + ): delete_success = bound_firewall.delete() - hetzner_client.request.assert_called_with(url="/firewalls/1", method="DELETE") + request_mock.assert_called_with(url="/firewalls/1", method="DELETE") assert delete_success is True - def test_set_rules(self, hetzner_client, bound_firewall, response_set_rules): - hetzner_client.request.return_value = response_set_rules + def test_set_rules( + self, + request_mock: mock.MagicMock, + bound_firewall, + response_set_rules, + ): + request_mock.return_value = response_set_rules actions = bound_firewall.set_rules( [ FirewallRule( @@ -143,7 +168,7 @@ def test_set_rules(self, hetzner_client, bound_firewall, response_set_rules): ) ] ) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/firewalls/1/actions/set_rules", method="POST", json={ @@ -162,13 +187,16 @@ def test_set_rules(self, hetzner_client, bound_firewall, response_set_rules): assert actions[0].progress == 100 def test_apply_to_resources( - self, hetzner_client, bound_firewall, response_set_rules + self, + request_mock: mock.MagicMock, + bound_firewall, + response_set_rules, ): - hetzner_client.request.return_value = response_set_rules + request_mock.return_value = response_set_rules actions = bound_firewall.apply_to_resources( [FirewallResource(type=FirewallResource.TYPE_SERVER, server=Server(id=5))] ) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/firewalls/1/actions/apply_to_resources", method="POST", json={"apply_to": [{"type": "server", "server": {"id": 5}}]}, @@ -178,13 +206,16 @@ def test_apply_to_resources( assert actions[0].progress == 100 def test_remove_from_resources( - self, hetzner_client, bound_firewall, response_set_rules + self, + request_mock: mock.MagicMock, + bound_firewall, + response_set_rules, ): - hetzner_client.request.return_value = response_set_rules + request_mock.return_value = response_set_rules actions = bound_firewall.remove_from_resources( [FirewallResource(type=FirewallResource.TYPE_SERVER, server=Server(id=5))] ) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/firewalls/1/actions/remove_from_resources", method="POST", json={"remove_from": [{"type": "server", "server": {"id": 5}}]}, diff --git a/tests/unit/floating_ips/test_client.py b/tests/unit/floating_ips/test_client.py index 1f1160c6..d48c85cb 100644 --- a/tests/unit/floating_ips/test_client.py +++ b/tests/unit/floating_ips/test_client.py @@ -4,6 +4,7 @@ import pytest +from hcloud import Client from hcloud.actions import BoundAction from hcloud.floating_ips import BoundFloatingIP, FloatingIP, FloatingIPsClient from hcloud.locations import BoundLocation, Location @@ -12,8 +13,8 @@ class TestBoundFloatingIP: @pytest.fixture() - def bound_floating_ip(self, hetzner_client): - return BoundFloatingIP(client=hetzner_client.floating_ips, data=dict(id=14)) + def bound_floating_ip(self, client: Client): + return BoundFloatingIP(client.floating_ips, data=dict(id=14)) def test_bound_floating_ip_init(self, floating_ip_response): bound_floating_ip = BoundFloatingIP( @@ -41,10 +42,16 @@ def test_bound_floating_ip_init(self, floating_ip_response): assert bound_floating_ip.home_location.latitude == 50.47612 assert bound_floating_ip.home_location.longitude == 12.370071 - def test_get_actions(self, hetzner_client, bound_floating_ip, response_get_actions): - hetzner_client.request.return_value = response_get_actions + def test_get_actions( + self, + request_mock: mock.MagicMock, + client: Client, + bound_floating_ip, + response_get_actions, + ): + request_mock.return_value = response_get_actions actions = bound_floating_ip.get_actions(sort="id") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/floating_ips/14/actions", method="GET", params={"sort": "id", "page": 1, "per_page": 50}, @@ -52,18 +59,21 @@ def test_get_actions(self, hetzner_client, bound_floating_ip, response_get_actio assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "assign_floating_ip" def test_update( - self, hetzner_client, bound_floating_ip, response_update_floating_ip + self, + request_mock: mock.MagicMock, + bound_floating_ip, + response_update_floating_ip, ): - hetzner_client.request.return_value = response_update_floating_ip + request_mock.return_value = response_update_floating_ip floating_ip = bound_floating_ip.update( description="New description", name="New name" ) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/floating_ips/14", method="PUT", json={"description": "New description", "name": "New name"}, @@ -73,19 +83,27 @@ def test_update( assert floating_ip.description == "New description" assert floating_ip.name == "New name" - def test_delete(self, hetzner_client, bound_floating_ip, generic_action): - hetzner_client.request.return_value = generic_action + def test_delete( + self, + request_mock: mock.MagicMock, + bound_floating_ip, + generic_action, + ): + request_mock.return_value = generic_action delete_success = bound_floating_ip.delete() - hetzner_client.request.assert_called_with( - url="/floating_ips/14", method="DELETE" - ) + request_mock.assert_called_with(url="/floating_ips/14", method="DELETE") assert delete_success is True - def test_change_protection(self, hetzner_client, bound_floating_ip, generic_action): - hetzner_client.request.return_value = generic_action + def test_change_protection( + self, + request_mock: mock.MagicMock, + bound_floating_ip, + generic_action, + ): + request_mock.return_value = generic_action action = bound_floating_ip.change_protection(True) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/floating_ips/14/actions/change_protection", method="POST", json={"delete": True}, @@ -97,28 +115,44 @@ def test_change_protection(self, hetzner_client, bound_floating_ip, generic_acti @pytest.mark.parametrize( "server", (Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))) ) - def test_assign(self, hetzner_client, bound_floating_ip, server, generic_action): - hetzner_client.request.return_value = generic_action + def test_assign( + self, + request_mock: mock.MagicMock, + bound_floating_ip, + server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_floating_ip.assign(server) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/floating_ips/14/actions/assign", method="POST", json={"server": 1} ) assert action.id == 1 assert action.progress == 0 - def test_unassign(self, hetzner_client, bound_floating_ip, generic_action): - hetzner_client.request.return_value = generic_action + def test_unassign( + self, + request_mock: mock.MagicMock, + bound_floating_ip, + generic_action, + ): + request_mock.return_value = generic_action action = bound_floating_ip.unassign() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/floating_ips/14/actions/unassign", method="POST" ) assert action.id == 1 assert action.progress == 0 - def test_change_dns_ptr(self, hetzner_client, bound_floating_ip, generic_action): - hetzner_client.request.return_value = generic_action + def test_change_dns_ptr( + self, + request_mock: mock.MagicMock, + bound_floating_ip, + generic_action, + ): + request_mock.return_value = generic_action action = bound_floating_ip.change_dns_ptr("1.2.3.4", "server02.example.com") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/floating_ips/14/actions/change_dns_ptr", method="POST", json={"ip": "1.2.3.4", "dns_ptr": "server02.example.com"}, diff --git a/tests/unit/images/test_client.py b/tests/unit/images/test_client.py index cf6ff2f9..62b42bcc 100644 --- a/tests/unit/images/test_client.py +++ b/tests/unit/images/test_client.py @@ -6,6 +6,7 @@ import pytest +from hcloud import Client from hcloud.actions import BoundAction from hcloud.images import BoundImage, Image, ImagesClient from hcloud.servers import BoundServer @@ -13,8 +14,8 @@ class TestBoundImage: @pytest.fixture() - def bound_image(self, hetzner_client): - return BoundImage(client=hetzner_client.images, data=dict(id=14)) + def bound_image(self, client: Client): + return BoundImage(client.images, data=dict(id=14)) def test_bound_image_init(self, image_response): bound_image = BoundImage(client=mock.MagicMock(), data=image_response["image"]) @@ -50,11 +51,16 @@ def test_bound_image_init(self, image_response): "params", [{}, {"sort": ["status"], "page": 1, "per_page": 2}] ) def test_get_actions_list( - self, hetzner_client, bound_image, response_get_actions, params + self, + request_mock: mock.MagicMock, + client: Client, + bound_image, + response_get_actions, + params, ): - hetzner_client.request.return_value = response_get_actions + request_mock.return_value = response_get_actions result = bound_image.get_actions_list(**params) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/images/14/actions", method="GET", params=params ) @@ -63,35 +69,45 @@ def test_get_actions_list( assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "change_protection" @pytest.mark.parametrize("params", [{}, {"sort": ["status"]}]) def test_get_actions( - self, hetzner_client, bound_image, response_get_actions, params + self, + request_mock: mock.MagicMock, + client: Client, + bound_image, + response_get_actions, + params, ): - hetzner_client.request.return_value = response_get_actions + request_mock.return_value = response_get_actions actions = bound_image.get_actions(**params) params.update({"page": 1, "per_page": 50}) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/images/14/actions", method="GET", params=params ) assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "change_protection" - def test_update(self, hetzner_client, bound_image, response_update_image): - hetzner_client.request.return_value = response_update_image + def test_update( + self, + request_mock: mock.MagicMock, + bound_image, + response_update_image, + ): + request_mock.return_value = response_update_image image = bound_image.update( description="My new Image description", type="snapshot", labels={} ) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/images/14", method="PUT", json={ @@ -104,17 +120,27 @@ def test_update(self, hetzner_client, bound_image, response_update_image): assert image.id == 4711 assert image.description == "My new Image description" - def test_delete(self, hetzner_client, bound_image, generic_action): - hetzner_client.request.return_value = generic_action + def test_delete( + self, + request_mock: mock.MagicMock, + bound_image, + generic_action, + ): + request_mock.return_value = generic_action delete_success = bound_image.delete() - hetzner_client.request.assert_called_with(url="/images/14", method="DELETE") + request_mock.assert_called_with(url="/images/14", method="DELETE") assert delete_success is True - def test_change_protection(self, hetzner_client, bound_image, generic_action): - hetzner_client.request.return_value = generic_action + def test_change_protection( + self, + request_mock: mock.MagicMock, + bound_image, + generic_action, + ): + request_mock.return_value = generic_action action = bound_image.change_protection(True) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/images/14/actions/change_protection", method="POST", json={"delete": True}, diff --git a/tests/unit/isos/test_client.py b/tests/unit/isos/test_client.py index 7e71f8dc..9c824377 100644 --- a/tests/unit/isos/test_client.py +++ b/tests/unit/isos/test_client.py @@ -6,13 +6,14 @@ import pytest +from hcloud import Client from hcloud.isos import BoundIso, IsosClient class TestBoundIso: @pytest.fixture() - def bound_iso(self, hetzner_client): - return BoundIso(client=hetzner_client.isos, data=dict(id=14)) + def bound_iso(self, client: Client): + return BoundIso(client.isos, data=dict(id=14)) def test_bound_iso_init(self, iso_response): bound_iso = BoundIso(client=mock.MagicMock(), data=iso_response["iso"]) diff --git a/tests/unit/load_balancers/test_client.py b/tests/unit/load_balancers/test_client.py index 02ce1e50..9010ec7c 100644 --- a/tests/unit/load_balancers/test_client.py +++ b/tests/unit/load_balancers/test_client.py @@ -4,6 +4,7 @@ import pytest +from hcloud import Client from hcloud.actions import BoundAction from hcloud.load_balancer_types import LoadBalancerType from hcloud.load_balancers import ( @@ -24,8 +25,8 @@ class TestBoundLoadBalancer: @pytest.fixture() - def bound_load_balancer(self, hetzner_client): - return BoundLoadBalancer(client=hetzner_client.load_balancers, data=dict(id=14)) + def bound_load_balancer(self, client: Client): + return BoundLoadBalancer(client.load_balancers, data=dict(id=14)) def test_bound_load_balancer_init(self, response_load_balancer): bound_load_balancer = BoundLoadBalancer( @@ -37,11 +38,16 @@ def test_bound_load_balancer_init(self, response_load_balancer): @pytest.mark.parametrize("params", [{"page": 1, "per_page": 10}, {}]) def test_get_actions_list( - self, hetzner_client, bound_load_balancer, response_get_actions, params + self, + request_mock: mock.MagicMock, + client: Client, + bound_load_balancer, + response_get_actions, + params, ): - hetzner_client.request.return_value = response_get_actions + request_mock.return_value = response_get_actions result = bound_load_balancer.get_actions_list(**params) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/load_balancers/14/actions", method="GET", params=params ) @@ -50,35 +56,43 @@ def test_get_actions_list( assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "change_protection" @pytest.mark.parametrize("params", [{}]) def test_get_actions( - self, hetzner_client, bound_load_balancer, response_get_actions, params + self, + request_mock: mock.MagicMock, + client: Client, + bound_load_balancer, + response_get_actions, + params, ): - hetzner_client.request.return_value = response_get_actions + request_mock.return_value = response_get_actions actions = bound_load_balancer.get_actions(**params) params.update({"page": 1, "per_page": 50}) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/load_balancers/14/actions", method="GET", params=params ) assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "change_protection" def test_update( - self, hetzner_client, bound_load_balancer, response_update_load_balancer + self, + request_mock: mock.MagicMock, + bound_load_balancer, + response_update_load_balancer, ): - hetzner_client.request.return_value = response_update_load_balancer + request_mock.return_value = response_update_load_balancer load_balancer = bound_load_balancer.update(name="new-name", labels={}) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/load_balancers/14", method="PUT", json={"name": "new-name", "labels": {}}, @@ -87,28 +101,31 @@ def test_update( assert load_balancer.id == 4711 assert load_balancer.name == "new-name" - def test_delete(self, hetzner_client, generic_action, bound_load_balancer): - hetzner_client.request.return_value = generic_action + def test_delete( + self, + request_mock: mock.MagicMock, + bound_load_balancer, + generic_action, + ): + request_mock.return_value = generic_action delete_success = bound_load_balancer.delete() - hetzner_client.request.assert_called_with( - url="/load_balancers/14", method="DELETE" - ) + request_mock.assert_called_with(url="/load_balancers/14", method="DELETE") assert delete_success is True def test_get_metrics( self, - hetzner_client, - response_get_metrics, + request_mock: mock.MagicMock, bound_load_balancer: BoundLoadBalancer, + response_get_metrics, ): - hetzner_client.request.return_value = response_get_metrics + request_mock.return_value = response_get_metrics response = bound_load_balancer.get_metrics( type=["requests_per_second"], start="2023-12-14T16:55:32+01:00", end="2023-12-14T16:55:32+01:00", ) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/load_balancers/14/metrics", method="GET", params={ @@ -121,12 +138,15 @@ def test_get_metrics( assert len(response.metrics.time_series["requests_per_second"]["values"]) == 3 def test_add_service( - self, hetzner_client, response_add_service, bound_load_balancer + self, + request_mock: mock.MagicMock, + bound_load_balancer, + response_add_service, ): - hetzner_client.request.return_value = response_add_service + request_mock.return_value = response_add_service service = LoadBalancerService(listen_port=80, protocol="http") action = bound_load_balancer.add_service(service) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( json={"protocol": "http", "listen_port": 80}, url="/load_balancers/14/actions/add_service", method="POST", @@ -137,12 +157,15 @@ def test_add_service( assert action.command == "add_service" def test_delete_service( - self, hetzner_client, response_delete_service, bound_load_balancer + self, + request_mock: mock.MagicMock, + bound_load_balancer, + response_delete_service, ): - hetzner_client.request.return_value = response_delete_service + request_mock.return_value = response_delete_service service = LoadBalancerService(listen_port=12) action = bound_load_balancer.delete_service(service) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( json={"listen_port": 12}, url="/load_balancers/14/actions/delete_service", method="POST", @@ -175,12 +198,17 @@ def test_delete_service( ], ) def test_add_target( - self, hetzner_client, response_add_target, bound_load_balancer, target, params + self, + request_mock: mock.MagicMock, + bound_load_balancer, + response_add_target, + target, + params, ): - hetzner_client.request.return_value = response_add_target + request_mock.return_value = response_add_target action = bound_load_balancer.add_target(target) params.update({"type": target.type}) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/load_balancers/14/actions/add_target", method="POST", json=params ) @@ -212,16 +240,16 @@ def test_add_target( ) def test_remove_target( self, - hetzner_client, - response_remove_target, + request_mock: mock.MagicMock, bound_load_balancer, + response_remove_target, target, params, ): - hetzner_client.request.return_value = response_remove_target + request_mock.return_value = response_remove_target action = bound_load_balancer.remove_target(target) params.update({"type": target.type}) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/load_balancers/14/actions/remove_target", method="POST", json=params ) @@ -230,16 +258,19 @@ def test_remove_target( assert action.command == "remove_target" def test_update_service( - self, hetzner_client, response_update_service, bound_load_balancer + self, + request_mock: mock.MagicMock, + bound_load_balancer, + response_update_service, ): - hetzner_client.request.return_value = response_update_service + request_mock.return_value = response_update_service new_health_check = LoadBalancerHealthCheck( protocol="http", port=13, interval=1, timeout=1, retries=1 ) service = LoadBalancerService(listen_port=12, health_check=new_health_check) action = bound_load_balancer.update_service(service) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( json={ "listen_port": 12, "health_check": { @@ -259,12 +290,15 @@ def test_update_service( assert action.command == "update_service" def test_change_algorithm( - self, hetzner_client, response_change_algorithm, bound_load_balancer + self, + request_mock: mock.MagicMock, + bound_load_balancer, + response_change_algorithm, ): - hetzner_client.request.return_value = response_change_algorithm + request_mock.return_value = response_change_algorithm algorithm = LoadBalancerAlgorithm(type="round_robin") action = bound_load_balancer.change_algorithm(algorithm) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( json={"type": "round_robin"}, url="/load_balancers/14/actions/change_algorithm", method="POST", @@ -275,13 +309,16 @@ def test_change_algorithm( assert action.command == "change_algorithm" def test_change_dns_ptr( - self, hetzner_client, response_change_reverse_dns_entry, bound_load_balancer + self, + request_mock: mock.MagicMock, + bound_load_balancer, + response_change_reverse_dns_entry, ): - hetzner_client.request.return_value = response_change_reverse_dns_entry + request_mock.return_value = response_change_reverse_dns_entry action = bound_load_balancer.change_dns_ptr( ip="1.2.3.4", dns_ptr="lb1.example.com" ) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( json={"dns_ptr": "lb1.example.com", "ip": "1.2.3.4"}, url="/load_balancers/14/actions/change_dns_ptr", method="POST", @@ -292,11 +329,14 @@ def test_change_dns_ptr( assert action.command == "change_dns_ptr" def test_change_protection( - self, hetzner_client, response_change_protection, bound_load_balancer + self, + request_mock: mock.MagicMock, + bound_load_balancer, + response_change_protection, ): - hetzner_client.request.return_value = response_change_protection + request_mock.return_value = response_change_protection action = bound_load_balancer.change_protection(delete=True) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( json={"delete": True}, url="/load_balancers/14/actions/change_protection", method="POST", @@ -307,11 +347,14 @@ def test_change_protection( assert action.command == "change_protection" def test_enable_public_interface( - self, response_enable_public_interface, hetzner_client, bound_load_balancer + self, + request_mock: mock.MagicMock, + bound_load_balancer, + response_enable_public_interface, ): - hetzner_client.request.return_value = response_enable_public_interface + request_mock.return_value = response_enable_public_interface action = bound_load_balancer.enable_public_interface() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/load_balancers/14/actions/enable_public_interface", method="POST" ) @@ -320,11 +363,14 @@ def test_enable_public_interface( assert action.command == "enable_public_interface" def test_disable_public_interface( - self, response_disable_public_interface, hetzner_client, bound_load_balancer + self, + request_mock: mock.MagicMock, + bound_load_balancer, + response_disable_public_interface, ): - hetzner_client.request.return_value = response_disable_public_interface + request_mock.return_value = response_disable_public_interface action = bound_load_balancer.disable_public_interface() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/load_balancers/14/actions/disable_public_interface", method="POST" ) @@ -334,13 +380,13 @@ def test_disable_public_interface( def test_attach_to_network( self, - response_attach_load_balancer_to_network, - hetzner_client, + request_mock: mock.MagicMock, bound_load_balancer, + response_attach_load_balancer_to_network, ): - hetzner_client.request.return_value = response_attach_load_balancer_to_network + request_mock.return_value = response_attach_load_balancer_to_network action = bound_load_balancer.attach_to_network(Network(id=1)) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( json={"network": 1}, url="/load_balancers/14/actions/attach_to_network", method="POST", @@ -351,11 +397,14 @@ def test_attach_to_network( assert action.command == "attach_to_network" def test_detach_from_network( - self, response_detach_from_network, hetzner_client, bound_load_balancer + self, + request_mock: mock.MagicMock, + bound_load_balancer, + response_detach_from_network, ): - hetzner_client.request.return_value = response_detach_from_network + request_mock.return_value = response_detach_from_network action = bound_load_balancer.detach_from_network(Network(id=1)) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( json={"network": 1}, url="/load_balancers/14/actions/detach_from_network", method="POST", @@ -365,10 +414,15 @@ def test_detach_from_network( assert action.progress == 100 assert action.command == "detach_from_network" - def test_change_type(self, hetzner_client, bound_load_balancer, generic_action): - hetzner_client.request.return_value = generic_action + def test_change_type( + self, + request_mock: mock.MagicMock, + bound_load_balancer, + generic_action, + ): + request_mock.return_value = generic_action action = bound_load_balancer.change_type(LoadBalancerType(name="lb21")) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/load_balancers/14/actions/change_type", method="POST", json={"load_balancer_type": "lb21"}, diff --git a/tests/unit/networks/test_client.py b/tests/unit/networks/test_client.py index 4e986414..8e365695 100644 --- a/tests/unit/networks/test_client.py +++ b/tests/unit/networks/test_client.py @@ -5,6 +5,7 @@ import pytest from dateutil.parser import isoparse +from hcloud import Client from hcloud.actions import BoundAction from hcloud.networks import ( BoundNetwork, @@ -18,8 +19,8 @@ class TestBoundNetwork: @pytest.fixture() - def bound_network(self, hetzner_client): - return BoundNetwork(client=hetzner_client.networks, data=dict(id=14)) + def bound_network(self, client: Client): + return BoundNetwork(client.networks, data=dict(id=14)) def test_bound_network_init(self, network_response): bound_network = BoundNetwork( @@ -49,10 +50,16 @@ def test_bound_network_init(self, network_response): assert bound_network.routes[0].destination == "10.100.1.0/24" assert bound_network.routes[0].gateway == "10.0.1.1" - def test_get_actions(self, hetzner_client, bound_network, response_get_actions): - hetzner_client.request.return_value = response_get_actions + def test_get_actions( + self, + request_mock: mock.MagicMock, + client: Client, + bound_network, + response_get_actions, + ): + request_mock.return_value = response_get_actions actions = bound_network.get_actions(sort="id") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/networks/14/actions", method="GET", params={"page": 1, "per_page": 50, "sort": "id"}, @@ -60,31 +67,46 @@ def test_get_actions(self, hetzner_client, bound_network, response_get_actions): assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "add_subnet" - def test_update(self, hetzner_client, bound_network, response_update_network): - hetzner_client.request.return_value = response_update_network + def test_update( + self, + request_mock: mock.MagicMock, + bound_network, + response_update_network, + ): + request_mock.return_value = response_update_network network = bound_network.update(name="new-name") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/networks/14", method="PUT", json={"name": "new-name"} ) assert network.id == 4711 assert network.name == "new-name" - def test_delete(self, hetzner_client, bound_network, generic_action): - hetzner_client.request.return_value = generic_action + def test_delete( + self, + request_mock: mock.MagicMock, + bound_network, + generic_action, + ): + request_mock.return_value = generic_action delete_success = bound_network.delete() - hetzner_client.request.assert_called_with(url="/networks/14", method="DELETE") + request_mock.assert_called_with(url="/networks/14", method="DELETE") assert delete_success is True - def test_change_protection(self, hetzner_client, bound_network, generic_action): - hetzner_client.request.return_value = generic_action + def test_change_protection( + self, + request_mock: mock.MagicMock, + bound_network, + generic_action, + ): + request_mock.return_value = generic_action action = bound_network.change_protection(True) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/networks/14/actions/change_protection", method="POST", json={"delete": True}, @@ -93,15 +115,20 @@ def test_change_protection(self, hetzner_client, bound_network, generic_action): assert action.id == 1 assert action.progress == 0 - def test_add_subnet(self, hetzner_client, bound_network, generic_action): - hetzner_client.request.return_value = generic_action + def test_add_subnet( + self, + request_mock: mock.MagicMock, + bound_network, + generic_action, + ): + request_mock.return_value = generic_action subnet = NetworkSubnet( type=NetworkSubnet.TYPE_CLOUD, ip_range="10.0.1.0/24", network_zone="eu-central", ) action = bound_network.add_subnet(subnet) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/networks/14/actions/add_subnet", method="POST", json={ @@ -114,11 +141,16 @@ def test_add_subnet(self, hetzner_client, bound_network, generic_action): assert action.id == 1 assert action.progress == 0 - def test_delete_subnet(self, hetzner_client, bound_network, generic_action): - hetzner_client.request.return_value = generic_action + def test_delete_subnet( + self, + request_mock: mock.MagicMock, + bound_network, + generic_action, + ): + request_mock.return_value = generic_action subnet = NetworkSubnet(ip_range="10.0.1.0/24") action = bound_network.delete_subnet(subnet) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/networks/14/actions/delete_subnet", method="POST", json={"ip_range": "10.0.1.0/24"}, @@ -127,11 +159,16 @@ def test_delete_subnet(self, hetzner_client, bound_network, generic_action): assert action.id == 1 assert action.progress == 0 - def test_add_route(self, hetzner_client, bound_network, generic_action): - hetzner_client.request.return_value = generic_action + def test_add_route( + self, + request_mock: mock.MagicMock, + bound_network, + generic_action, + ): + request_mock.return_value = generic_action route = NetworkRoute(destination="10.100.1.0/24", gateway="10.0.1.1") action = bound_network.add_route(route) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/networks/14/actions/add_route", method="POST", json={"destination": "10.100.1.0/24", "gateway": "10.0.1.1"}, @@ -140,11 +177,16 @@ def test_add_route(self, hetzner_client, bound_network, generic_action): assert action.id == 1 assert action.progress == 0 - def test_delete_route(self, hetzner_client, bound_network, generic_action): - hetzner_client.request.return_value = generic_action + def test_delete_route( + self, + request_mock: mock.MagicMock, + bound_network, + generic_action, + ): + request_mock.return_value = generic_action route = NetworkRoute(destination="10.100.1.0/24", gateway="10.0.1.1") action = bound_network.delete_route(route) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/networks/14/actions/delete_route", method="POST", json={"destination": "10.100.1.0/24", "gateway": "10.0.1.1"}, @@ -153,10 +195,15 @@ def test_delete_route(self, hetzner_client, bound_network, generic_action): assert action.id == 1 assert action.progress == 0 - def test_change_ip(self, hetzner_client, bound_network, generic_action): - hetzner_client.request.return_value = generic_action + def test_change_ip( + self, + request_mock: mock.MagicMock, + bound_network, + generic_action, + ): + request_mock.return_value = generic_action action = bound_network.change_ip_range("10.0.0.0/12") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/networks/14/actions/change_ip_range", method="POST", json={"ip_range": "10.0.0.0/12"}, diff --git a/tests/unit/placement_groups/test_client.py b/tests/unit/placement_groups/test_client.py index 27410cf9..58abd31d 100644 --- a/tests/unit/placement_groups/test_client.py +++ b/tests/unit/placement_groups/test_client.py @@ -4,6 +4,7 @@ import pytest +from hcloud import Client from hcloud.placement_groups import BoundPlacementGroup, PlacementGroupsClient @@ -17,10 +18,8 @@ def check_variables(placement_group, expected): class TestBoundPlacementGroup: @pytest.fixture() - def bound_placement_group(self, hetzner_client): - return BoundPlacementGroup( - client=hetzner_client.placement_groups, data=dict(id=897) - ) + def bound_placement_group(self, client: Client): + return BoundPlacementGroup(client.placement_groups, data=dict(id=897)) def test_bound_placement_group_init(self, placement_group_response): bound_placement_group = BoundPlacementGroup( @@ -32,14 +31,17 @@ def test_bound_placement_group_init(self, placement_group_response): ) def test_update( - self, hetzner_client, bound_placement_group, placement_group_response + self, + request_mock: mock.MagicMock, + bound_placement_group, + placement_group_response, ): - hetzner_client.request.return_value = placement_group_response + request_mock.return_value = placement_group_response placement_group = bound_placement_group.update( name=placement_group_response["placement_group"]["name"], labels=placement_group_response["placement_group"]["labels"], ) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/placement_groups/{placement_group_id}".format( placement_group_id=placement_group_response["placement_group"]["id"] ), @@ -52,11 +54,13 @@ def test_update( check_variables(placement_group, placement_group_response["placement_group"]) - def test_delete(self, hetzner_client, bound_placement_group): + def test_delete( + self, + request_mock: mock.MagicMock, + bound_placement_group, + ): delete_success = bound_placement_group.delete() - hetzner_client.request.assert_called_with( - url="/placement_groups/897", method="DELETE" - ) + request_mock.assert_called_with(url="/placement_groups/897", method="DELETE") assert delete_success is True diff --git a/tests/unit/primary_ips/test_client.py b/tests/unit/primary_ips/test_client.py index 65a19be9..4e57e144 100644 --- a/tests/unit/primary_ips/test_client.py +++ b/tests/unit/primary_ips/test_client.py @@ -4,6 +4,7 @@ import pytest +from hcloud import Client from hcloud.actions import BoundAction from hcloud.datacenters import BoundDatacenter, Datacenter from hcloud.primary_ips import BoundPrimaryIP, PrimaryIP, PrimaryIPsClient @@ -11,8 +12,8 @@ class TestBoundPrimaryIP: @pytest.fixture() - def bound_primary_ip(self, hetzner_client): - return BoundPrimaryIP(client=hetzner_client.primary_ips, data=dict(id=14)) + def bound_primary_ip(self, client: Client): + return BoundPrimaryIP(client.primary_ips, data=dict(id=14)) def test_bound_primary_ip_init(self, primary_ip_response): bound_primary_ip = BoundPrimaryIP( @@ -39,10 +40,15 @@ def test_bound_primary_ip_init(self, primary_ip_response): assert bound_primary_ip.datacenter.location.latitude == 50.47612 assert bound_primary_ip.datacenter.location.longitude == 12.370071 - def test_update(self, hetzner_client, bound_primary_ip, response_update_primary_ip): - hetzner_client.request.return_value = response_update_primary_ip + def test_update( + self, + request_mock: mock.MagicMock, + bound_primary_ip, + response_update_primary_ip, + ): + request_mock.return_value = response_update_primary_ip primary_ip = bound_primary_ip.update(auto_delete=True, name="my-resource") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/primary_ips/14", method="PUT", json={"auto_delete": True, "name": "my-resource"}, @@ -51,19 +57,27 @@ def test_update(self, hetzner_client, bound_primary_ip, response_update_primary_ assert primary_ip.id == 42 assert primary_ip.auto_delete is True - def test_delete(self, hetzner_client, bound_primary_ip, generic_action): - hetzner_client.request.return_value = generic_action + def test_delete( + self, + request_mock: mock.MagicMock, + bound_primary_ip, + generic_action, + ): + request_mock.return_value = generic_action delete_success = bound_primary_ip.delete() - hetzner_client.request.assert_called_with( - url="/primary_ips/14", method="DELETE" - ) + request_mock.assert_called_with(url="/primary_ips/14", method="DELETE") assert delete_success is True - def test_change_protection(self, hetzner_client, bound_primary_ip, generic_action): - hetzner_client.request.return_value = generic_action + def test_change_protection( + self, + request_mock: mock.MagicMock, + bound_primary_ip, + generic_action, + ): + request_mock.return_value = generic_action action = bound_primary_ip.change_protection(True) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/primary_ips/14/actions/change_protection", method="POST", json={"delete": True}, @@ -72,10 +86,15 @@ def test_change_protection(self, hetzner_client, bound_primary_ip, generic_actio assert action.id == 1 assert action.progress == 0 - def test_assign(self, hetzner_client, bound_primary_ip, generic_action): - hetzner_client.request.return_value = generic_action + def test_assign( + self, + request_mock: mock.MagicMock, + bound_primary_ip, + generic_action, + ): + request_mock.return_value = generic_action action = bound_primary_ip.assign(assignee_id=12, assignee_type="server") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/primary_ips/14/actions/assign", method="POST", json={"assignee_id": 12, "assignee_type": "server"}, @@ -83,19 +102,29 @@ def test_assign(self, hetzner_client, bound_primary_ip, generic_action): assert action.id == 1 assert action.progress == 0 - def test_unassign(self, hetzner_client, bound_primary_ip, generic_action): - hetzner_client.request.return_value = generic_action + def test_unassign( + self, + request_mock: mock.MagicMock, + bound_primary_ip, + generic_action, + ): + request_mock.return_value = generic_action action = bound_primary_ip.unassign() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/primary_ips/14/actions/unassign", method="POST" ) assert action.id == 1 assert action.progress == 0 - def test_change_dns_ptr(self, hetzner_client, bound_primary_ip, generic_action): - hetzner_client.request.return_value = generic_action + def test_change_dns_ptr( + self, + request_mock: mock.MagicMock, + bound_primary_ip, + generic_action, + ): + request_mock.return_value = generic_action action = bound_primary_ip.change_dns_ptr("1.2.3.4", "server02.example.com") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/primary_ips/14/actions/change_dns_ptr", method="POST", json={"ip": "1.2.3.4", "dns_ptr": "server02.example.com"}, diff --git a/tests/unit/server_types/test_client.py b/tests/unit/server_types/test_client.py index 6021a563..633f67d9 100644 --- a/tests/unit/server_types/test_client.py +++ b/tests/unit/server_types/test_client.py @@ -5,13 +5,14 @@ import pytest +from hcloud import Client from hcloud.server_types import BoundServerType, ServerTypesClient class TestBoundServerType: @pytest.fixture() - def bound_server_type(self, hetzner_client): - return BoundServerType(client=hetzner_client.server_types, data=dict(id=14)) + def bound_server_type(self, client: Client): + return BoundServerType(client.server_types, data=dict(id=14)) def test_bound_server_type_init(self, server_type_response): bound_server_type = BoundServerType( diff --git a/tests/unit/servers/test_client.py b/tests/unit/servers/test_client.py index cb69f4f6..214de3f0 100644 --- a/tests/unit/servers/test_client.py +++ b/tests/unit/servers/test_client.py @@ -4,6 +4,7 @@ import pytest +from hcloud import Client from hcloud.actions import BoundAction from hcloud.datacenters import BoundDatacenter, Datacenter from hcloud.firewalls import BoundFirewall, Firewall @@ -29,8 +30,8 @@ class TestBoundServer: @pytest.fixture() - def bound_server(self, hetzner_client): - return BoundServer(client=hetzner_client.servers, data=dict(id=14)) + def bound_server(self, client: Client): + return BoundServer(client.servers, data=dict(id=14)) def test_bound_server_init(self, response_full_server): bound_server = BoundServer( @@ -134,11 +135,16 @@ def test_bound_server_init(self, response_full_server): ], ) def test_get_actions_list( - self, hetzner_client, bound_server, response_get_actions, params + self, + request_mock: mock.MagicMock, + client: Client, + bound_server, + response_get_actions, + params, ): - hetzner_client.request.return_value = response_get_actions + request_mock.return_value = response_get_actions result = bound_server.get_actions_list(**params) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions", method="GET", params=params ) @@ -147,7 +153,7 @@ def test_get_actions_list( assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "start_server" @@ -155,54 +161,69 @@ def test_get_actions_list( "params", [{"status": [Server.STATUS_RUNNING], "sort": "status"}, {}] ) def test_get_actions( - self, hetzner_client, bound_server, response_get_actions, params + self, + request_mock: mock.MagicMock, + client: Client, + bound_server, + response_get_actions, + params, ): - hetzner_client.request.return_value = response_get_actions + request_mock.return_value = response_get_actions actions = bound_server.get_actions(**params) params.update({"page": 1, "per_page": 50}) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions", method="GET", params=params ) assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "start_server" - def test_update(self, hetzner_client, bound_server, response_update_server): - hetzner_client.request.return_value = response_update_server + def test_update( + self, + request_mock: mock.MagicMock, + bound_server, + response_update_server, + ): + request_mock.return_value = response_update_server server = bound_server.update(name="new-name", labels={}) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14", method="PUT", json={"name": "new-name", "labels": {}} ) assert server.id == 14 assert server.name == "new-name" - def test_delete(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_delete( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.delete() - hetzner_client.request.assert_called_with(url="/servers/14", method="DELETE") + request_mock.assert_called_with(url="/servers/14", method="DELETE") assert action.id == 1 assert action.progress == 0 def test_get_metrics( self, - hetzner_client, + request_mock: mock.MagicMock, bound_server: BoundServer, response_get_metrics, ): - hetzner_client.request.return_value = response_get_metrics + request_mock.return_value = response_get_metrics response = bound_server.get_metrics( type=["cpu", "disk"], start="2023-12-14T17:40:00+01:00", end="2023-12-14T17:50:00+01:00", ) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/metrics", method="GET", params={ @@ -216,50 +237,71 @@ def test_get_metrics( assert "disk.0.iops.read" in response.metrics.time_series assert len(response.metrics.time_series["disk.0.iops.read"]["values"]) == 3 - def test_power_off(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_power_off( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.power_off() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/poweroff", method="POST" ) assert action.id == 1 assert action.progress == 0 - def test_power_on(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_power_on( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.power_on() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/poweron", method="POST" ) assert action.id == 1 assert action.progress == 0 - def test_reboot(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_reboot( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.reboot() - hetzner_client.request.assert_called_with( - url="/servers/14/actions/reboot", method="POST" - ) + request_mock.assert_called_with(url="/servers/14/actions/reboot", method="POST") assert action.id == 1 assert action.progress == 0 - def test_reset(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_reset( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.reset() - hetzner_client.request.assert_called_with( - url="/servers/14/actions/reset", method="POST" - ) + request_mock.assert_called_with(url="/servers/14/actions/reset", method="POST") assert action.id == 1 assert action.progress == 0 - def test_shutdown(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_shutdown( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.shutdown() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/shutdown", method="POST" ) @@ -267,11 +309,14 @@ def test_shutdown(self, hetzner_client, bound_server, generic_action): assert action.progress == 0 def test_reset_password( - self, hetzner_client, bound_server, response_server_reset_password + self, + request_mock: mock.MagicMock, + bound_server, + response_server_reset_password, ): - hetzner_client.request.return_value = response_server_reset_password + request_mock.return_value = response_server_reset_password response = bound_server.reset_password() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/reset_password", method="POST" ) @@ -279,10 +324,15 @@ def test_reset_password( assert response.action.progress == 0 assert response.root_password == "YItygq1v3GYjjMomLaKc" - def test_change_type(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_change_type( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.change_type(ServerType(name="cx11"), upgrade_disk=True) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/change_type", method="POST", json={"server_type": "cx11", "upgrade_disk": True}, @@ -292,11 +342,14 @@ def test_change_type(self, hetzner_client, bound_server, generic_action): assert action.progress == 0 def test_enable_rescue( - self, hetzner_client, bound_server, response_server_enable_rescue + self, + request_mock: mock.MagicMock, + bound_server, + response_server_enable_rescue, ): - hetzner_client.request.return_value = response_server_enable_rescue + request_mock.return_value = response_server_enable_rescue response = bound_server.enable_rescue(type="linux64") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/enable_rescue", method="POST", json={"type": "linux64"}, @@ -306,10 +359,15 @@ def test_enable_rescue( assert response.action.progress == 0 assert response.root_password == "YItygq1v3GYjjMomLaKc" - def test_disable_rescue(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_disable_rescue( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.disable_rescue() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/disable_rescue", method="POST" ) @@ -317,11 +375,14 @@ def test_disable_rescue(self, hetzner_client, bound_server, generic_action): assert action.progress == 0 def test_create_image( - self, hetzner_client, bound_server, response_server_create_image + self, + request_mock: mock.MagicMock, + bound_server, + response_server_create_image, ): - hetzner_client.request.return_value = response_server_create_image + request_mock.return_value = response_server_create_image response = bound_server.create_image(description="my image", type="snapshot") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/create_image", method="POST", json={"description": "my image", "type": "snapshot"}, @@ -331,13 +392,18 @@ def test_create_image( assert response.action.progress == 0 assert response.image.description == "my image" - def test_rebuild(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_rebuild( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action response = bound_server.rebuild( Image(name="ubuntu-20.04"), return_response=True, ) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/rebuild", method="POST", json={"image": "ubuntu-20.04"}, @@ -347,30 +413,45 @@ def test_rebuild(self, hetzner_client, bound_server, generic_action): assert response.action.progress == 0 assert response.root_password is None or isinstance(response.root_password, str) - def test_enable_backup(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_enable_backup( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.enable_backup() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/enable_backup", method="POST" ) assert action.id == 1 assert action.progress == 0 - def test_disable_backup(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_disable_backup( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.disable_backup() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/disable_backup", method="POST" ) assert action.id == 1 assert action.progress == 0 - def test_attach_iso(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_attach_iso( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.attach_iso(Iso(name="FreeBSD-11.0-RELEASE-amd64-dvd1")) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/attach_iso", method="POST", json={"iso": "FreeBSD-11.0-RELEASE-amd64-dvd1"}, @@ -379,20 +460,30 @@ def test_attach_iso(self, hetzner_client, bound_server, generic_action): assert action.id == 1 assert action.progress == 0 - def test_detach_iso(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_detach_iso( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.detach_iso() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/detach_iso", method="POST" ) assert action.id == 1 assert action.progress == 0 - def test_change_dns_ptr(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_change_dns_ptr( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.change_dns_ptr("1.2.3.4", "example.com") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/change_dns_ptr", method="POST", json={"ip": "1.2.3.4", "dns_ptr": "example.com"}, @@ -401,10 +492,15 @@ def test_change_dns_ptr(self, hetzner_client, bound_server, generic_action): assert action.id == 1 assert action.progress == 0 - def test_change_protection(self, hetzner_client, bound_server, generic_action): - hetzner_client.request.return_value = generic_action + def test_change_protection( + self, + request_mock: mock.MagicMock, + bound_server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_server.change_protection(True, True) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/change_protection", method="POST", json={"delete": True, "rebuild": True}, @@ -414,11 +510,14 @@ def test_change_protection(self, hetzner_client, bound_server, generic_action): assert action.progress == 0 def test_request_console( - self, hetzner_client, bound_server, response_server_request_console + self, + request_mock: mock.MagicMock, + bound_server, + response_server_request_console, ): - hetzner_client.request.return_value = response_server_request_console + request_mock.return_value = response_server_request_console response = bound_server.request_console() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/request_console", method="POST" ) @@ -434,13 +533,17 @@ def test_request_console( "network", [Network(id=4711), BoundNetwork(mock.MagicMock(), dict(id=4711))] ) def test_attach_to_network( - self, hetzner_client, bound_server, network, response_attach_to_network + self, + request_mock: mock.MagicMock, + bound_server, + network, + response_attach_to_network, ): - hetzner_client.request.return_value = response_attach_to_network + request_mock.return_value = response_attach_to_network action = bound_server.attach_to_network( network, "10.0.1.1", ["10.0.1.2", "10.0.1.3"] ) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/attach_to_network", method="POST", json={ @@ -458,11 +561,15 @@ def test_attach_to_network( "network", [Network(id=4711), BoundNetwork(mock.MagicMock(), dict(id=4711))] ) def test_detach_from_network( - self, hetzner_client, bound_server, network, response_detach_from_network + self, + request_mock: mock.MagicMock, + bound_server, + network, + response_detach_from_network, ): - hetzner_client.request.return_value = response_detach_from_network + request_mock.return_value = response_detach_from_network action = bound_server.detach_from_network(network) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/detach_from_network", method="POST", json={"network": 4711}, @@ -476,11 +583,15 @@ def test_detach_from_network( "network", [Network(id=4711), BoundNetwork(mock.MagicMock(), dict(id=4711))] ) def test_change_alias_ips( - self, hetzner_client, bound_server, network, response_change_alias_ips + self, + request_mock: mock.MagicMock, + bound_server, + network, + response_change_alias_ips, ): - hetzner_client.request.return_value = response_change_alias_ips + request_mock.return_value = response_change_alias_ips action = bound_server.change_alias_ips(network, ["10.0.1.2", "10.0.1.3"]) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/change_alias_ips", method="POST", json={"network": 4711, "alias_ips": ["10.0.1.2", "10.0.1.3"]}, @@ -496,14 +607,14 @@ def test_change_alias_ips( ) def test_add_to_placement_group( self, - hetzner_client, + request_mock: mock.MagicMock, bound_server, placement_group, response_add_to_placement_group, ): - hetzner_client.request.return_value = response_add_to_placement_group + request_mock.return_value = response_add_to_placement_group action = bound_server.add_to_placement_group(placement_group) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/add_to_placement_group", method="POST", json={"placement_group": 897}, @@ -514,11 +625,14 @@ def test_add_to_placement_group( assert action.command == "add_to_placement_group" def test_remove_from_placement_group( - self, hetzner_client, bound_server, response_remove_from_placement_group + self, + request_mock: mock.MagicMock, + bound_server, + response_remove_from_placement_group, ): - hetzner_client.request.return_value = response_remove_from_placement_group + request_mock.return_value = response_remove_from_placement_group action = bound_server.remove_from_placement_group() - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/servers/14/actions/remove_from_placement_group", method="POST" ) diff --git a/tests/unit/ssh_keys/test_client.py b/tests/unit/ssh_keys/test_client.py index 8a64a89f..e11f5205 100644 --- a/tests/unit/ssh_keys/test_client.py +++ b/tests/unit/ssh_keys/test_client.py @@ -4,13 +4,14 @@ import pytest +from hcloud import Client from hcloud.ssh_keys import BoundSSHKey, SSHKey, SSHKeysClient class TestBoundSSHKey: @pytest.fixture() - def bound_ssh_key(self, hetzner_client): - return BoundSSHKey(client=hetzner_client.ssh_keys, data=dict(id=14)) + def bound_ssh_key(self, client: Client): + return BoundSSHKey(client.ssh_keys, data=dict(id=14)) def test_bound_ssh_key_init(self, ssh_key_response): bound_ssh_key = BoundSSHKey( @@ -25,20 +26,30 @@ def test_bound_ssh_key_init(self, ssh_key_response): ) assert bound_ssh_key.public_key == "ssh-rsa AAAjjk76kgf...Xt" - def test_update(self, hetzner_client, bound_ssh_key, response_update_ssh_key): - hetzner_client.request.return_value = response_update_ssh_key + def test_update( + self, + request_mock: mock.MagicMock, + bound_ssh_key, + response_update_ssh_key, + ): + request_mock.return_value = response_update_ssh_key ssh_key = bound_ssh_key.update(name="New name") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/ssh_keys/14", method="PUT", json={"name": "New name"} ) assert ssh_key.id == 2323 assert ssh_key.name == "New name" - def test_delete(self, hetzner_client, bound_ssh_key, generic_action): - hetzner_client.request.return_value = generic_action + def test_delete( + self, + request_mock: mock.MagicMock, + bound_ssh_key, + generic_action, + ): + request_mock.return_value = generic_action delete_success = bound_ssh_key.delete() - hetzner_client.request.assert_called_with(url="/ssh_keys/14", method="DELETE") + request_mock.assert_called_with(url="/ssh_keys/14", method="DELETE") assert delete_success is True diff --git a/tests/unit/volumes/test_client.py b/tests/unit/volumes/test_client.py index 1133a417..5662d23e 100644 --- a/tests/unit/volumes/test_client.py +++ b/tests/unit/volumes/test_client.py @@ -5,6 +5,7 @@ import pytest from dateutil.parser import isoparse +from hcloud import Client from hcloud.actions import BoundAction from hcloud.locations import BoundLocation, Location from hcloud.servers import BoundServer, Server @@ -13,8 +14,8 @@ class TestBoundVolume: @pytest.fixture() - def bound_volume(self, hetzner_client): - return BoundVolume(client=hetzner_client.volumes, data=dict(id=14)) + def bound_volume(self, client: Client): + return BoundVolume(client.volumes, data=dict(id=14)) def test_bound_volume_init(self, volume_response): bound_volume = BoundVolume( @@ -41,10 +42,16 @@ def test_bound_volume_init(self, volume_response): assert bound_volume.location.latitude == 50.47612 assert bound_volume.location.longitude == 12.370071 - def test_get_actions(self, hetzner_client, bound_volume, response_get_actions): - hetzner_client.request.return_value = response_get_actions + def test_get_actions( + self, + request_mock: mock.MagicMock, + client: Client, + bound_volume, + response_get_actions, + ): + request_mock.return_value = response_get_actions actions = bound_volume.get_actions(sort="id") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/volumes/14/actions", method="GET", params={"page": 1, "per_page": 50, "sort": "id"}, @@ -52,31 +59,46 @@ def test_get_actions(self, hetzner_client, bound_volume, response_get_actions): assert len(actions) == 1 assert isinstance(actions[0], BoundAction) - assert actions[0]._client == hetzner_client.actions + assert actions[0]._client == client.actions assert actions[0].id == 13 assert actions[0].command == "attach_volume" - def test_update(self, hetzner_client, bound_volume, response_update_volume): - hetzner_client.request.return_value = response_update_volume + def test_update( + self, + request_mock: mock.MagicMock, + bound_volume, + response_update_volume, + ): + request_mock.return_value = response_update_volume volume = bound_volume.update(name="new-name") - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/volumes/14", method="PUT", json={"name": "new-name"} ) assert volume.id == 4711 assert volume.name == "new-name" - def test_delete(self, hetzner_client, bound_volume, generic_action): - hetzner_client.request.return_value = generic_action + def test_delete( + self, + request_mock: mock.MagicMock, + bound_volume, + generic_action, + ): + request_mock.return_value = generic_action delete_success = bound_volume.delete() - hetzner_client.request.assert_called_with(url="/volumes/14", method="DELETE") + request_mock.assert_called_with(url="/volumes/14", method="DELETE") assert delete_success is True - def test_change_protection(self, hetzner_client, bound_volume, generic_action): - hetzner_client.request.return_value = generic_action + def test_change_protection( + self, + request_mock: mock.MagicMock, + bound_volume, + generic_action, + ): + request_mock.return_value = generic_action action = bound_volume.change_protection(True) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/volumes/14/actions/change_protection", method="POST", json={"delete": True}, @@ -88,10 +110,16 @@ def test_change_protection(self, hetzner_client, bound_volume, generic_action): @pytest.mark.parametrize( "server", (Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))) ) - def test_attach(self, hetzner_client, bound_volume, server, generic_action): - hetzner_client.request.return_value = generic_action + def test_attach( + self, + request_mock: mock.MagicMock, + bound_volume, + server, + generic_action, + ): + request_mock.return_value = generic_action action = bound_volume.attach(server) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/volumes/14/actions/attach", method="POST", json={"server": 1} ) assert action.id == 1 @@ -101,11 +129,15 @@ def test_attach(self, hetzner_client, bound_volume, server, generic_action): "server", (Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))) ) def test_attach_with_automount( - self, hetzner_client, bound_volume, server, generic_action + self, + request_mock: mock.MagicMock, + bound_volume, + server, + generic_action, ): - hetzner_client.request.return_value = generic_action + request_mock.return_value = generic_action action = bound_volume.attach(server, False) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/volumes/14/actions/attach", method="POST", json={"server": 1, "automount": False}, @@ -113,19 +145,27 @@ def test_attach_with_automount( assert action.id == 1 assert action.progress == 0 - def test_detach(self, hetzner_client, bound_volume, generic_action): - hetzner_client.request.return_value = generic_action + def test_detach( + self, + request_mock: mock.MagicMock, + bound_volume, + generic_action, + ): + request_mock.return_value = generic_action action = bound_volume.detach() - hetzner_client.request.assert_called_with( - url="/volumes/14/actions/detach", method="POST" - ) + request_mock.assert_called_with(url="/volumes/14/actions/detach", method="POST") assert action.id == 1 assert action.progress == 0 - def test_resize(self, hetzner_client, bound_volume, generic_action): - hetzner_client.request.return_value = generic_action + def test_resize( + self, + request_mock: mock.MagicMock, + bound_volume, + generic_action, + ): + request_mock.return_value = generic_action action = bound_volume.resize(50) - hetzner_client.request.assert_called_with( + request_mock.assert_called_with( url="/volumes/14/actions/resize", method="POST", json={"size": 50} ) assert action.id == 1