Skip to content
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
47 changes: 47 additions & 0 deletions mock_tests/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
InsufficientPermissionsError,
UnexpectedStatusCodeError,
WeaviateStartUpError,
WeaviateUnsupportedFeatureError,
)

ACCESS_TOKEN = "HELLO!IamAnAccessToken"
Expand Down Expand Up @@ -437,6 +438,52 @@ def test_backup_cancel_while_create_and_restore(
)


def test_backup_create_include_roles_users(
weaviate_no_auth_mock: HTTPServer, start_grpc_server: grpc.Server
) -> None:
client = weaviate.connect_to_local(port=MOCK_PORT, host=MOCK_IP, grpc_port=MOCK_PORT_GRPC)
bodies: List[Dict[str, Any]] = []

def handler(request: Request) -> Response:
bodies.append(request.get_json())
return Response(json.dumps({"status": "STARTED", "path": "path", "id": "id"}))

weaviate_no_auth_mock.expect_request(
"/v1/backups/filesystem", method="POST"
).respond_with_handler(handler)

client.backup.create(backup_id="id", backend=BackupStorage.FILESYSTEM)
assert "includeRoles" not in bodies[0] and "includeUsers" not in bodies[0]

# the mock reports 1.36, below the 1.40 minimum
with pytest.raises(WeaviateUnsupportedFeatureError):
client.backup.create(backup_id="id", backend=BackupStorage.FILESYSTEM, include_roles="r")


def test_backup_create_include_roles_users_sent(
httpserver: HTTPServer, start_grpc_server: grpc.Server
) -> None:
httpserver.expect_request("/v1/.well-known/ready").respond_with_json({})
httpserver.expect_request("/v1/meta").respond_with_json({"version": "1.40.0"})
bodies: List[Dict[str, Any]] = []

def handler(request: Request) -> Response:
bodies.append(request.get_json())
return Response(json.dumps({"status": "STARTED", "path": "path", "id": "id"}))

httpserver.expect_request("/v1/backups/filesystem", method="POST").respond_with_handler(handler)

client = weaviate.connect_to_local(port=MOCK_PORT, host=MOCK_IP, grpc_port=MOCK_PORT_GRPC)
client.backup.create(
backup_id="id",
backend=BackupStorage.FILESYSTEM,
include_roles="r",
include_users=["u1", "u2"],
)
assert bodies[0]["includeRoles"] == ["r"]
assert bodies[0]["includeUsers"] == ["u1", "u2"]


def test_grpc_retry_logic(
retries: tuple[weaviate.collections.Collection, MockRetriesWeaviateService],
) -> None:
Expand Down
2 changes: 2 additions & 0 deletions weaviate/backup/async_.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class _BackupAsync(_BackupExecutor[ConnectionAsync]):
wait_for_completion: bool = False,
config: Optional[BackupConfigCreate] = None,
backup_location: Optional[BackupLocationType] = None,
include_roles: Union[List[str], str, None] = None,
include_users: Union[List[str], str, None] = None,
) -> BackupReturn: ...
async def get_create_status(
self,
Expand Down
24 changes: 24 additions & 0 deletions weaviate/backup/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ def create(
wait_for_completion: bool = False,
config: Optional[BackupConfigCreate] = None,
backup_location: Optional[BackupLocationType] = None,
include_roles: Union[List[str], str, None] = None,
include_users: Union[List[str], str, None] = None,
) -> executor.Result[BackupReturn]:
"""Create a backup of all/per collection Weaviate objects.

Expand All @@ -66,6 +68,10 @@ def create(
wait_for_completion: Whether to wait until the backup is done. By default False.
config: The configuration of the backup creation. By default None.
backup_location: The dynamic location of a backup. By default None.
include_roles: Roles to include. Accepts `*` and `?` wildcards. None backs up all roles, an empty list backs up
none. Requires Weaviate 1.40.0. By default None.
include_users: Dynamic DB users to include. Accepts `*` and `?` wildcards. None backs up all users, an empty list
backs up none. Requires Weaviate 1.40.0. By default None.

Returns:
A `_BackupReturn` object that contains the backup creation response.
Expand Down Expand Up @@ -98,6 +104,15 @@ def create(
"1.37.0",
)

if (
include_roles is not None or include_users is not None
) and self._connection._weaviate_version.is_lower_than(1, 40, 0):
raise WeaviateUnsupportedFeatureError(
"Backup include_roles/include_users",
str(self._connection._weaviate_version),
"1.40.0",
)

payload: dict = {
"id": backup_id,
"include": include_collections,
Expand All @@ -109,6 +124,15 @@ def create(
),
}

if include_roles is not None:
payload["includeRoles"] = (
[include_roles] if isinstance(include_roles, str) else include_roles
)
if include_users is not None:
payload["includeUsers"] = (
[include_users] if isinstance(include_users, str) else include_users
)

if config is not None:
payload["config"] = config._to_dict()

Expand Down
2 changes: 2 additions & 0 deletions weaviate/backup/sync.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class _Backup(_BackupExecutor[ConnectionSync]):
wait_for_completion: bool = False,
config: Optional[BackupConfigCreate] = None,
backup_location: Optional[BackupLocationType] = None,
include_roles: Union[List[str], str, None] = None,
include_users: Union[List[str], str, None] = None,
) -> BackupReturn: ...
def get_create_status(
self,
Expand Down
Loading