[#XX] Add object operation tests with -g flag

The tests check the result of an 'anonymous' user interacting with a gRPC API object.

Signed-off-by: Kirill Sosnovskikh <k.sosnovskikh@yadro.com>
This commit is contained in:
k.sosnovskikh 2024-07-26 20:24:46 +03:00
parent 89891b306b
commit 6f569fc757
2 changed files with 450 additions and 0 deletions
pytest.ini
pytest_tests/testsuites/object

View file

@ -19,6 +19,7 @@ markers =
grpc_api: standard gRPC API tests
grpc_control: tests related to using frostfs-cli control commands
grpc_object_lock: gRPC lock tests
grpc_without_user: gRPC without user tests
http_gate: HTTP gate contract
http_put: HTTP gate test cases with PUT call
s3_gate: All S3 gate tests

View file

@ -0,0 +1,449 @@
import logging
import os
import re
import uuid
from collections.abc import Generator
import allure
import pytest
from frostfs_testlib import reporter
from frostfs_testlib.cli import FrostfsCli
from frostfs_testlib.resources.cli import CLI_DEFAULT_TIMEOUT, FROSTFS_CLI_EXEC
from frostfs_testlib.resources.common import ASSETS_DIR
from frostfs_testlib.resources.error_patterns import OBJECT_IS_LOCKED
from frostfs_testlib.resources.wellknown_acl import PUBLIC_ACL_F
from frostfs_testlib.shell import Shell
from frostfs_testlib.steps.cli.container import create_container, delete_container
from frostfs_testlib.storage.dataclasses.wallet import WalletInfo
from frostfs_testlib.testing.cluster_test_base import ClusterTestBase
from frostfs_testlib.testing.test_control import expect_not_raises
from frostfs_testlib.utils.file_utils import TestFile
logger = logging.getLogger("NeoLogger")
@pytest.mark.grpc_without_user
class TestObjectApiWithoutUser(ClusterTestBase):
def _parse_oid(self, stdout: str) -> str:
id_str = stdout.strip().split("\n")[-2]
oid = id_str.split(":")[1]
return oid.strip()
def _parse_tombstone_oid(self, stdout: str) -> str:
id_str = stdout.split("\n")[1]
tombstone = id_str.split(":")[1]
return tombstone.strip()
@pytest.fixture(scope="function")
def public_container(self, default_wallet: WalletInfo) -> Generator[str, None, None]:
with reporter.step("Create public container"):
cid_public = create_container(
default_wallet,
self.shell,
self.cluster.default_rpc_endpoint,
basic_acl=PUBLIC_ACL_F,
)
yield cid_public
with reporter.step("Delete public container"):
delete_container(
default_wallet,
cid_public,
self.shell,
self.cluster.default_rpc_endpoint,
force=True,
)
@pytest.fixture(scope="class")
def frostfs_cli(self, client_shell: Shell) -> FrostfsCli:
return FrostfsCli(client_shell, FROSTFS_CLI_EXEC)
@pytest.fixture(scope="function")
def test_file(self) -> TestFile:
write_object = str(uuid.uuid4())
return TestFile(os.path.join(ASSETS_DIR, write_object))
@allure.title("Get public container")
def test_get_container_with_generated_key(self, frostfs_cli: FrostfsCli, public_container: str):
"""
Get container with public ACL, with generated private key.
"""
cid = public_container
rpc_endpoint = self.cluster.default_rpc_endpoint
with reporter.step("Get container with generate key"):
with expect_not_raises():
result = frostfs_cli.container.get(rpc_endpoint, cid, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
assert result.return_code == 0, result.stderr
@allure.title("Get list containers")
def test_list_containers_with_generated_key(self, frostfs_cli: FrostfsCli, default_wallet: WalletInfo, public_container: str):
"""
Get list containers with generated private key.
"""
rpc_endpoint = self.cluster.default_rpc_endpoint
owner = default_wallet.get_address_from_json(0)
with reporter.step("Get list containers with generate key"):
with expect_not_raises():
result = frostfs_cli.container.list(rpc_endpoint, owner=owner, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
assert result.return_code == 0, result.stderr
containers = result.stdout.split()
assert public_container in containers
@allure.title("Get list of public container objects")
def test_list_objects_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str):
"""
Get list container objects with public ACL, with generated private key.
"""
cid = public_container
rpc_endpoint = self.cluster.default_rpc_endpoint
with reporter.step("Get list objects with generate key"):
with expect_not_raises():
result = frostfs_cli.container.list_objects(rpc_endpoint, cid, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
assert result.return_code == 0, result.stderr
objects = result.stdout.split()
assert len(objects) == 0, objects
@allure.title("Search public container nodes")
def test_search_nodes_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str):
"""
Get list container nodes with public ACL, with generated private key.
"""
cid = public_container
rpc_endpoint = self.cluster.default_rpc_endpoint
with reporter.step("Search nodes with generate key"):
with expect_not_raises():
result = frostfs_cli.container.search_node(rpc_endpoint, cid, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
assert result.return_code == 0, result.stderr
@allure.title("Put object into public container (obj_size={object_size})")
def test_put_object_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: str):
"""
Put object into container with public ACL, with generated private key
and check object in container object list.
"""
cid = public_container
rpc_endpoint = self.cluster.default_rpc_endpoint
with reporter.step("Upload object with generate key"):
with expect_not_raises():
result = frostfs_cli.object.put(
rpc_endpoint,
cid,
file_path,
generate_key=True,
no_progress=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
assert result.return_code == 0, result.stderr
oid = self._parse_oid(result.stdout)
with reporter.step("Get list objects and check occurrence of uploaded object"):
result = frostfs_cli.container.list_objects(rpc_endpoint, cid, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
objects = result.stdout.split()
assert oid in objects, objects
@allure.title("Get public container object (obj_size={object_size})")
def test_get_object_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: str, test_file: TestFile):
"""
Get object uploaded to container with public ACL, with generated private key.
"""
cid = public_container
rpc_endpoint = self.cluster.default_rpc_endpoint
with reporter.step("Upload object with generate key"):
result = frostfs_cli.object.put(
rpc_endpoint,
cid,
file_path,
generate_key=True,
no_progress=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
oid = self._parse_oid(result.stdout)
with reporter.step("Get object with generate key"):
with expect_not_raises():
frostfs_cli.object.get(
rpc_endpoint,
cid,
oid,
file=test_file,
generate_key=True,
no_progress=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
with reporter.step("Validate downloaded file"):
with open(file_path, "rb") as file:
expected = file.read()
with open(test_file.path, "rb") as file:
data = file.read()
assert data == expected
@allure.title("Head public container object (obj_size={object_size})")
def test_head_object_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: str):
"""
Head object uploaded to container with public ACL, with generated private key.
"""
cid = public_container
rpc_endpoint = self.cluster.default_rpc_endpoint
with reporter.step("Upload object with generate key"):
result = frostfs_cli.object.put(
rpc_endpoint,
cid,
file_path,
generate_key=True,
no_progress=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
oid = self._parse_oid(result.stdout)
with reporter.step("Head object with generate key"):
with expect_not_raises():
result = frostfs_cli.object.head(rpc_endpoint, cid, oid, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
assert result.return_code == 0, result.stderr
@allure.title("Delete public container object (obj_size={object_size})")
def test_delete_object_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: str):
"""
Delete object uploaded to container with public ACL, with generated private key.
"""
cid = public_container
rpc_endpoint = self.cluster.default_rpc_endpoint
with reporter.step("Upload object with generate key"):
result = frostfs_cli.object.put(
rpc_endpoint,
cid,
file_path,
generate_key=True,
no_progress=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
oid = self._parse_oid(result.stdout)
with reporter.step("Delete object with generate key"):
with expect_not_raises():
result = frostfs_cli.object.delete(rpc_endpoint, cid, oid, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
assert result.return_code == 0, result.stderr
oid = self._parse_tombstone_oid(result.stdout)
with reporter.step("Head object and expected tombstone"):
result = frostfs_cli.object.head(
rpc_endpoint,
cid,
oid,
generate_key=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
object_type = re.search(r"(?<=type: )tombstone", result.stdout, re.IGNORECASE).group()
assert object_type == "TOMBSTONE", object_type
@allure.title("Lock public container object (obj_size={object_size})")
def test_lock_object_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: str):
"""
Lock object uploaded to container with public ACL, with generated private key.
Attempt to delete the locked object.
"""
cid = public_container
rpc_endpoint = self.cluster.default_rpc_endpoint
with reporter.step("Upload object with generate key"):
result = frostfs_cli.object.put(
rpc_endpoint,
cid,
file_path,
generate_key=True,
no_progress=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
oid = self._parse_oid(result.stdout)
with reporter.step("Lock object with generate key"):
with expect_not_raises():
frostfs_cli.object.lock(
rpc_endpoint,
cid,
oid,
generate_key=True,
timeout=CLI_DEFAULT_TIMEOUT,
lifetime=5,
)
with reporter.step("Delete locked object and expect error"):
with pytest.raises(Exception, match=OBJECT_IS_LOCKED):
result = frostfs_cli.object.delete(
rpc_endpoint,
cid,
oid,
generate_key=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
@allure.title("Search public container objects (obj_size={object_size})")
def test_search_object_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: str):
"""
Search container objects with public ACL, with generated private key.
"""
cid = public_container
rpc_endpoint = self.cluster.default_rpc_endpoint
with reporter.step("Upload object with generate key"):
result = frostfs_cli.object.put(
rpc_endpoint,
cid,
file_path,
generate_key=True,
no_progress=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
oid = self._parse_oid(result.stdout)
with reporter.step("Search objects with generate key"):
with expect_not_raises():
result = frostfs_cli.object.search(rpc_endpoint, cid, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
assert result.return_code == 0, result.stderr
object_ids = re.findall(r"(\w{43,44})", result.stdout)
assert oid in object_ids
@allure.title("Get range of public container object (obj_size={object_size})")
def test_range_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: str, test_file: TestFile):
"""
Get range of container object with public ACL, with generated private key.
"""
cid = public_container
rpc_endpoint = self.cluster.default_rpc_endpoint
with reporter.step("Upload object with generate key"):
result = frostfs_cli.object.put(
rpc_endpoint,
cid,
file_path,
generate_key=True,
no_progress=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
oid = self._parse_oid(result.stdout)
with reporter.step("Get range of object with generate key"):
with expect_not_raises():
frostfs_cli.object.range(
rpc_endpoint,
cid,
oid,
"0:10",
file=test_file,
generate_key=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
@allure.title("Get hash of public container object (obj_size={object_size})")
def test_hash_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: str):
"""
Get range hash of container object with public ACL, with generated private key.
"""
cid = public_container
rpc_endpoint = self.cluster.default_rpc_endpoint
with reporter.step("Upload object with generate key"):
result = frostfs_cli.object.put(
rpc_endpoint,
cid,
file_path,
generate_key=True,
no_progress=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
oid = self._parse_oid(result.stdout)
with reporter.step("Get range hash of object with generate key"):
with expect_not_raises():
result = frostfs_cli.object.hash(
rpc_endpoint,
cid,
oid,
range="0:10",
generate_key=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
assert result.return_code == 0, result.stderr
@allure.title("Get public container object nodes (obj_size={object_size})")
def test_nodes_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: str):
"""
Get container object nodes with public ACL, with generated private key.
"""
cid = public_container
rpc_endpoint = self.cluster.default_rpc_endpoint
with reporter.step("Upload object with generate key"):
result = frostfs_cli.object.put(
rpc_endpoint,
cid,
file_path,
no_progress=True,
generate_key=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
oid = self._parse_oid(result.stdout)
alive_node = self.cluster.cluster_nodes[0]
node_shell = alive_node.host.get_shell()
rpc_endpoint = alive_node.storage_node.get_rpc_endpoint()
node_frostfs_cli = FrostfsCli(node_shell, FROSTFS_CLI_EXEC)
with reporter.step("Get object nodes with generate key"):
with expect_not_raises():
result = node_frostfs_cli.object.nodes(
rpc_endpoint,
cid,
oid=oid,
generate_key=True,
timeout=CLI_DEFAULT_TIMEOUT,
)
assert result.return_code == 0, result.stderr