2024-07-26 17:24:46 +00:00
|
|
|
import logging
|
|
|
|
import re
|
|
|
|
|
|
|
|
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.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
|
|
|
|
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, get_file_hash
|
|
|
|
|
|
|
|
logger = logging.getLogger("NeoLogger")
|
|
|
|
|
|
|
|
|
2024-10-11 09:30:23 +00:00
|
|
|
@pytest.mark.nightly
|
2024-07-26 17:24:46 +00:00
|
|
|
@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) -> str:
|
|
|
|
with reporter.step("Create public container"):
|
|
|
|
cid_public = create_container(
|
|
|
|
default_wallet,
|
|
|
|
self.shell,
|
|
|
|
self.cluster.default_rpc_endpoint,
|
|
|
|
basic_acl=PUBLIC_ACL_F,
|
|
|
|
)
|
|
|
|
|
|
|
|
return cid_public
|
|
|
|
|
|
|
|
@pytest.fixture(scope="class")
|
|
|
|
def frostfs_cli(self, client_shell: Shell) -> FrostfsCli:
|
|
|
|
return FrostfsCli(client_shell, FROSTFS_CLI_EXEC)
|
|
|
|
|
|
|
|
@allure.title("Get public container by native API with generate private key")
|
|
|
|
def test_get_container_with_generated_key(self, frostfs_cli: FrostfsCli, public_container: str):
|
|
|
|
"""
|
|
|
|
Validate `container get` native API with flag `--generate-key`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
cid = public_container
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
|
|
|
|
with reporter.step("Get container with generate key"):
|
|
|
|
with expect_not_raises():
|
|
|
|
frostfs_cli.container.get(rpc_endpoint, cid, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
|
|
|
|
|
|
|
|
@allure.title("Get list containers by native API with generate private key")
|
|
|
|
def test_list_containers_with_generated_key(self, frostfs_cli: FrostfsCli, default_wallet: WalletInfo, public_container: str):
|
|
|
|
"""
|
|
|
|
Validate `container list` native API with flag `--generate-key`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
owner = default_wallet.get_address_from_json(0)
|
|
|
|
|
|
|
|
with reporter.step("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)
|
|
|
|
|
|
|
|
with reporter.step("Expect container in received containers list"):
|
|
|
|
containers = result.stdout.split()
|
|
|
|
assert public_container in containers
|
|
|
|
|
|
|
|
@allure.title("Get list of public container objects by native API with generate private key")
|
|
|
|
def test_list_objects_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str):
|
|
|
|
"""
|
|
|
|
Validate `container list_objects` native API with flag `--generate-key`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
cid = public_container
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
|
|
|
|
with reporter.step("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)
|
|
|
|
|
|
|
|
with reporter.step("Expect empty objects list"):
|
|
|
|
objects = result.stdout.split()
|
|
|
|
assert len(objects) == 0, objects
|
|
|
|
|
|
|
|
@allure.title("Search public container nodes by native API with generate private key")
|
|
|
|
def test_search_nodes_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str):
|
|
|
|
"""
|
|
|
|
Validate `container search_node` native API with flag `--generate-key`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
cid = public_container
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
|
|
|
|
with reporter.step("Search nodes with generate key"):
|
|
|
|
with expect_not_raises():
|
|
|
|
frostfs_cli.container.search_node(rpc_endpoint, cid, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
|
|
|
|
|
|
|
|
@allure.title("Put object into public container by native API with generate private key (obj_size={object_size})")
|
|
|
|
def test_put_object_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: TestFile):
|
|
|
|
"""
|
|
|
|
Validate `object put` into container with public ACL and flag `--generate-key`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
cid = public_container
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
|
|
|
|
with reporter.step("Put 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,
|
|
|
|
)
|
|
|
|
|
|
|
|
oid = self._parse_oid(result.stdout)
|
|
|
|
|
|
|
|
with reporter.step("List objects with generate key"):
|
|
|
|
result = frostfs_cli.container.list_objects(rpc_endpoint, cid, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
|
|
|
|
|
|
|
|
with reporter.step("Expect object in received objects list"):
|
|
|
|
objects = result.stdout.split()
|
|
|
|
assert oid in objects, objects
|
|
|
|
|
|
|
|
@allure.title("Get public container object by native API with generate private key (obj_size={object_size})")
|
|
|
|
def test_get_object_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: TestFile):
|
|
|
|
"""
|
|
|
|
Validate `object get` for container with public ACL and flag `--generate-key`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
cid = public_container
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
expected_hash = get_file_hash(file_path)
|
|
|
|
|
|
|
|
with reporter.step("Put 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=file_path,
|
|
|
|
generate_key=True,
|
|
|
|
no_progress=True,
|
|
|
|
timeout=CLI_DEFAULT_TIMEOUT,
|
|
|
|
)
|
|
|
|
|
|
|
|
downloaded_hash = get_file_hash(file_path)
|
|
|
|
|
|
|
|
with reporter.step("Validate downloaded file"):
|
|
|
|
assert expected_hash == downloaded_hash
|
|
|
|
|
|
|
|
@allure.title("Head public container object by native API with generate private key (obj_size={object_size})")
|
|
|
|
def test_head_object_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: TestFile):
|
|
|
|
"""
|
|
|
|
Validate `object head` for container with public ACL and flag `--generate-key`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
cid = public_container
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
|
|
|
|
with reporter.step("Put 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():
|
|
|
|
frostfs_cli.object.head(rpc_endpoint, cid, oid, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
|
|
|
|
|
|
|
|
@allure.title("Delete public container object by native API with generate private key (obj_size={object_size})")
|
|
|
|
def test_delete_object_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: TestFile):
|
|
|
|
"""
|
|
|
|
Validate `object delete` for container with public ACL and flag `--generate key`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
cid = public_container
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
|
|
|
|
with reporter.step("Put 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)
|
|
|
|
|
|
|
|
oid = self._parse_tombstone_oid(result.stdout)
|
|
|
|
|
|
|
|
with reporter.step("Head object with generate key"):
|
|
|
|
result = frostfs_cli.object.head(
|
|
|
|
rpc_endpoint,
|
|
|
|
cid,
|
|
|
|
oid,
|
|
|
|
generate_key=True,
|
|
|
|
timeout=CLI_DEFAULT_TIMEOUT,
|
|
|
|
)
|
|
|
|
|
|
|
|
with reporter.step("Expect object type TOMBSTONE"):
|
|
|
|
object_type = re.search(r"(?<=type: )tombstone", result.stdout, re.IGNORECASE).group()
|
|
|
|
assert object_type == "TOMBSTONE", object_type
|
|
|
|
|
|
|
|
@allure.title("Lock public container object by native API with generate private key (obj_size={object_size})")
|
|
|
|
def test_lock_object_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: TestFile):
|
|
|
|
"""
|
|
|
|
Validate `object lock` for container with public ACL and flag `--generate-key`.
|
|
|
|
Attempt to delete the locked object.
|
|
|
|
"""
|
|
|
|
|
|
|
|
cid = public_container
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
|
|
|
|
with reporter.step("Put 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 with generate key and expect error"):
|
|
|
|
with pytest.raises(Exception, match=OBJECT_IS_LOCKED):
|
|
|
|
frostfs_cli.object.delete(
|
|
|
|
rpc_endpoint,
|
|
|
|
cid,
|
|
|
|
oid,
|
|
|
|
generate_key=True,
|
|
|
|
timeout=CLI_DEFAULT_TIMEOUT,
|
|
|
|
)
|
|
|
|
|
|
|
|
@allure.title("Search public container objects by native API with generate private key (obj_size={object_size})")
|
|
|
|
def test_search_object_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: TestFile):
|
|
|
|
"""
|
|
|
|
Validate `object search` for container with public ACL and flag `--generate-key`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
cid = public_container
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
|
|
|
|
with reporter.step("Put 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("Object search with generate key"):
|
|
|
|
with expect_not_raises():
|
|
|
|
result = frostfs_cli.object.search(rpc_endpoint, cid, generate_key=True, timeout=CLI_DEFAULT_TIMEOUT)
|
|
|
|
|
|
|
|
with reporter.step("Expect object in received objects list of container"):
|
|
|
|
object_ids = re.findall(r"(\w{43,44})", result.stdout)
|
|
|
|
assert oid in object_ids
|
|
|
|
|
|
|
|
@allure.title("Get range of public container object by native API with generate private key (obj_size={object_size})")
|
|
|
|
def test_range_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: TestFile):
|
|
|
|
"""
|
|
|
|
Validate `object range` for container with public ACL and `--generate-key`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
cid = public_container
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
|
|
|
|
with reporter.step("Put 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=file_path,
|
|
|
|
generate_key=True,
|
|
|
|
timeout=CLI_DEFAULT_TIMEOUT,
|
|
|
|
)
|
|
|
|
|
|
|
|
@allure.title("Get hash of public container object by native API with generate private key (obj_size={object_size})")
|
|
|
|
def test_hash_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: TestFile):
|
|
|
|
"""
|
|
|
|
Validate `object hash` for container with public ACL and `--generate-key`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
cid = public_container
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
|
|
|
|
with reporter.step("Put 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():
|
|
|
|
frostfs_cli.object.hash(
|
|
|
|
rpc_endpoint,
|
|
|
|
cid,
|
|
|
|
oid,
|
|
|
|
range="0:10",
|
|
|
|
generate_key=True,
|
|
|
|
timeout=CLI_DEFAULT_TIMEOUT,
|
|
|
|
)
|
|
|
|
|
|
|
|
@allure.title("Get public container object nodes by native API with generate private key (obj_size={object_size})")
|
|
|
|
def test_nodes_with_generate_key(self, frostfs_cli: FrostfsCli, public_container: str, file_path: TestFile):
|
|
|
|
"""
|
|
|
|
Validate `object nodes` for container with public ACL and `--generate-key`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
cid = public_container
|
|
|
|
rpc_endpoint = self.cluster.default_rpc_endpoint
|
|
|
|
|
|
|
|
with reporter.step("Put 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)
|
|
|
|
|
|
|
|
with reporter.step("Configure frostfs-cli for alive remote node"):
|
|
|
|
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():
|
|
|
|
node_frostfs_cli.object.nodes(
|
|
|
|
rpc_endpoint,
|
|
|
|
cid,
|
|
|
|
oid=oid,
|
|
|
|
generate_key=True,
|
|
|
|
timeout=CLI_DEFAULT_TIMEOUT,
|
|
|
|
)
|