8000 new: `get/put /_admin/server/mode` (#312) · arangodb/python-arango@70548d9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 70548d9

Browse files
authored
new: get/put /_admin/server/mode (#312)
* new: `mode()`, `server_mode()`, `set_mode()` * fix: test getting read-only errors even after running `sys_db.set_mode("default")`. Probably sync issues..
1 parent 6653c1b commit 70548d9

File tree

6 files changed

+129
-3
lines changed

6 files changed

+129
-3
lines changed

arango/cluster.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
ClusterServerCountError,
1212
ClusterServerEngineError,
1313
ClusterServerIDError,
14+
ClusterServerModeError,
1415
ClusterServerRoleError,
1516
ClusterServerStatisticsError,
1617
ClusterServerVersionError,
@@ -57,6 +58,27 @@ def response_handler(resp: Response) -> str:
5758

5859
return self._execute(request, response_handler)
5960

61+
def server_mode(self) -> Result[str]:
62+
"""Return the server mode.
63+
64+
In a read-only server, all write operations will fail
65+
with an error code of 1004 (ERROR_READ_ONLY). Creating or dropping
66+
databases and collections will also fail with error code 11 (ERROR_FORBIDDEN).
67+
68+
:return: Server mode. Possible values are "default" or "readonly".
69+
:rtype: str
70+
:raise arango.exceptions.ClusterServerModeError: If retrieval fails.
71+
"""
72+
request = Request(method="get", endpoint="/_admin/server/mode")
73+
74+
def response_handler(resp: Response) -> str:
75+
if resp.is_success:
76+
return str(resp.body["mode"])
77+
78+
raise ClusterServerModeError(resp, request)
79+
80+
return self._execute(request, response_handler)
81+
6082
def server_version(self, server_id: str) -> Result[Json]:
6183
"""Return the version of the given server.
6284

arango/database.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
ServerLogSettingError,
5353
ServerLogSettingSetError,
5454
ServerMetricsError,
55+
ServerModeError,
56+
ServerModeSetError,
5557
ServerReadLogError,
5658
ServerReloadRoutingError,
5759
ServerRequiredDBVersionError,
@@ -554,6 +556,56 @@ def response_handler(resp: Response) -> str:
554556

555557
return self._execute(request, response_handler)
556558

559+
def mode(self) -> Result[str]:
560+
"""Return the server mode (default or read-only)
561+
562+
In a read-only server, all write operations will fail
563+
with an error code of 1004 (ERROR_READ_ONLY). Creating or dropping
564+
databases and collections will also fail with error code 11 (ERROR_FORBIDDEN).
565+
566+
:return: Server mode. Possible values are "default" or "readonly".
567+
:rtype: str
568+
:raise arango.exceptions.ServerModeError: If retrieval fails.
569+
"""
570+
request = Request(method="get", endpoint="/_admin/server/mode")
571+
572+
def response_handler(resp: Response) -> str:
573+
if resp.is_success:
574+
return str(resp.body["mode"])
575+
576+
raise ServerModeError(resp, request)
577+
578+
return self._execute(request, response_handler)
579+
580+
def set_mode(self, mode: str) -> Result[Json]:
581+
"""Set the server mode to read-only or default.
582+
583+
Update mode information about a server. The JSON response will
584+
contain a field mode with the value readonly or default.
585+
In a read-only server all write operations will fail with an error
586+
code of 1004 (ERROR_READ_ONLY). Creating or dropping of databases
587+
and collections will also fail with error code 11 (ERROR_FORBIDDEN).
588+
589+
This is a protected API. It requires authentication and administrative
590+
server rights.
591+
592+
:param mode: Server mode. Possible values are "default" or "readonly".
593+
:type mode: str
594+
:return: Server mode.
595+
:rtype: str
596+
:raise arango.exceptions.ServerModeSetError: If set fails.
597+
"""
598+
request = Request(
599+
method="put", endpoint="/_admin/server/mode", data={"mode": mode}
600+
)
601+
602+
def response_handler(resp: Response) -> Json:
603+
if resp.is_success:
604+
return format_body(resp.body)
605+
raise ServerModeSetError(resp, request)
606+
607+
return self._execute(request, response_handler)
608+
557609
def time(self) -> Result[datetime]:
558610
"""Return server system time.
559611

arango/exceptions.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,15 @@ class ServerMetricsError(ArangoServerError):
695695

696696

697697
class ServerRoleError(ArangoServerError):
698-
"""Failed to retrieve server role in a cluster."""
698+
"""Failed to retrieve server role."""
699+
700+
701+
class ServerModeError(ArangoServerError):
702+
"""Failed to retrieve server mode."""
703+
704+
705+
class ServerModeSetError(ArangoServerError):
706+
"""Failed to set server mode."""
699707

700708

701709
class ServerTLSError(ArangoServerError):
@@ -980,7 +988,11 @@ class ClusterServerIDError(ArangoServerError):
980988

981989

982990
class ClusterServerRoleError(ArangoServerError):
983-
"""Failed to retrieve server role."""
991+
"""Failed to retrieve server role in a cluster."""
992+
993+
994+
class ClusterServerModeError(ArangoServerError):
995+
"""Failed to retrieve server mode in a cluster."""
984996

985997

986998
class ClusterServerStatisticsError(ArangoServerError):

docs/admin.rst

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,22 @@ database.
3232
# Retrieve the server time.
3333
sys_db.time()
3434

35-
# Retrieve the server role in a cluster.
35+
# Retrieve the server role.
3636
sys_db.role()
3737

38+
# Retrieve the server role in a cluster.
39+
sys_db.cluster.server_role()
40+
41+
# Retrieve the server mode.
42+
sys_db.mode()
43+
44+
# Retrieve the server mode in a cluster.
45+
sys_db.cluster.server_mode()
46+
47+
# Set the server mode.
48+
sys_db.set_mode('readonly')
49+
sys_db.set_mode('default')
50+
3851
# Retrieve the server statistics.
3952
sys_db.statistics()
4053

tests/test_cluster.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
ClusterServerCountError,
1313
ClusterServerEngineError,
1414
ClusterServerIDError,
15+
ClusterServerModeError,
1516
ClusterServerRoleError,
1617
ClusterServerStatisticsError,
1718
ClusterServerVersionError,
@@ -43,6 +44,18 @@ def test_cluster_server_role(sys_db, bad_db, cluster):
4344
assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
4445

4546

47+
def test_cluster_server_mode(sys_db, bad_db, cluster):
48+
if not cluster:
49+
pytest.skip("Only tested in a cluster setup")
50+
51+
result = sys_db.cluster.server_mode()
52+
assert result == "default"
53+
54+
with assert_raises(ClusterServerModeError) as err:
55+
bad_db.cluster.server_mode()
56+
assert err.value.error_code in {FORBIDDEN, DATABASE_NOT_FOUND}
57+
58+
4659
def test_cluster_health(sys_db, bad_db, cluster):
4760
if not cluster:
4861
pytest.skip("Only tested in a cluster setup")

tests/test_database.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
ServerLogLevelError,
2626
ServerLogLevelSetError,
2727
ServerMetricsError,
28+
ServerModeSetError,
2829
ServerReadLogError,
2930
ServerReloadRoutingError,
3031
ServerRequiredDBVersionError,
@@ -138,6 +139,19 @@ def test_database_misc_methods(client, sys_db, db, bad_db, cluster, secret):
138139
bad_db.role()
139140
assert err.value.error_code in {11, 1228}
140141

142+
# Test get/set server mode
143+
assert sys_db.mode() == "default"
144+
with assert_raises(ServerModeSetError):
145+
sys_db.set_mode("badmode")
146+
assert err.value.error_code in {11, 1228}
147+
148+
with assert_raises(ServerModeSetError):
149+
db.set_mode("readonly")
150+
assert err.value.error_code in {11, 1228}
151+
152+
result = sys_db.set_mode("default")
153+
assert result == {"mode": "default"}
154+
141155
# Test get server status
142156
status = db.status()
143157
assert "host" in status

0 commit comments

Comments
 (0)
0