예제 #1
0
    def realise_modify_routes(self, allow_recreate: bool) -> None:
        defn: NetworkOptions = self.get_defn().config

        # workaround to get hashable types
        # TODO patch nixops StateDict getter for dicts (if appropriate)
        prev_routes = {
            RouteOptions(**x)
            for x in self._state.get("routes", ())
        }
        final_routes = set(defn.routes)

        for route in prev_routes - final_routes:
            self.logger.log(f"deleting route for {route.gateway}")
            self.wait_on_action(self.get_client().networks.delete_route(
                network=Network(self.resource_id),
                route=NetworkRoute(route.destination, route.gateway),
            ))

        for route in final_routes - prev_routes:
            self.logger.log(f"adding route to {route.gateway}")
            self.wait_on_action(self.get_client().networks.add_route(
                network=Network(self.resource_id),
                route=NetworkRoute(route.destination, route.gateway),
            ))

        # Why must we insert as a list when the original type (tuple) is json encodable?
        # StateDict setter accepts inserting lists and dicts for legacy reasons.
        # TODO patch nixops to encode tuples (in addition, for backwards compat)
        with self.depl._db:
            self._state["routes"] = list(defn.routes)
예제 #2
0
    def test_create(self, hetzner_client):
        response = hetzner_client.servers.create(
            "my-server",
            server_type=ServerType(name="cx11"),
            image=Image(name="ubuntu-16.04"),
            ssh_keys=[SSHKey(name="my-ssh-key")],
            volumes=[Volume(id=1)],
            networks=[Network(id=1)],
            user_data=
            "#cloud-config\\nruncmd:\\n- [touch, /root/cloud-init-worked]\\n",
            location=Location(name="nbg1"),
            automount=False)
        server = response.server
        action = response.action
        next_actions = response.next_actions
        root_password = response.root_password

        assert server.id == 42
        assert server.volumes == []
        assert server.server_type.id == 1
        assert server.datacenter.id == 1
        assert server.image.id == 4711

        assert action.id == 1
        assert action.command == "create_server"

        assert len(next_actions) == 1
        assert next_actions[0].id == 13
        assert next_actions[0].command == "start_server"

        assert root_password == "YItygq1v3GYjjMomLaKc"
예제 #3
0
    def test_detach_from_network(self, response_detach_from_network,
                                 hetzner_client, bound_load_balancer):
        hetzner_client.request.return_value = response_detach_from_network
        action = bound_load_balancer.detach_from_network(Network(id=1))
        hetzner_client.request.assert_called_with(
            json={"network": 1},
            url="/load_balancers/14/actions/detach_from_network",
            method="POST")

        assert action.id == 13
        assert action.progress == 100
        assert action.command == "detach_from_network"
예제 #4
0
    def realise_modify_subnets(self, allow_recreate: bool) -> None:
        defn: NetworkOptions = self.get_defn().config

        prev_subnets = set(self._state.get("subnets", ()))
        final_subnets = set(defn.subnets)

        for ip_range in prev_subnets - final_subnets:
            self.logger.log(f"deleting subnet {ip_range}")
            self.wait_on_action(self.get_client().networks.delete_subnet(
                network=Network(self.resource_id),
                subnet=NetworkSubnet(ip_range, "cloud", "eu-central"),
            ))

        for ip_range in final_subnets - prev_subnets:
            self.logger.log(f"adding subnet {ip_range}")
            self.wait_on_action(self.get_client().networks.add_subnet(
                network=Network(self.resource_id),
                subnet=NetworkSubnet(ip_range, "cloud", "eu-central"),
            ))

        with self.depl._db:
            self._state["subnets"] = list(defn.subnets)
def create():
    with open(data_file, "r") as file:
        data = json.load(file)

    client = Client(token=data["token"])
    response = client.servers.create("win10-OCR",
                                     server_type=ServerType(name="cx41"),
                                     image=Image(id=22859215),
                                     networks=[Network(id=135205)],
                                     location=Location(id=2))
    server = response.server
    data["server_id"] = f"{server.id}"

    with open(data_file, "w") as file:
        json.dump(data, file, indent=4)
    click.echo("creation complete")
예제 #6
0
    def test_create_with_networks(self, servers_client, response_create_simple_server):
        servers_client._client.request.return_value = response_create_simple_server
        networks = [Network(id=1), BoundNetwork(mock.MagicMock(), dict(id=2))]
        response = servers_client.create(
            "my-server",
            server_type=ServerType(name="cx11"),
            image=Image(id=4711),
            networks=networks,
            start_after_create=False
        )
        servers_client._client.request.assert_called_with(
            url="/servers",
            method="POST",
            json={
                'name': "my-server",
                'server_type': "cx11",
                'image': 4711,
                'networks': [1, 2],
                "start_after_create": False
            }
        )

        bound_server = response.server
        bound_action = response.action
        next_actions = response.next_actions
        root_password = response.root_password

        assert root_password == "YItygq1v3GYjjMomLaKc"

        assert bound_server._client is servers_client
        assert bound_server.id == 1
        assert bound_server.name == "my-server"

        assert isinstance(bound_action, BoundAction)
        assert bound_action._client == servers_client._client.actions
        assert bound_action.id == 1
        assert bound_action.command == "create_server"

        assert next_actions[0].id == 13
