Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
c27fb5747b [#376] Added ape manager group command to grpc client
Signed-off-by: Dmitriy Zayakin
Signed-off-by: Dmitriy Zayakin <d.zayakin@yadro.com>
2025-05-06 12:50:11 +00:00
517a7b9322 [#377] Update text for "subject not found" error
All checks were successful
DCO action / DCO (pull_request) Successful in 22s
Signed-off-by: Kirill Sosnovskikh <k.sosnovskikh@yadro.com>
2025-04-29 13:46:56 +03:00
10 changed files with 151 additions and 1 deletions

View file

@ -29,6 +29,7 @@ class FrostfsCli:
util: FrostfsCliUtil util: FrostfsCliUtil
version: FrostfsCliVersion version: FrostfsCliVersion
control: FrostfsCliControl control: FrostfsCliControl
ape_manager: FrostfsCliApeManager
def __init__(self, shell: Shell, frostfs_cli_exec_path: str, config_file: Optional[str] = None): def __init__(self, shell: Shell, frostfs_cli_exec_path: str, config_file: Optional[str] = None):
self.accounting = FrostfsCliAccounting(shell, frostfs_cli_exec_path, config=config_file) self.accounting = FrostfsCliAccounting(shell, frostfs_cli_exec_path, config=config_file)

View file

@ -1,6 +1,6 @@
# Regex patterns of status codes of Container service # Regex patterns of status codes of Container service
CONTAINER_NOT_FOUND = "code = 3072.*message = container not found" CONTAINER_NOT_FOUND = "code = 3072.*message = container not found"
SUBJECT_NOT_FOUND = "code = 1024.*message = frostfs error: chain/client.*subject not found.*" SUBJECT_NOT_FOUND = "code = 1024.*message =.*chain/client.*subject not found.*"
# Regex patterns of status codes of Object service # Regex patterns of status codes of Object service
MALFORMED_REQUEST = "code = 1024.*message = malformed request" MALFORMED_REQUEST = "code = 1024.*message = malformed request"

View file

@ -8,6 +8,7 @@ class CliClientWrapper(interfaces_wrapper.GrpcClientWrapper):
self.object: interfaces.ObjectInterface = implementations.ObjectOperations(self.cli) self.object: interfaces.ObjectInterface = implementations.ObjectOperations(self.cli)
self.container: interfaces.ContainerInterface = implementations.ContainerOperations(self.cli) self.container: interfaces.ContainerInterface = implementations.ContainerOperations(self.cli)
self.netmap: interfaces.NetmapInterface = implementations.NetmapOperations(self.cli) self.netmap: interfaces.NetmapInterface = implementations.NetmapOperations(self.cli)
self.ape_manager: interfaces.ApeManagerInterface = implementations.ApeManagerOperations(self.cli)
class RpcClientWrapper(interfaces_wrapper.GrpcClientWrapper): class RpcClientWrapper(interfaces_wrapper.GrpcClientWrapper):

View file

@ -1,3 +1,4 @@
from .ape_manager import ApeManagerOperations
from .chunks import ChunksOperations from .chunks import ChunksOperations
from .container import ContainerOperations from .container import ContainerOperations
from .netmap import NetmapOperations from .netmap import NetmapOperations

View file

@ -0,0 +1,79 @@
from typing import Optional
from frostfs_testlib import reporter
from frostfs_testlib.cli.frostfs_cli.cli import FrostfsCli
from frostfs_testlib.resources.cli import CLI_DEFAULT_TIMEOUT
class ApeManagerOperations:
def __init__(self, cli: FrostfsCli):
self.cli = cli
@reporter.step("Add ape rule")
def add(
self,
rpc_endpoint: str,
chain_id: Optional[str] = None,
chain_id_hex: Optional[str] = None,
path: Optional[str] = None,
rule: Optional[str] | Optional[list[str]] = None,
target_name: Optional[str] = None,
target_type: Optional[str] = None,
wallet: Optional[str] = None,
address: Optional[str] = None,
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
):
return self.cli.ape_manager.add(
rpc_endpoint=rpc_endpoint,
chain_id=chain_id,
chain_id_hex=chain_id_hex,
path=path,
rule=rule,
target_name=target_name,
target_type=target_type,
wallet=wallet,
address=address,
timeout=timeout,
)
@reporter.step("Get list APE rules")
def list(
self,
rpc_endpoint: str,
target_name: Optional[str] = None,
target_type: Optional[str] = None,
wallet: Optional[str] = None,
address: Optional[str] = None,
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
):
return self.cli.ape_manager.list(
rpc_endpoint=rpc_endpoint,
target_name=target_name,
target_type=target_type,
wallet=wallet,
address=address,
timeout=timeout,
)
@reporter.step("Remove APE rule")
def remove(
self,
rpc_endpoint: str,
chain_id: Optional[str] = None,
chain_id_hex: Optional[str] = None,
target_name: Optional[str] = None,
target_type: Optional[str] = None,
wallet: Optional[str] = None,
address: Optional[str] = None,
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
):
return self.cli.ape_manager.remove(
rpc_endpoint=rpc_endpoint,
chain_id=chain_id,
chain_id_hex=chain_id_hex,
target_name=target_name,
target_type=target_type,
wallet=wallet,
address=address,
timeout=timeout,
)

View file

@ -1,6 +1,7 @@
import json import json
import logging import logging
import re import re
from time import sleep
from typing import List, Optional, Union from typing import List, Optional, Union
from frostfs_testlib import reporter from frostfs_testlib import reporter
@ -301,6 +302,16 @@ class ContainerOperations(interfaces.ContainerInterface):
resolver: BucketContainerResolver = resolver_cls() resolver: BucketContainerResolver = resolver_cls()
return resolver.resolve(node, name) return resolver.resolve(node, name)
@reporter.step("Wait create container, with list")
def wait_creation(self, cid: str, endpoint: str, attempts: int = 15, sleep_interval: int = 1):
for _ in range(attempts):
containers = self.list(endpoint)
if cid in containers:
return
logger.info(f"There is no {cid} in {containers} yet; sleep {sleep_interval} and continue")
sleep(sleep_interval)
raise RuntimeError(f"After {attempts * sleep_interval} seconds container {cid} hasn't been persisted; exiting")
def _parse_cid(self, output: str) -> str: def _parse_cid(self, output: str) -> str:
""" """
Parses container ID from a given CLI output. The input string we expect: Parses container ID from a given CLI output. The input string we expect:

View file

@ -1,3 +1,4 @@
from .ape_manager import ApeManagerInterface
from .chunks import ChunksInterface from .chunks import ChunksInterface
from .container import ContainerInterface from .container import ContainerInterface
from .netmap import NetmapInterface from .netmap import NetmapInterface

View file

@ -0,0 +1,48 @@
from abc import ABC, abstractmethod
from typing import Optional
from frostfs_testlib.shell.interfaces import CommandResult
class ApeManagerInterface(ABC):
@abstractmethod
def add(
self,
rpc_endpoint: str,
chain_id: Optional[str] = None,
chain_id_hex: Optional[str] = None,
path: Optional[str] = None,
rule: Optional[str] | Optional[list[str]] = None,
target_name: Optional[str] = None,
target_type: Optional[str] = None,
wallet: Optional[str] = None,
address: Optional[str] = None,
timeout: Optional[str] = None,
) -> CommandResult:
pass
@abstractmethod
def list(
self,
rpc_endpoint: str,
target_name: Optional[str] = None,
target_type: Optional[str] = None,
wallet: Optional[str] = None,
address: Optional[str] = None,
timeout: Optional[str] = None,
) -> CommandResult:
pass
@abstractmethod
def remove(
self,
rpc_endpoint: str,
chain_id: Optional[str] = None,
chain_id_hex: Optional[str] = None,
target_name: Optional[str] = None,
target_type: Optional[str] = None,
wallet: Optional[str] = None,
address: Optional[str] = None,
timeout: Optional[str] = None,
) -> CommandResult:
pass

View file

@ -123,3 +123,7 @@ class ContainerInterface(ABC):
) -> List[ClusterNode]: ) -> List[ClusterNode]:
"""Show the nodes participating in the container in the current epoch.""" """Show the nodes participating in the container in the current epoch."""
raise NotImplementedError("No implemethed method nodes") raise NotImplementedError("No implemethed method nodes")
@abstractmethod
def wait_creation(self, cid: str, endpoint: str, attempts: Optional[str], sleep_interval: Optional[int]) -> None:
raise NotImplementedError("No implemented method wait_creation")

View file

@ -1,10 +1,14 @@
from abc import ABC from abc import ABC
from frostfs_testlib.cli.frostfs_cli.cli import FrostfsCli
from . import interfaces from . import interfaces
class GrpcClientWrapper(ABC): class GrpcClientWrapper(ABC):
def __init__(self) -> None: def __init__(self) -> None:
self.cli: FrostfsCli
self.object: interfaces.ObjectInterface self.object: interfaces.ObjectInterface
self.container: interfaces.ContainerInterface self.container: interfaces.ContainerInterface
self.netmap: interfaces.NetmapInterface self.netmap: interfaces.NetmapInterface
self.ape_manager: interfaces.ApeManagerInterface