Skip to content

DE-741 | Options API [3.12] #317

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions arango/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
PermissionListError,
PermissionResetError,
PermissionUpdateError,
ServerAvailableOptionsGetError,
ServerCurrentOptionsGetError,
ServerDetailsError,
ServerEchoError,
ServerEncryptionError,
Expand Down Expand Up @@ -1118,6 +1120,58 @@ def response_handler(resp: Response) -> Json:

return self._execute(request, response_handler)

def options(self) -> Result[Json]:
"""Return the currently-set server options (ArangoDB 3.12+)

As this API may reveal sensitive data about the deployment, it can only
be accessed from inside the _system database. In addition, there is a
policy control startup option --server.options-api that determines if and
to whom the API is made available. This option can have the following
values:
- disabled: API is disabled.
- jwt: API can only be accessed via superuser JWT.
- admin: API can be accessed by admin users in the _system database only.
- public: everyone with access to _system database can access the API.

:return: Server options.
:rtype: dict
"""
request = Request(method="get", endpoint="/_admin/options")

def response_handler(resp: Response) -> Json:
if resp.is_success:
result: Json = resp.body
return result
raise ServerCurrentOptionsGetError(resp, request)

return self._execute(request, response_handler)

def options_available(self) -> Result[Json]:
"""Return a description of all available server options (ArangoDB 3.12+)

As this API may reveal sensitive data about the deployment, it can only
be accessed from inside the _system database. In addition, there is a
policy control startup option --server.options-api that determines if and
to whom the API is made available. This option can have the following
values:
- disabled: API is disabled.
- jwt: API can only be accessed via superuser JWT.
- admin: API can be accessed by admin users in the _system database only.
- public: everyone with access to _system database can access the options API.

:return: Server options.
:rtype: dict
"""
request = Request(method="get", endpoint="/_admin/options-description")

def response_handler(resp: Response) -> Json:
if resp.is_success:
result: Json = resp.body
return result
raise ServerAvailableOptionsGetError(resp, request)

return self._execute(request, response_handler)

#######################
# Database Management #
#######################
Expand Down
8 changes: 8 additions & 0 deletions arango/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,14 @@ class ServerEncryptionError(ArangoServerError):
"""Failed to reload user-defined encryption keys."""


class ServerCurrentOptionsGetError(ArangoServerError):
"""Failed to retrieve currently-set server options."""


class ServerAvailableOptionsGetError(ArangoServerError):
"""Failed to retrieve available server options."""


class ServerExecuteError(ArangoServerError):
"""Failed to execute raw JavaScript command."""

Expand Down
7 changes: 3 additions & 4 deletions starter.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,10 @@ else
exit 1
fi

conf_file=""
if [[ "${version%.*}" == "3.10" ]]; then
conf_file="${setup}-3.10"
if [ "$version" == "latest" ]; then
conf_file="${setup}-3.12"
else
conf_file="${setup}"
conf_file="${setup}-${version%.*.*}"
fi

docker run -d \
Expand Down
File renamed without changes.
15 changes: 15 additions & 0 deletions tests/static/cluster-3.12.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[starter]
mode = cluster
local = true
address = 0.0.0.0
port = 8528

[auth]
jwt-secret = /tests/static/keyfile

[args]
all.database.password = passwd
all.database.extended-names = true
all.log.api-enabled = true
all.javascript.allow-admin-execute = true
all.server.options-api = admin
File renamed without changes.
13 changes: 13 additions & 0 deletions tests/static/single-3.12.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[starter]
mode = single
address = 0.0.0.0
port = 8528

[auth]
jwt-secret = /tests/static/keyfile

[args]
all.database.password = passwd
all.database.extended-names = true
all.javascript.allow-admin-execute = true
all.server.options-api = admin
10 changes: 10 additions & 0 deletions tests/test_database.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from datetime import datetime

import pytest
from packaging import version

from arango.aql import AQL
from arango.backup import Backup
Expand Down Expand Up @@ -438,3 +439,12 @@ def test_license(sys_db, enterprise):
assert license == {"license": "none"}
with pytest.raises(ServerLicenseSetError):
sys_db.set_license("abc")


def test_options(sys_db, db_version):
# Skip if below 3.12
if db_version < version.parse("3.12.0"):
pytest.skip("Database options require ArangoDB 3.12+")

assert sys_db.options()
assert sys_db.options_available()
Loading