예제 #7
0
class TestServersClient(object):
    @pytest.fixture()
    def servers_client(self):
        return ServersClient(client=mock.MagicMock())

    def test_get_by_id(self, servers_client, response_simple_server):
        servers_client._client.request.return_value = response_simple_server
        bound_server = servers_client.get_by_id(1)
        servers_client._client.request.assert_called_with(url="/servers/1",
                                                          method="GET")
        assert bound_server._client is servers_client
        assert bound_server.id == 1
        assert bound_server.name == "my-server"

    @pytest.mark.parametrize("params", [{
        'name': "server1",
        'label_selector': "label1",
        'page': 1,
        'per_page': 10
    }, {
        'name': ""
    }, {}])
    def test_get_list(self, servers_client, response_simple_servers, params):
        servers_client._client.request.return_value = response_simple_servers
        result = servers_client.get_list(**params)
        servers_client._client.request.assert_called_with(url="/servers",
                                                          method="GET",
                                                          params=params)

        bound_servers = result.servers
        assert result.meta is None

        assert len(bound_servers) == 2

        bound_server1 = bound_servers[0]
        bound_server2 = bound_servers[1]

        assert bound_server1._client is servers_client
        assert bound_server1.id == 1
        assert bound_server1.name == "my-server"

        assert bound_server2._client is servers_client
        assert bound_server2.id == 2
        assert bound_server2.name == "my-server2"

    @pytest.mark.parametrize("params", [{
        'name': "server1",
        'label_selector': "label1"
    }, {}])
    def test_get_all(self, servers_client, response_simple_servers, params):
        servers_client._client.request.return_value = response_simple_servers
        bound_servers = servers_client.get_all(**params)

        params.update({'page': 1, 'per_page': 50})

        servers_client._client.request.assert_called_with(url="/servers",
                                                          method="GET",
                                                          params=params)

        assert len(bound_servers) == 2

        bound_server1 = bound_servers[0]
        bound_server2 = bound_servers[1]

        assert bound_server1._client is servers_client
        assert bound_server1.id == 1
        assert bound_server1.name == "my-server"

        assert bound_server2._client is servers_client
        assert bound_server2.id == 2
        assert bound_server2.name == "my-server2"

    def test_get_by_name(self, servers_client, response_simple_servers):
        servers_client._client.request.return_value = response_simple_servers
        bound_server = servers_client.get_by_name("my-server")

        params = {'name': "my-server"}

        servers_client._client.request.assert_called_with(url="/servers",
                                                          method="GET",
                                                          params=params)

        assert bound_server._client is servers_client
        assert bound_server.id == 1
        assert bound_server.name == "my-server"

    def test_create_with_datacenter(self, servers_client,
                                    response_create_simple_server):
        servers_client._client.request.return_value = response_create_simple_server
        response = servers_client.create("my-server",
                                         server_type=ServerType(name="cx11"),
                                         image=Image(id=4711),
                                         datacenter=Datacenter(id=1))
        servers_client._client.request.assert_called_with(
            url="/servers",
            method="POST",
            json={
                'name': "my-server",
                'server_type': "cx11",
                'image': 4711,
                'datacenter': 1,
                "start_after_create": True
            })

        bound_server = response.server

        assert bound_server._client is servers_client
        assert bound_server.id == 1
        assert bound_server.name == "my-server"

    def test_create_with_location(self, servers_client,
                                  response_create_simple_server):
        servers_client._client.request.return_value = response_create_simple_server
        response = servers_client.create("my-server",
                                         server_type=ServerType(name="cx11"),
                                         image=Image(name="ubuntu-20.04"),
                                         location=Location(name="fsn1"))
        servers_client._client.request.assert_called_with(
            url="/servers",
            method="POST",
            json={
                'name': "my-server",
                'server_type': "cx11",
                'image': "ubuntu-20.04",
                'location': "fsn1",
                "start_after_create": True
            })

        bound_server = response.server
        bound_action = response.action

        assert bound_server._client is servers_client
        assert bound_server.id == 1
        assert bound_server.name == "my-server"

        assert isinstance(bound_action, BoundAction)
        assert bound_action._client == servers_client._client.actions
        assert bound_action.id == 1
        assert bound_action.command == "create_server"

    def test_create_with_volumes(self, servers_client,
                                 response_create_simple_server):
        servers_client._client.request.return_value = response_create_simple_server
        volumes = [Volume(id=1), BoundVolume(mock.MagicMock(), dict(id=2))]
        response = servers_client.create("my-server",
                                         server_type=ServerType(name="cx11"),
                                         image=Image(id=4711),
                                         volumes=volumes,
                                         start_after_create=False)
        servers_client._client.request.assert_called_with(
            url="/servers",
            method="POST",
            json={
                'name': "my-server",
                'server_type': "cx11",
                'image': 4711,
                'volumes': [1, 2],
                "start_after_create": False
            })

        bound_server = response.server
        bound_action = response.action
        next_actions = response.next_actions
        root_password = response.root_password

        assert root_password == "YItygq1v3GYjjMomLaKc"

        assert bound_server._client is servers_client
        assert bound_server.id == 1
        assert bound_server.name == "my-server"

        assert isinstance(bound_action, BoundAction)
        assert bound_action._client == servers_client._client.actions
        assert bound_action.id == 1
        assert bound_action.command == "create_server"

        assert next_actions[0].id == 13

    def test_create_with_networks(self, servers_client,
                                  response_create_simple_server):
        servers_client._client.request.return_value = response_create_simple_server
        networks = [Network(id=1), BoundNetwork(mock.MagicMock(), dict(id=2))]
        response = servers_client.create("my-server",
                                         server_type=ServerType(name="cx11"),
                                         image=Image(id=4711),
                                         networks=networks,
                                         start_after_create=False)
        servers_client._client.request.assert_called_with(
            url="/servers",
            method="POST",
            json={
                'name': "my-server",
                'server_type': "cx11",
                'image': 4711,
                'networks': [1, 2],
                "start_after_create": False
            })

        bound_server = response.server
        bound_action = response.action
        next_actions = response.next_actions
        root_password = response.root_password

        assert root_password == "YItygq1v3GYjjMomLaKc"

        assert bound_server._client is servers_client
        assert bound_server.id == 1
        assert bound_server.name == "my-server"

        assert isinstance(bound_action, BoundAction)
        assert bound_action._client == servers_client._client.actions
        assert bound_action.id == 1
        assert bound_action.command == "create_server"

        assert next_actions[0].id == 13

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_get_actions_list(self, servers_client, server,
                              response_get_actions):
        servers_client._client.request.return_value = response_get_actions
        result = servers_client.get_actions_list(server)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions", method="GET", params={})

        actions = result.actions
        assert result.meta is None

        assert len(actions) == 1
        assert isinstance(actions[0], BoundAction)

        assert actions[0]._client == servers_client._client.actions
        assert actions[0].id == 13
        assert actions[0].command == "start_server"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_update(self, servers_client, server, response_update_server):
        servers_client._client.request.return_value = response_update_server
        server = servers_client.update(server, name="new-name", labels={})
        servers_client._client.request.assert_called_with(url="/servers/1",
                                                          method="PUT",
                                                          json={
                                                              "name":
                                                              "new-name",
                                                              "labels": {}
                                                          })

        assert server.id == 14
        assert server.name == "new-name"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_delete(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.delete(server)
        servers_client._client.request.assert_called_with(url="/servers/1",
                                                          method="DELETE")

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_power_off(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.power_off(server)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/poweroff", method="POST")

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_power_on(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.power_on(server)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/poweron", method="POST")

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_reboot(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.reboot(server)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/reboot", method="POST")

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_reset(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.reset(server)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/reset", method="POST")

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_shutdown(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.shutdown(server)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/shutdown", method="POST")

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_reset_password(self, servers_client, server,
                            response_server_reset_password):
        servers_client._client.request.return_value = response_server_reset_password
        response = servers_client.reset_password(server)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/reset_password", method="POST")

        assert response.action.id == 1
        assert response.action.progress == 0
        assert response.root_password == "YItygq1v3GYjjMomLaKc"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_change_type_with_server_type_name(self, servers_client, server,
                                               generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.change_type(server,
                                            ServerType(name="cx11"),
                                            upgrade_disk=True)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/change_type",
            method="POST",
            json={
                "server_type": "cx11",
                "upgrade_disk": True
            })

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_change_type_with_server_type_id(self, servers_client, server,
                                             generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.change_type(server,
                                            ServerType(id=1),
                                            upgrade_disk=True)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/change_type",
            method="POST",
            json={
                "server_type": 1,
                "upgrade_disk": True
            })

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_change_type_with_blank_server_type(self, servers_client, server):
        with pytest.raises(ValueError) as e:
            servers_client.change_type(server, ServerType(), upgrade_disk=True)
        assert str(e.value) == "id or name must be set"
        servers_client._client.request.assert_not_called()

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_enable_rescue(self, servers_client, server,
                           response_server_enable_rescue):
        servers_client._client.request.return_value = response_server_enable_rescue
        response = servers_client.enable_rescue(server, "linux64", [2323])
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/enable_rescue",
            method="POST",
            json={
                "type": "linux64",
                "ssh_keys": [2323]
            })

        assert response.action.id == 1
        assert response.action.progress == 0
        assert response.root_password == "YItygq1v3GYjjMomLaKc"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_disable_rescue(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.disable_rescue(server)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/disable_rescue", method="POST")

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_create_image(self, servers_client, server,
                          response_server_create_image):
        servers_client._client.request.return_value = response_server_create_image
        response = servers_client.create_image(server,
                                               description="my image",
                                               type="snapshot",
                                               labels={"key": "value"})
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/create_image",
            method="POST",
            json={
                "description": "my image",
                "type": "snapshot",
                "labels": {
                    "key": "value"
                }
            })

        assert response.action.id == 1
        assert response.action.progress == 0
        assert response.image.description == "my image"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_rebuild(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.rebuild(server, Image(name="ubuntu-20.04"))
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/rebuild",
            method="POST",
            json={"image": "ubuntu-20.04"})

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_enable_backup(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.enable_backup(server)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/enable_backup", method="POST")

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_disable_backup(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.disable_backup(server)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/disable_backup", method="POST")

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_attach_iso(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.attach_iso(
            server, Iso(name="FreeBSD-11.0-RELEASE-amd64-dvd1"))
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/attach_iso",
            method="POST",
            json={"iso": "FreeBSD-11.0-RELEASE-amd64-dvd1"})

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_detach_iso(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.detach_iso(server)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/detach_iso", method="POST")

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_change_dns_ptr(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.change_dns_ptr(server, "1.2.3.4",
                                               "example.com")
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/change_dns_ptr",
            method="POST",
            json={
                "ip": "1.2.3.4",
                "dns_ptr": "example.com"
            })

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_change_protection(self, servers_client, server, generic_action):
        servers_client._client.request.return_value = generic_action
        action = servers_client.change_protection(server, True, True)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/change_protection",
            method="POST",
            json={
                "delete": True,
                "rebuild": True
            })

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_request_console(self, servers_client, server,
                             response_server_request_console):
        servers_client._client.request.return_value = response_server_request_console
        response = servers_client.request_console(server)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/request_console", method="POST")

        assert response.action.id == 1
        assert response.action.progress == 0
        assert response.wss_url == "wss://console.hetzner.cloud/?server_id=1&token=3db32d15-af2f-459c-8bf8-dee1fd05f49c"
        assert response.password == "9MQaTg2VAGI0FIpc10k3UpRXcHj2wQ6x"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    @pytest.mark.parametrize(
        "network",
        [Network(id=4711),
         BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_attach_to_network(self, servers_client, server, network,
                               response_attach_to_network):
        servers_client._client.request.return_value = response_attach_to_network
        action = servers_client.attach_to_network(server, network, "10.0.1.1",
                                                  ["10.0.1.2", "10.0.1.3"])
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/attach_to_network",
            method="POST",
            json={
                "network": 4711,
                "ip": "10.0.1.1",
                "alias_ips": ["10.0.1.2", "10.0.1.3"]
            })

        assert action.id == 1
        assert action.progress == 0
        assert action.command == "attach_to_network"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    @pytest.mark.parametrize(
        "network",
        [Network(id=4711),
         BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_detach_from_network(self, servers_client, server, network,
                                 response_detach_from_network):
        servers_client._client.request.return_value = response_detach_from_network
        action = servers_client.detach_from_network(server, network)
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/detach_from_network",
            method="POST",
            json={"network": 4711})

        assert action.id == 1
        assert action.progress == 0
        assert action.command == "detach_from_network"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    @pytest.mark.parametrize(
        "network",
        [Network(id=4711),
         BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_change_alias_ips(self, servers_client, server, network,
                              response_change_alias_ips):
        servers_client._client.request.return_value = response_change_alias_ips
        action = servers_client.change_alias_ips(server, network,
                                                 ["10.0.1.2", "10.0.1.3"])
        servers_client._client.request.assert_called_with(
            url="/servers/1/actions/change_alias_ips",
            method="POST",
            json={
                "network": 4711,
                "alias_ips": ["10.0.1.2", "10.0.1.3"]
            })

        assert action.id == 1
        assert action.progress == 0
        assert action.command == "change_alias_ips"
예제 #8
0
class TestBoundServer(object):
    @pytest.fixture()
    def bound_server(self, hetzner_client):
        return BoundServer(client=hetzner_client.servers, data=dict(id=14))

    def test_bound_server_init(self, response_full_server):
        bound_server = BoundServer(client=mock.MagicMock(),
                                   data=response_full_server['server'])

        assert bound_server.id == 42
        assert bound_server.name == "my-server"
        assert isinstance(bound_server.public_net, PublicNetwork)
        assert isinstance(bound_server.public_net.ipv4, IPv4Address)
        assert bound_server.public_net.ipv4.ip == "1.2.3.4"
        assert bound_server.public_net.ipv4.blocked is False
        assert bound_server.public_net.ipv4.dns_ptr == "server01.example.com"

        assert isinstance(bound_server.public_net.ipv6, IPv6Network)
        assert bound_server.public_net.ipv6.ip == "2001:db8::/64"
        assert bound_server.public_net.ipv6.blocked is False
        assert bound_server.public_net.ipv6.network == "2001:db8::"
        assert bound_server.public_net.ipv6.network_mask == "64"

        assert isinstance(bound_server.public_net.floating_ips[0],
                          BoundFloatingIP)
        assert bound_server.public_net.floating_ips[0].id == 478
        assert bound_server.public_net.floating_ips[0].complete is False

        assert isinstance(bound_server.datacenter, BoundDatacenter)
        assert bound_server.datacenter._client == bound_server._client._client.datacenters
        assert bound_server.datacenter.id == 1
        assert bound_server.datacenter.complete is True

        assert isinstance(bound_server.server_type, BoundServerType)
        assert bound_server.server_type._client == bound_server._client._client.server_types
        assert bound_server.server_type.id == 1
        assert bound_server.server_type.complete is True

        assert len(bound_server.volumes) == 2
        assert isinstance(bound_server.volumes[0], BoundVolume)
        assert bound_server.volumes[
            0]._client == bound_server._client._client.volumes
        assert bound_server.volumes[0].id == 1
        assert bound_server.volumes[0].complete is False

        assert isinstance(bound_server.volumes[1], BoundVolume)
        assert bound_server.volumes[
            1]._client == bound_server._client._client.volumes
        assert bound_server.volumes[1].id == 2
        assert bound_server.volumes[1].complete is False

        assert isinstance(bound_server.image, BoundImage)
        assert bound_server.image._client == bound_server._client._client.images
        assert bound_server.image.id == 4711
        assert bound_server.image.name == "ubuntu-20.04"
        assert bound_server.image.complete is True

        assert isinstance(bound_server.iso, BoundIso)
        assert bound_server.iso._client == bound_server._client._client.isos
        assert bound_server.iso.id == 4711
        assert bound_server.iso.name == "FreeBSD-11.0-RELEASE-amd64-dvd1"
        assert bound_server.iso.complete is True

        assert len(bound_server.private_net) == 1
        assert isinstance(bound_server.private_net[0], PrivateNet)
        assert bound_server.private_net[
            0].network._client == bound_server._client._client.networks
        assert bound_server.private_net[0].ip == "10.1.1.5"
        assert bound_server.private_net[0].mac_address == "86:00:ff:2a:7d:e1"
        assert len(bound_server.private_net[0].alias_ips) == 1
        assert bound_server.private_net[0].alias_ips[0] == "10.1.1.8"

    @pytest.mark.parametrize("params", [{
        "status": [Server.STATUS_RUNNING],
        "sort": "status",
        "page": 1,
        "per_page": 10
    }, {}])
    def test_get_actions_list(self, hetzner_client, bound_server,
                              response_get_actions, params):
        hetzner_client.request.return_value = response_get_actions
        result = bound_server.get_actions_list(**params)
        hetzner_client.request.assert_called_with(url="/servers/14/actions",
                                                  method="GET",
                                                  params=params)

        actions = result.actions
        assert result.meta is None

        assert len(actions) == 1
        assert isinstance(actions[0], BoundAction)
        assert actions[0].id == 13
        assert actions[0].command == "start_server"

    @pytest.mark.parametrize("params", [{
        "status": [Server.STATUS_RUNNING],
        "sort": "status"
    }, {}])
    def test_get_actions(self, hetzner_client, bound_server,
                         response_get_actions, params):
        hetzner_client.request.return_value = response_get_actions
        actions = bound_server.get_actions(**params)

        params.update({'page': 1, 'per_page': 50})

        hetzner_client.request.assert_called_with(url="/servers/14/actions",
                                                  method="GET",
                                                  params=params)

        assert len(actions) == 1
        assert isinstance(actions[0], BoundAction)
        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
        server = bound_server.update(name="new-name", labels={})
        hetzner_client.request.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
        action = bound_server.delete()
        hetzner_client.request.assert_called_with(url="/servers/14",
                                                  method="DELETE")

        assert action.id == 1
        assert action.progress == 0

    def test_power_off(self, hetzner_client, bound_server, generic_action):
        hetzner_client.request.return_value = generic_action
        action = bound_server.power_off()
        hetzner_client.request.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
        action = bound_server.power_on()
        hetzner_client.request.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
        action = bound_server.reboot()
        hetzner_client.request.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
        action = bound_server.reset()
        hetzner_client.request.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
        action = bound_server.shutdown()
        hetzner_client.request.assert_called_with(
            url="/servers/14/actions/shutdown", method="POST")

        assert action.id == 1
        assert action.progress == 0

    def test_reset_password(self, hetzner_client, bound_server,
                            response_server_reset_password):
        hetzner_client.request.return_value = response_server_reset_password
        response = bound_server.reset_password()
        hetzner_client.request.assert_called_with(
            url="/servers/14/actions/reset_password", method="POST")

        assert response.action.id == 1
        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
        action = bound_server.change_type(ServerType(name="cx11"),
                                          upgrade_disk=True)
        hetzner_client.request.assert_called_with(
            url="/servers/14/actions/change_type",
            method="POST",
            json={
                "server_type": "cx11",
                "upgrade_disk": True
            })

        assert action.id == 1
        assert action.progress == 0

    def test_enable_rescue(self, hetzner_client, bound_server,
                           response_server_enable_rescue):
        hetzner_client.request.return_value = response_server_enable_rescue
        response = bound_server.enable_rescue(type="linux64")
        hetzner_client.request.assert_called_with(
            url="/servers/14/actions/enable_rescue",
            method="POST",
            json={"type": "linux64"})

        assert response.action.id == 1
        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
        action = bound_server.disable_rescue()
        hetzner_client.request.assert_called_with(
            url="/servers/14/actions/disable_rescue", method="POST")

        assert action.id == 1
        assert action.progress == 0

    def test_create_image(self, hetzner_client, bound_server,
                          response_server_create_image):
        hetzner_client.request.return_value = response_server_create_image
        response = bound_server.create_image(description="my image",
                                             type="snapshot")
        hetzner_client.request.assert_called_with(
            url="/servers/14/actions/create_image",
            method="POST",
            json={
                "description": "my image",
                "type": "snapshot"
            })

        assert response.action.id == 1
        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
        action = bound_server.rebuild(Image(name="ubuntu-20.04"))
        hetzner_client.request.assert_called_with(
            url="/servers/14/actions/rebuild",
            method="POST",
            json={"image": "ubuntu-20.04"})

        assert action.id == 1
        assert action.progress == 0

    def test_enable_backup(self, hetzner_client, bound_server, generic_action):
        hetzner_client.request.return_value = generic_action
        action = bound_server.enable_backup()
        hetzner_client.request.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
        action = bound_server.disable_backup()
        hetzner_client.request.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
        action = bound_server.attach_iso(
            Iso(name="FreeBSD-11.0-RELEASE-amd64-dvd1"))
        hetzner_client.request.assert_called_with(
            url="/servers/14/actions/attach_iso",
            method="POST",
            json={"iso": "FreeBSD-11.0-RELEASE-amd64-dvd1"})

        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
        action = bound_server.detach_iso()
        hetzner_client.request.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
        action = bound_server.change_dns_ptr("1.2.3.4", "example.com")
        hetzner_client.request.assert_called_with(
            url="/servers/14/actions/change_dns_ptr",
            method="POST",
            json={
                "ip": "1.2.3.4",
                "dns_ptr": "example.com"
            })

        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
        action = bound_server.change_protection(True, True)
        hetzner_client.request.assert_called_with(
            url="/servers/14/actions/change_protection",
            method="POST",
            json={
                "delete": True,
                "rebuild": True
            })

        assert action.id == 1
        assert action.progress == 0

    def test_request_console(self, hetzner_client, bound_server,
                             response_server_request_console):
        hetzner_client.request.return_value = response_server_request_console
        response = bound_server.request_console()
        hetzner_client.request.assert_called_with(
            url="/servers/14/actions/request_console", method="POST")

        assert response.action.id == 1
        assert response.action.progress == 0
        assert response.wss_url == "wss://console.hetzner.cloud/?server_id=1&token=3db32d15-af2f-459c-8bf8-dee1fd05f49c"
        assert response.password == "9MQaTg2VAGI0FIpc10k3UpRXcHj2wQ6x"

    @pytest.mark.parametrize(
        "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):
        hetzner_client.request.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(
            url="/servers/14/actions/attach_to_network",
            method="POST",
            json={
                "network": 4711,
                "ip": "10.0.1.1",
                "alias_ips": ["10.0.1.2", "10.0.1.3"]
            })

        assert action.id == 1
        assert action.progress == 0
        assert action.command == "attach_to_network"

    @pytest.mark.parametrize(
        "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):
        hetzner_client.request.return_value = response_detach_from_network
        action = bound_server.detach_from_network(network)
        hetzner_client.request.assert_called_with(
            url="/servers/14/actions/detach_from_network",
            method="POST",
            json={"network": 4711})

        assert action.id == 1
        assert action.progress == 0
        assert action.command == "detach_from_network"

    @pytest.mark.parametrize(
        "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):
        hetzner_client.request.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(
            url="/servers/14/actions/change_alias_ips",
            method="POST",
            json={
                "network": 4711,
                "alias_ips": ["10.0.1.2", "10.0.1.3"]
            })

        assert action.id == 1
        assert action.progress == 0
        assert action.command == "change_alias_ips"
예제 #9
0
class TestNetworksClient(object):

    @pytest.fixture()
    def network_subnet(self):
        return NetworkSubnet(type="server", ip_range="10.0.1.0/24", network_zone="eu-central")

    @pytest.fixture()
    def network_route(self):
        return NetworkRoute(destination="10.100.1.0/24", gateway="10.0.1.1")

    def test_get_by_id(self, hetzner_client):
        network = hetzner_client.networks.get_by_id(4711)
        assert network.id == 4711
        assert network.name == "mynet"
        assert network.ip_range == "10.0.0.0/16"
        assert len(network.subnets) == 1
        assert len(network.routes) == 1
        assert len(network.servers) == 1
        assert network.protection['delete'] is False

    def test_get_by_name(self, hetzner_client):
        network = hetzner_client.networks.get_by_name("mynet")
        assert network.id == 4711
        assert network.name == "mynet"
        assert network.ip_range == "10.0.0.0/16"
        assert len(network.subnets) == 1
        assert len(network.routes) == 1
        assert len(network.servers) == 1
        assert network.protection['delete'] is False

    def test_get_list(self, hetzner_client):
        result = hetzner_client.networks.get_list()
        networks = result.networks
        assert networks[0].id == 4711
        assert networks[0].name == "mynet"
        assert networks[0].ip_range == "10.0.0.0/16"
        assert len(networks[0].subnets) == 1
        assert len(networks[0].routes) == 1
        assert len(networks[0].servers) == 1
        assert networks[0].protection['delete'] is False

    def test_get_all(self, hetzner_client):
        networks = hetzner_client.networks.get_all()
        assert networks[0].id == 4711
        assert networks[0].name == "mynet"
        assert networks[0].ip_range == "10.0.0.0/16"
        assert len(networks[0].subnets) == 1
        assert len(networks[0].routes) == 1
        assert len(networks[0].servers) == 1
        assert networks[0].protection['delete'] is False

    def test_create(self, hetzner_client, network_subnet, network_route):
        network = hetzner_client.networks.create(name="mynet", ip_range="10.0.0.0/16", subnets=[network_subnet],
                                                 routes=[network_route])
        assert network.id == 4711
        assert network.name == "mynet"
        assert network.ip_range == "10.0.0.0/16"
        assert len(network.subnets) == 1
        assert len(network.routes) == 1
        assert len(network.servers) == 1
        assert network.protection['delete'] is False

    @pytest.mark.parametrize("network", [Network(id=4711), BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_get_actions_list(self, hetzner_client, network):
        result = hetzner_client.networks.get_actions_list(network)
        actions = result.actions

        assert len(actions) == 1
        assert actions[0].id == 13
        assert actions[0].command == "add_subnet"

    @pytest.mark.parametrize("network", [Network(id=4711), BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_update(self, hetzner_client, network):
        network = hetzner_client.networks.update(network, name="new-name", labels={})

        assert network.id == 4711
        assert network.name == "new-name"

    @pytest.mark.parametrize("network", [Network(id=4711), BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_delete(self, hetzner_client, network):
        result = hetzner_client.networks.delete(network)

        assert result is True

    @pytest.mark.parametrize("network", [Network(id=4711), BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_change_protection(self, hetzner_client, network):
        action = hetzner_client.networks.change_protection(network, delete=True)

        assert action.id == 13
        assert action.command == "change_protection"

    @pytest.mark.parametrize("network", [Network(id=4711), BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_add_subnet(self, hetzner_client, network, network_subnet):
        action = hetzner_client.networks.add_subnet(network, network_subnet)

        assert action.id == 13
        assert action.command == "add_subnet"

    @pytest.mark.parametrize("network", [Network(id=4711), BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_delete_subnet(self, hetzner_client, network, network_subnet):
        action = hetzner_client.networks.delete_subnet(network, network_subnet)

        assert action.id == 13
        assert action.command == "delete_subnet"

    @pytest.mark.parametrize("network", [Network(id=4711), BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_add_route(self, hetzner_client, network, network_route):
        action = hetzner_client.networks.add_route(network, network_route)

        assert action.id == 13
        assert action.command == "add_route"

    @pytest.mark.parametrize("network", [Network(id=4711), BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_delete_route(self, hetzner_client, network, network_route):
        action = hetzner_client.networks.delete_route(network, network_route)

        assert action.id == 13
        assert action.command == "delete_route"

    @pytest.mark.parametrize("network", [Network(id=4711), BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_change_ip_range(self, hetzner_client, network):
        action = hetzner_client.networks.change_ip_range(network, "10.0.0.0/12")

        assert action.id == 13
        assert action.command == "change_ip_range"
예제 #10
0
class TestServersClient(object):
    def test_get_by_id(self, hetzner_client):
        server = hetzner_client.servers.get_by_id(42)
        assert server.id == 42
        assert server.volumes == []
        assert server.server_type.id == 1
        assert server.datacenter.id == 1
        assert server.image.id == 4711

    def test_get_by_name(self, hetzner_client):
        server = hetzner_client.servers.get_by_name("my-server")
        assert server.id == 42
        assert server.name == "my-server"
        assert server.volumes == []
        assert server.server_type.id == 1
        assert server.datacenter.id == 1
        assert server.image.id == 4711

    def test_get_list(self, hetzner_client):
        result = hetzner_client.servers.get_list()
        servers = result.servers
        assert servers[0].id == 42
        assert servers[0].volumes == []
        assert servers[0].server_type.id == 1
        assert servers[0].datacenter.id == 1
        assert servers[0].image.id == 4711

    def test_create(self, hetzner_client):
        response = hetzner_client.servers.create(
            "my-server",
            server_type=ServerType(name="cx11"),
            image=Image(name="ubuntu-16.04"),
            ssh_keys=[SSHKey(name="my-ssh-key")],
            volumes=[Volume(id=1)],
            user_data=
            "#cloud-config\\nruncmd:\\n- [touch, /root/cloud-init-worked]\\n",
            location=Location(name="nbg1"),
            automount=False)
        server = response.server
        action = response.action
        next_actions = response.next_actions
        root_password = response.root_password

        assert server.id == 42
        assert server.volumes == []
        assert server.server_type.id == 1
        assert server.datacenter.id == 1
        assert server.image.id == 4711

        assert action.id == 1
        assert action.command == "create_server"

        assert len(next_actions) == 1
        assert next_actions[0].id == 13
        assert next_actions[0].command == "start_server"

        assert root_password == "YItygq1v3GYjjMomLaKc"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_get_actions_list(self, hetzner_client, server):
        result = hetzner_client.servers.get_actions_list(server)
        actions = result.actions

        assert len(actions) == 1
        assert actions[0].id == 13
        assert actions[0].command == "start_server"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_update(self, hetzner_client, server):
        server = hetzner_client.servers.update(server,
                                               name="new-name",
                                               labels={})

        assert server.id == 42
        assert server.name == "new-name"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_delete(self, hetzner_client, server):
        action = hetzner_client.servers.delete(server)

        assert action.id == 13
        assert action.command == "delete_server"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_power_off(self, hetzner_client, server):
        action = hetzner_client.servers.power_off(server)

        assert action.id == 13
        assert action.command == "stop_server"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_power_on(self, hetzner_client, server):
        action = hetzner_client.servers.power_on(server)

        assert action.id == 13
        assert action.command == "start_server"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_reboot(self, hetzner_client, server):
        action = hetzner_client.servers.reboot(server)

        assert action.id == 13
        assert action.command == "reboot_server"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_reset(self, hetzner_client, server):
        action = hetzner_client.servers.reset(server)

        assert action.id == 13
        assert action.command == "reset_server"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_shutdown(self, hetzner_client, server):
        action = hetzner_client.servers.shutdown(server)

        assert action.id == 13
        assert action.command == "shutdown_server"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_reset_password(self, hetzner_client, server):
        response = hetzner_client.servers.reset_password(server)

        assert response.action.id == 13
        assert response.action.command == "reset_password"
        assert response.root_password == "zCWbFhnu950dUTko5f40"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_change_type(self, hetzner_client, server):
        action = hetzner_client.servers.change_type(server,
                                                    ServerType(name="cx11"),
                                                    upgrade_disk=True)

        assert action.id == 13
        assert action.command == "change_server_type"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_enable_rescue(self, hetzner_client, server):
        response = hetzner_client.servers.enable_rescue(server,
                                                        type="linux64",
                                                        ssh_keys=[2323])

        assert response.action.id == 13
        assert response.action.command == "enable_rescue"
        assert response.root_password == "zCWbFhnu950dUTko5f40"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_disable_rescue(self, hetzner_client, server):
        action = hetzner_client.servers.disable_rescue(server)

        assert action.id == 13
        assert action.command == "disable_rescue"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_create_image(self, hetzner_client, server):
        response = hetzner_client.servers.create_image(server,
                                                       description="my image",
                                                       type="snapshot")

        assert response.action.id == 13
        assert response.action.command == "create_image"
        assert response.image.description == "my image"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_rebuild(self, hetzner_client, server):
        action = hetzner_client.servers.rebuild(server,
                                                Image(name="ubuntu-16.04"))

        assert action.id == 13
        assert action.command == "rebuild_server"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_enable_backup(self, hetzner_client, server):
        action = hetzner_client.servers.enable_backup(server)

        assert action.id == 13
        assert action.command == "enable_backup"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_disable_backup(self, hetzner_client, server):
        action = hetzner_client.servers.disable_backup(server)

        assert action.id == 13
        assert action.command == "disable_backup"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_attach_iso(self, hetzner_client, server):
        action = hetzner_client.servers.attach_iso(
            server, Iso(name="FreeBSD-11.0-RELEASE-amd64-dvd1"))

        assert action.id == 13
        assert action.command == "attach_iso"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_detach_iso(self, hetzner_client, server):
        action = hetzner_client.servers.detach_iso(server)

        assert action.id == 13
        assert action.command == "detach_iso"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_change_dns_ptr(self, hetzner_client, server):
        action = hetzner_client.servers.change_dns_ptr(server, "1.2.3.4",
                                                       "example.com")

        assert action.id == 13
        assert action.command == "change_dns_ptr"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_change_protection(self, hetzner_client, server):
        action = hetzner_client.servers.change_protection(server,
                                                          delete=True,
                                                          rebuild=True)

        assert action.id == 13
        assert action.command == "change_protection"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    def test_request_console(self, hetzner_client, server):
        response = hetzner_client.servers.request_console(server)

        assert response.action.id == 13
        assert response.action.command == "request_console"
        assert response.wss_url == "wss://console.hetzner.cloud/?server_id=1&token=3db32d15-af2f-459c-8bf8-dee1fd05f49c"
        assert response.password == "9MQaTg2VAGI0FIpc10k3UpRXcHj2wQ6x"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    @pytest.mark.parametrize(
        "network",
        [Network(id=4711),
         BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_attach_to_network(self, hetzner_client, server, network):
        action = hetzner_client.servers.attach_to_network(
            server, network, ip="10.0.1.1", alias_ips=["10.0.1.2"])

        assert action.id == 13
        assert action.command == "attach_to_network"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    @pytest.mark.parametrize(
        "network",
        [Network(id=4711),
         BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_detach_from_network(self, hetzner_client, server, network):
        action = hetzner_client.servers.detach_from_network(server, network)

        assert action.id == 13
        assert action.command == "detach_from_network"

    @pytest.mark.parametrize(
        "server",
        [Server(id=1), BoundServer(mock.MagicMock(), dict(id=1))])
    @pytest.mark.parametrize(
        "network",
        [Network(id=4711),
         BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_change_alias_ips(self, hetzner_client, server, network):
        action = hetzner_client.servers.change_alias_ips(
            server, network, alias_ips=["10.0.1.2"])

        assert action.id == 13
        assert action.command == "change_alias_ips"
예제 #11
0
class TestBoundServer(object):
    @pytest.fixture()
    def bound_server(self, hetzner_client):
        return BoundServer(client=hetzner_client.servers, data=dict(id=42))

    def test_get_actions_list(self, bound_server):
        result = bound_server.get_actions_list()
        actions = result.actions

        assert len(actions) == 1
        assert actions[0].id == 13
        assert actions[0].command == "start_server"

    def test_update(self, bound_server):
        server = bound_server.update(name="new-name", labels={})
        assert server.id == 42
        assert server.name == "new-name"

    def test_delete(self, bound_server):
        action = bound_server.delete()
        assert action.id == 13
        assert action.command == "delete_server"

    def test_power_off(self, bound_server):
        action = bound_server.power_off()
        assert action.id == 13
        assert action.command == "stop_server"

    def test_power_on(self, bound_server):
        action = bound_server.power_on()

        assert action.id == 13
        assert action.command == "start_server"

    def test_reboot(self, bound_server):
        action = bound_server.reboot()

        assert action.id == 13
        assert action.command == "reboot_server"

    def test_reset(self, bound_server):
        action = bound_server.reset()

        assert action.id == 13
        assert action.command == "reset_server"

    def test_reset_password(self, bound_server):
        response = bound_server.reset_password()

        assert response.action.id == 13
        assert response.action.command == "reset_password"
        assert response.root_password == "zCWbFhnu950dUTko5f40"

    def test_change_type(self, bound_server):
        action = bound_server.change_type(ServerType(name="cx11"),
                                          upgrade_disk=True)
        assert action.id == 13
        assert action.command == "change_server_type"

    def test_enable_rescue(self, bound_server):
        response = bound_server.enable_rescue(type="linux64", ssh_keys=[2323])

        assert response.action.id == 13
        assert response.action.command == "enable_rescue"
        assert response.root_password == "zCWbFhnu950dUTko5f40"

    def test_disable_rescue(self, bound_server):
        action = bound_server.disable_rescue()

        assert action.id == 13
        assert action.command == "disable_rescue"

    def test_create_image(self, bound_server):
        response = bound_server.create_image(description="my image",
                                             type="snapshot")

        assert response.action.id == 13
        assert response.action.command == "create_image"
        assert response.image.description == "my image"

    def test_rebuild(self, bound_server):
        action = bound_server.rebuild(Image(name="ubuntu-16.04"))

        assert action.id == 13
        assert action.command == "rebuild_server"

    def test_enable_backup(self, bound_server):
        action = bound_server.enable_backup()

        assert action.id == 13
        assert action.command == "enable_backup"

    def test_disable_backup(self, bound_server):
        action = bound_server.disable_backup()

        assert action.id == 13
        assert action.command == "disable_backup"

    def test_attach_iso(self, bound_server):
        action = bound_server.attach_iso(
            Iso(name="FreeBSD-11.0-RELEASE-amd64-dvd1"))

        assert action.id == 13
        assert action.command == "attach_iso"

    def test_detach_iso(self, bound_server):
        action = bound_server.detach_iso()

        assert action.id == 13
        assert action.command == "detach_iso"

    def test_change_dns_ptr(self, bound_server):
        action = bound_server.change_dns_ptr(ip="1.2.3.4",
                                             dns_ptr="example.com")

        assert action.id == 13
        assert action.command == "change_dns_ptr"

    def test_change_protection(self, bound_server):
        action = bound_server.change_protection(True, True)

        assert action.id == 13
        assert action.command == "change_protection"

    def test_request_console(self, bound_server):
        response = bound_server.request_console()

        assert response.action.id == 13
        assert response.action.command == "request_console"
        assert response.wss_url == "wss://console.hetzner.cloud/?server_id=1&token=3db32d15-af2f-459c-8bf8-dee1fd05f49c"
        assert response.password == "9MQaTg2VAGI0FIpc10k3UpRXcHj2wQ6x"

    @pytest.mark.parametrize(
        "network",
        [Network(id=4711),
         BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_attach_to_network(self, bound_server, network):
        action = bound_server.attach_to_network(network,
                                                ip="10.0.1.1",
                                                alias_ips=["10.0.1.2"])

        assert action.id == 13
        assert action.command == "attach_to_network"

    @pytest.mark.parametrize(
        "network",
        [Network(id=4711),
         BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_detach_from_network(self, bound_server, network):
        action = bound_server.detach_from_network(network)

        assert action.id == 13
        assert action.command == "detach_from_network"

    @pytest.mark.parametrize(
        "network",
        [Network(id=4711),
         BoundNetwork(mock.MagicMock(), dict(id=4711))])
    def test_change_alias_ips(self, bound_server, network):
        action = bound_server.change_alias_ips(network, alias_ips=["10.0.1.2"])

        assert action.id == 13
        assert action.command == "change_alias_ips"
예제 #12
0
class TestNetworksClient(object):

    @pytest.fixture()
    def networks_client(self):
        return NetworksClient(client=mock.MagicMock())

    @pytest.fixture()
    def network_subnet(self):
        return NetworkSubnet(type="cloud", ip_range="10.0.1.0/24", network_zone="eu-central")

    @pytest.fixture()
    def network_route(self):
        return NetworkRoute(destination="10.100.1.0/24", gateway="10.0.1.1")

    def test_get_by_id(self, networks_client, network_response):
        networks_client._client.request.return_value = network_response
        bound_network = networks_client.get_by_id(1)
        networks_client._client.request.assert_called_with(url="/networks/1", method="GET")
        assert bound_network._client is networks_client
        assert bound_network.id == 1
        assert bound_network.name == "mynet"

    @pytest.mark.parametrize(
        "params",
        [
            {'label_selector': "label1", 'page': 1, 'per_page': 10},
            {}
        ]
    )
    def test_get_list(self, networks_client, two_networks_response, params):
        networks_client._client.request.return_value = two_networks_response
        result = networks_client.get_list(**params)
        networks_client._client.request.assert_called_with(url="/networks", method="GET", params=params)

        bound_networks = result.networks
        assert result.meta is None

        assert len(bound_networks) == 2

        bound_network1 = bound_networks[0]
        bound_network2 = bound_networks[1]

        assert bound_network1._client is networks_client
        assert bound_network1.id == 1
        assert bound_network1.name == "mynet"

        assert bound_network2._client is networks_client
        assert bound_network2.id == 2
        assert bound_network2.name == "myanothernet"

    @pytest.mark.parametrize("params", [{'label_selector': "label1"}])
    def test_get_all(self, networks_client, two_networks_response, params):
        networks_client._client.request.return_value = two_networks_response
        bound_networks = networks_client.get_all(**params)

        params.update({'page': 1, 'per_page': 50})

        networks_client._client.request.assert_called_with(url="/networks", method="GET", params=params)

        assert len(bound_networks) == 2

        bound_network1 = bound_networks[0]
        bound_network2 = bound_networks[1]

        assert bound_network1._client is networks_client
        assert bound_network1.id == 1
        assert bound_network1.name == "mynet"

        assert bound_network2._client is networks_client
        assert bound_network2.id == 2
        assert bound_network2.name == "myanothernet"

    def test_get_by_name(self, networks_client, one_network_response):
        networks_client._client.request.return_value = one_network_response
        bound_network = networks_client.get_by_name("mynet")

        params = {'name': "mynet"}

        networks_client._client.request.assert_called_with(url="/networks", method="GET", params=params)

        assert bound_network._client is networks_client
        assert bound_network.id == 1
        assert bound_network.name == "mynet"

    def test_create(self, networks_client, network_create_response):
        networks_client._client.request.return_value = network_create_response
        networks_client.create(
            name="mynet",
            ip_range="10.0.0.0/8"
        )
        networks_client._client.request.assert_called_with(
            url="/networks",
            method="POST",
            json={
                'name': "mynet",
                'ip_range': "10.0.0.0/8",
            }
        )

    def test_create_with_subnet(self, networks_client, network_subnet, network_create_response):
        networks_client._client.request.return_value = network_create_response
        networks_client.create(
            name="mynet",
            ip_range="10.0.0.0/8",
            subnets=[network_subnet]
        )
        networks_client._client.request.assert_called_with(
            url="/networks",
            method="POST",
            json={
                'name': "mynet",
                'ip_range': "10.0.0.0/8",
                'subnets': [
                    {
                        'type': "cloud",
                        'ip_range': "10.0.1.0/24",
                        'network_zone': "eu-central"
                    }
                ]
            }
        )

    def test_create_with_route(self, networks_client, network_route, network_create_response):
        networks_client._client.request.return_value = network_create_response
        networks_client.create(
            name="mynet",
            ip_range="10.0.0.0/8",
            routes=[network_route]
        )
        networks_client._client.request.assert_called_with(
            url="/networks",
            method="POST",
            json={
                'name': "mynet",
                'ip_range': "10.0.0.0/8",
                'routes': [
                    {
                        'destination': "10.100.1.0/24",
                        'gateway': "10.0.1.1",
                    }
                ]
            }
        )

    def test_create_with_route_and_subnet(self, networks_client, network_subnet, network_route,
                                          network_create_response):
        networks_client._client.request.return_value = network_create_response
        networks_client.create(
            name="mynet",
            ip_range="10.0.0.0/8",
            subnets=[network_subnet],
            routes=[network_route]
        )
        networks_client._client.request.assert_called_with(
            url="/networks",
            method="POST",
            json={
                'name': "mynet",
                'ip_range': "10.0.0.0/8",
                'subnets': [
                    {
                        'type': "cloud",
                        'ip_range': "10.0.1.0/24",
                        'network_zone': "eu-central"
                    }
                ],
                'routes': [
                    {
                        'destination': "10.100.1.0/24",
                        'gateway': "10.0.1.1",
                    }
                ]
            }
        )

    @pytest.mark.parametrize("network", [Network(id=1), BoundNetwork(mock.MagicMock(), dict(id=1))])
    def test_get_actions_list(self, networks_client, network, response_get_actions):
        networks_client._client.request.return_value = response_get_actions
        result = networks_client.get_actions_list(network, sort="id")
        networks_client._client.request.assert_called_with(url="/networks/1/actions", method="GET",
                                                           params={"sort": "id"})

        actions = result.actions
        assert len(actions) == 1
        assert isinstance(actions[0], BoundAction)

        assert actions[0]._client == networks_client._client.actions
        assert actions[0].id == 13
        assert actions[0].command == "add_subnet"

    @pytest.mark.parametrize("network", [Network(id=1), BoundNetwork(mock.MagicMock(), dict(id=1))])
    def test_update(self, networks_client, network, response_update_network):
        networks_client._client.request.return_value = response_update_network
        network = networks_client.update(network, name="new-name")
        networks_client._client.request.assert_called_with(url="/networks/1", method="PUT", json={"name": "new-name"})

        assert network.id == 4711
        assert network.name == "new-name"

    @pytest.mark.parametrize("network", [Network(id=1), BoundNetwork(mock.MagicMock(), dict(id=1))])
    def test_change_protection(self, networks_client, network, generic_action):
        networks_client._client.request.return_value = generic_action
        action = networks_client.change_protection(network, True)
        networks_client._client.request.assert_called_with(url="/networks/1/actions/change_protection", method="POST",
                                                           json={"delete": True})

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize("network", [Network(id=1), BoundNetwork(mock.MagicMock(), dict(id=1))])
    def test_delete(self, networks_client, network, generic_action):
        networks_client._client.request.return_value = generic_action
        delete_success = networks_client.delete(network)
        networks_client._client.request.assert_called_with(url="/networks/1", method="DELETE")

        assert delete_success is True

    @pytest.mark.parametrize("network", [Network(id=1), BoundNetwork(mock.MagicMock(), dict(id=1))])
    def test_add_subnet(self, networks_client, network, generic_action, network_subnet):
        networks_client._client.request.return_value = generic_action

        action = networks_client.add_subnet(network, network_subnet)
        networks_client._client.request.assert_called_with(url="/networks/1/actions/add_subnet", method="POST",
                                                           json={"type": "cloud", "ip_range": "10.0.1.0/24",
                                                                 "network_zone": "eu-central"})

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize("network", [Network(id=1), BoundNetwork(mock.MagicMock(), dict(id=1))])
    def test_delete_subnet(self, networks_client, network, generic_action, network_subnet):
        networks_client._client.request.return_value = generic_action

        action = networks_client.delete_subnet(network, network_subnet)
        networks_client._client.request.assert_called_with(url="/networks/1/actions/delete_subnet", method="POST",
                                                           json={"ip_range": "10.0.1.0/24"})

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize("network", [Network(id=1), BoundNetwork(mock.MagicMock(), dict(id=1))])
    def test_add_route(self, networks_client, network, generic_action, network_route):
        networks_client._client.request.return_value = generic_action

        action = networks_client.add_route(network, network_route)
        networks_client._client.request.assert_called_with(url="/networks/1/actions/add_route", method="POST",
                                                           json={"destination": "10.100.1.0/24", "gateway": "10.0.1.1"})

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize("network", [Network(id=1), BoundNetwork(mock.MagicMock(), dict(id=1))])
    def test_delete_route(self, networks_client, network, generic_action, network_route):
        networks_client._client.request.return_value = generic_action

        action = networks_client.delete_route(network, network_route)
        networks_client._client.request.assert_called_with(url="/networks/1/actions/delete_route", method="POST",
                                                           json={"destination": "10.100.1.0/24", "gateway": "10.0.1.1"})

        assert action.id == 1
        assert action.progress == 0

    @pytest.mark.parametrize("network", [Network(id=1), BoundNetwork(mock.MagicMock(), dict(id=1))])
    def test_change_ip_range(self, networks_client, network, generic_action):
        networks_client._client.request.return_value = generic_action
        action = networks_client.change_ip_range(network, "10.0.0.0/12")
        networks_client._client.request.assert_called_with(url="/networks/1/actions/change_ip_range", method="POST",
                                                           json={"ip_range": "10.0.0.0/12"})

        assert action.id == 1
        assert action.progress == 0
예제 #13
0
 def test_created_is_datetime(self):
     network = Network(id=1, created="2016-01-30T23:50+00:00")
     assert network.created == datetime.datetime(2016, 1, 30, 23, 50, tzinfo=tzoffset(None, 0))