Add container operational in CliWrapper #284
3 changed files with 377 additions and 38 deletions
|
@ -16,6 +16,8 @@ class FrostfsCliContainer(CliCommand):
|
||||||
basic_acl: Optional[str] = None,
|
basic_acl: Optional[str] = None,
|
||||||
await_mode: bool = False,
|
await_mode: bool = False,
|
||||||
disable_timestamp: bool = False,
|
disable_timestamp: bool = False,
|
||||||
|
force: bool = False,
|
||||||
|
trace: bool = False,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
nonce: Optional[str] = None,
|
nonce: Optional[str] = None,
|
||||||
policy: Optional[str] = None,
|
policy: Optional[str] = None,
|
||||||
|
@ -37,6 +39,8 @@ class FrostfsCliContainer(CliCommand):
|
||||||
basic_acl: Hex encoded basic ACL value or keywords like 'public-read-write',
|
basic_acl: Hex encoded basic ACL value or keywords like 'public-read-write',
|
||||||
'private', 'eacl-public-read' (default "private").
|
'private', 'eacl-public-read' (default "private").
|
||||||
disable_timestamp: Disable timestamp container attribute.
|
disable_timestamp: Disable timestamp container attribute.
|
||||||
|
force: Skip placement validity check.
|
||||||
|
trace: Generate trace ID and print it.
|
||||||
name: Container name attribute.
|
name: Container name attribute.
|
||||||
nonce: UUIDv4 nonce value for container.
|
nonce: UUIDv4 nonce value for container.
|
||||||
policy: QL-encoded or JSON-encoded placement policy or path to file with it.
|
policy: QL-encoded or JSON-encoded placement policy or path to file with it.
|
||||||
|
@ -69,6 +73,7 @@ class FrostfsCliContainer(CliCommand):
|
||||||
ttl: Optional[int] = None,
|
ttl: Optional[int] = None,
|
||||||
xhdr: Optional[dict] = None,
|
xhdr: Optional[dict] = None,
|
||||||
force: bool = False,
|
force: bool = False,
|
||||||
|
trace: bool = False,
|
||||||
) -> CommandResult:
|
) -> CommandResult:
|
||||||
"""
|
"""
|
||||||
Delete an existing container.
|
Delete an existing container.
|
||||||
|
@ -78,6 +83,7 @@ class FrostfsCliContainer(CliCommand):
|
||||||
address: Address of wallet account.
|
address: Address of wallet account.
|
||||||
await_mode: Block execution until container is removed.
|
await_mode: Block execution until container is removed.
|
||||||
cid: Container ID.
|
cid: Container ID.
|
||||||
|
trace: Generate trace ID and print it.
|
||||||
force: Do not check whether container contains locks and remove immediately.
|
force: Do not check whether container contains locks and remove immediately.
|
||||||
rpc_endpoint: Remote node address (as 'multiaddr' or '<host>:<port>').
|
rpc_endpoint: Remote node address (as 'multiaddr' or '<host>:<port>').
|
||||||
session: Path to a JSON-encoded container session token.
|
session: Path to a JSON-encoded container session token.
|
||||||
|
@ -104,6 +110,7 @@ class FrostfsCliContainer(CliCommand):
|
||||||
await_mode: bool = False,
|
await_mode: bool = False,
|
||||||
to: Optional[str] = None,
|
to: Optional[str] = None,
|
||||||
json_mode: bool = False,
|
json_mode: bool = False,
|
||||||
|
trace: bool = False,
|
||||||
ttl: Optional[int] = None,
|
ttl: Optional[int] = None,
|
||||||
xhdr: Optional[dict] = None,
|
xhdr: Optional[dict] = None,
|
||||||
timeout: Optional[str] = None,
|
timeout: Optional[str] = None,
|
||||||
|
@ -116,6 +123,7 @@ class FrostfsCliContainer(CliCommand):
|
||||||
await_mode: Block execution until container is removed.
|
await_mode: Block execution until container is removed.
|
||||||
cid: Container ID.
|
cid: Container ID.
|
||||||
json_mode: Print or dump container in JSON format.
|
json_mode: Print or dump container in JSON format.
|
||||||
|
trace: Generate trace ID and print it.
|
||||||
rpc_endpoint: Remote node address (as 'multiaddr' or '<host>:<port>').
|
rpc_endpoint: Remote node address (as 'multiaddr' or '<host>:<port>').
|
||||||
to: Path to dump encoded container.
|
to: Path to dump encoded container.
|
||||||
ttl: TTL value in request meta header (default 2).
|
ttl: TTL value in request meta header (default 2).
|
||||||
|
@ -155,6 +163,8 @@ class FrostfsCliContainer(CliCommand):
|
||||||
cid: Container ID.
|
cid: Container ID.
|
||||||
rpc_endpoint: Remote node address (as 'multiaddr' or '<host>:<port>').
|
rpc_endpoint: Remote node address (as 'multiaddr' or '<host>:<port>').
|
||||||
to: Path to dump encoded container.
|
to: Path to dump encoded container.
|
||||||
|
json_mode: Print or dump container in JSON format.
|
||||||
|
trace: Generate trace ID and print it.
|
||||||
session: Path to a JSON-encoded container session token.
|
session: Path to a JSON-encoded container session token.
|
||||||
ttl: TTL value in request meta header (default 2).
|
ttl: TTL value in request meta header (default 2).
|
||||||
wallet: WIF (NEP-2) string or path to the wallet or binary key.
|
wallet: WIF (NEP-2) string or path to the wallet or binary key.
|
||||||
|
@ -174,6 +184,7 @@ class FrostfsCliContainer(CliCommand):
|
||||||
def list(
|
def list(
|
||||||
self,
|
self,
|
||||||
rpc_endpoint: str,
|
rpc_endpoint: str,
|
||||||
|
name: Optional[str] = None,
|
||||||
wallet: Optional[str] = None,
|
wallet: Optional[str] = None,
|
||||||
address: Optional[str] = None,
|
address: Optional[str] = None,
|
||||||
generate_key: Optional[bool] = None,
|
generate_key: Optional[bool] = None,
|
||||||
|
@ -188,11 +199,13 @@ class FrostfsCliContainer(CliCommand):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
address: Address of wallet account.
|
address: Address of wallet account.
|
||||||
|
name: List containers by the attribute name.
|
||||||
owner: Owner of containers (omit to use owner from private key).
|
owner: Owner of containers (omit to use owner from private key).
|
||||||
rpc_endpoint: Remote node address (as 'multiaddr' or '<host>:<port>').
|
rpc_endpoint: Remote node address (as 'multiaddr' or '<host>:<port>').
|
||||||
ttl: TTL value in request meta header (default 2).
|
ttl: TTL value in request meta header (default 2).
|
||||||
wallet: WIF (NEP-2) string or path to the wallet or binary key.
|
wallet: WIF (NEP-2) string or path to the wallet or binary key.
|
||||||
xhdr: Dict with request X-Headers.
|
xhdr: Dict with request X-Headers.
|
||||||
|
trace: Generate trace ID and print it.
|
||||||
timeout: Timeout for the operation (default 15s).
|
timeout: Timeout for the operation (default 15s).
|
||||||
generate_key: Generate a new private key.
|
generate_key: Generate a new private key.
|
||||||
|
|
||||||
|
@ -208,9 +221,11 @@ class FrostfsCliContainer(CliCommand):
|
||||||
self,
|
self,
|
||||||
rpc_endpoint: str,
|
rpc_endpoint: str,
|
||||||
cid: str,
|
cid: str,
|
||||||
|
bearer: Optional[str] = None,
|
||||||
wallet: Optional[str] = None,
|
wallet: Optional[str] = None,
|
||||||
address: Optional[str] = None,
|
address: Optional[str] = None,
|
||||||
generate_key: Optional[bool] = None,
|
generate_key: Optional[bool] = None,
|
||||||
|
trace: bool = False,
|
||||||
ttl: Optional[int] = None,
|
ttl: Optional[int] = None,
|
||||||
xhdr: Optional[dict] = None,
|
xhdr: Optional[dict] = None,
|
||||||
timeout: Optional[str] = None,
|
timeout: Optional[str] = None,
|
||||||
|
@ -221,10 +236,12 @@ class FrostfsCliContainer(CliCommand):
|
||||||
Args:
|
Args:
|
||||||
address: Address of wallet account.
|
address: Address of wallet account.
|
||||||
cid: Container ID.
|
cid: Container ID.
|
||||||
|
bearer: File with signed JSON or binary encoded bearer token.
|
||||||
rpc_endpoint: Remote node address (as 'multiaddr' or '<host>:<port>').
|
rpc_endpoint: Remote node address (as 'multiaddr' or '<host>:<port>').
|
||||||
ttl: TTL value in request meta header (default 2).
|
ttl: TTL value in request meta header (default 2).
|
||||||
wallet: WIF (NEP-2) string or path to the wallet or binary key.
|
wallet: WIF (NEP-2) string or path to the wallet or binary key.
|
||||||
xhdr: Dict with request X-Headers.
|
xhdr: Dict with request X-Headers.
|
||||||
|
trace: Generate trace ID and print it.
|
||||||
timeout: Timeout for the operation (default 15s).
|
timeout: Timeout for the operation (default 15s).
|
||||||
generate_key: Generate a new private key.
|
generate_key: Generate a new private key.
|
||||||
|
|
||||||
|
@ -236,6 +253,7 @@ class FrostfsCliContainer(CliCommand):
|
||||||
**{param: value for param, value in locals().items() if param not in ["self"]},
|
**{param: value for param, value in locals().items() if param not in ["self"]},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO Deprecated method with 0.42
|
||||||
def set_eacl(
|
def set_eacl(
|
||||||
self,
|
self,
|
||||||
rpc_endpoint: str,
|
rpc_endpoint: str,
|
||||||
|
@ -281,6 +299,7 @@ class FrostfsCliContainer(CliCommand):
|
||||||
address: Optional[str] = None,
|
address: Optional[str] = None,
|
||||||
ttl: Optional[int] = None,
|
ttl: Optional[int] = None,
|
||||||
from_file: Optional[str] = None,
|
from_file: Optional[str] = None,
|
||||||
|
trace: bool = False,
|
||||||
short: Optional[bool] = True,
|
short: Optional[bool] = True,
|
||||||
xhdr: Optional[dict] = None,
|
xhdr: Optional[dict] = None,
|
||||||
generate_key: Optional[bool] = None,
|
generate_key: Optional[bool] = None,
|
||||||
|
@ -298,6 +317,7 @@ class FrostfsCliContainer(CliCommand):
|
||||||
from_file: string File path with encoded container
|
from_file: string File path with encoded container
|
||||||
timeout: duration Timeout for the operation (default 15 s)
|
timeout: duration Timeout for the operation (default 15 s)
|
||||||
short: shorten the output of node information.
|
short: shorten the output of node information.
|
||||||
|
trace: Generate trace ID and print it.
|
||||||
xhdr: Dict with request X-Headers.
|
xhdr: Dict with request X-Headers.
|
||||||
generate_key: Generate a new private key.
|
generate_key: Generate a new private key.
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
from typing import Optional
|
import re
|
||||||
|
from typing import List, Optional, Union
|
||||||
|
|
||||||
from frostfs_testlib import reporter
|
from frostfs_testlib import reporter
|
||||||
from frostfs_testlib.cli.frostfs_cli.cli import FrostfsCli
|
from frostfs_testlib.cli.frostfs_cli.cli import FrostfsCli
|
||||||
|
from frostfs_testlib.plugins import load_plugin
|
||||||
from frostfs_testlib.resources.cli import CLI_DEFAULT_TIMEOUT
|
from frostfs_testlib.resources.cli import CLI_DEFAULT_TIMEOUT
|
||||||
from frostfs_testlib.storage.constants import PlacementRule
|
from frostfs_testlib.s3.interfaces import BucketContainerResolver
|
||||||
|
from frostfs_testlib.storage.cluster import ClusterNode
|
||||||
from frostfs_testlib.storage.grpc_operations import interfaces
|
from frostfs_testlib.storage.grpc_operations import interfaces
|
||||||
|
from frostfs_testlib.utils import json_utils
|
||||||
|
|
||||||
logger = logging.getLogger("NeoLogger")
|
logger = logging.getLogger("NeoLogger")
|
||||||
|
|
||||||
|
@ -18,13 +23,22 @@ class ContainerOperations(interfaces.ContainerInterface):
|
||||||
def create(
|
def create(
|
||||||
self,
|
self,
|
||||||
endpoint: str,
|
endpoint: str,
|
||||||
rule: str = PlacementRule.DEFAULT_PLACEMENT_RULE,
|
nns_zone: Optional[str] = None,
|
||||||
basic_acl: str = "",
|
nns_name: Optional[str] = None,
|
||||||
|
address: Optional[str] = None,
|
||||||
attributes: Optional[dict] = None,
|
attributes: Optional[dict] = None,
|
||||||
session_token: str = "",
|
basic_acl: Optional[str] = None,
|
||||||
|
await_mode: bool = False,
|
||||||
|
disable_timestamp: bool = False,
|
||||||
|
force: bool = False,
|
||||||
|
trace: bool = False,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
options: Optional[dict] = None,
|
nonce: Optional[str] = None,
|
||||||
await_mode: bool = True,
|
policy: Optional[str] = None,
|
||||||
|
session: Optional[str] = None,
|
||||||
|
subnet: Optional[str] = None,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -54,14 +68,23 @@ class ContainerOperations(interfaces.ContainerInterface):
|
||||||
"""
|
"""
|
||||||
result = self.cli.container.create(
|
result = self.cli.container.create(
|
||||||
rpc_endpoint=endpoint,
|
rpc_endpoint=endpoint,
|
||||||
policy=rule,
|
policy=policy,
|
||||||
basic_acl=basic_acl,
|
nns_zone=nns_zone,
|
||||||
|
nns_name=nns_name,
|
||||||
|
address=address,
|
||||||
attributes=attributes,
|
attributes=attributes,
|
||||||
name=name,
|
basic_acl=basic_acl,
|
||||||
session=session_token,
|
|
||||||
await_mode=await_mode,
|
await_mode=await_mode,
|
||||||
|
disable_timestamp=disable_timestamp,
|
||||||
|
force=force,
|
||||||
|
trace=trace,
|
||||||
|
name=name,
|
||||||
|
nonce=nonce,
|
||||||
|
session=session,
|
||||||
|
subnet=subnet,
|
||||||
|
ttl=ttl,
|
||||||
|
xhdr=xhdr,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
**options or {},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cid = self._parse_cid(result.stdout)
|
cid = self._parse_cid(result.stdout)
|
||||||
|
@ -71,21 +94,215 @@ class ContainerOperations(interfaces.ContainerInterface):
|
||||||
return cid
|
return cid
|
||||||
|
|
||||||
@reporter.step("List Containers")
|
@reporter.step("List Containers")
|
||||||
def list(self, endpoint: str, timeout: Optional[str] = CLI_DEFAULT_TIMEOUT) -> list[str]:
|
def list(
|
||||||
|
self,
|
||||||
|
endpoint: str,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
address: Optional[str] = None,
|
||||||
|
generate_key: Optional[bool] = None,
|
||||||
|
owner: Optional[str] = None,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
|
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
||||||
|
**params,
|
||||||
|
) -> List[str]:
|
||||||
"""
|
"""
|
||||||
A wrapper for `frostfs-cli container list` call. It returns all the
|
A wrapper for `frostfs-cli container list` call. It returns all the
|
||||||
available containers for the given wallet.
|
available containers for the given wallet.
|
||||||
Args:
|
Args:
|
||||||
wallet (WalletInfo): a wallet on whose behalf we list the containers
|
|
||||||
shell: executor for cli command
|
shell: executor for cli command
|
||||||
endpoint: FrostFS endpoint to send request to, appends to `--rpc-endpoint` key
|
endpoint: FrostFS endpoint to send request to, appends to `--rpc-endpoint` key
|
||||||
timeout: Timeout for the operation.
|
timeout: Timeout for the operation.
|
||||||
Returns:
|
Returns:
|
||||||
(list): list of containers
|
(list): list of containers
|
||||||
"""
|
"""
|
||||||
result = self.cli.container.list(rpc_endpoint=endpoint, timeout=timeout)
|
result = self.cli.container.list(
|
||||||
|
rpc_endpoint=endpoint,
|
||||||
|
name=name,
|
||||||
|
address=address,
|
||||||
|
generate_key=generate_key,
|
||||||
|
owner=owner,
|
||||||
|
ttl=ttl,
|
||||||
|
xhdr=xhdr,
|
||||||
|
timeout=timeout,
|
||||||
|
**params,
|
||||||
|
)
|
||||||
return result.stdout.split()
|
return result.stdout.split()
|
||||||
|
|
||||||
|
@reporter.step("List Objects in container")
|
||||||
|
def list_objects(
|
||||||
|
self,
|
||||||
|
endpoint: str,
|
||||||
|
cid: str,
|
||||||
|
bearer: Optional[str] = None,
|
||||||
|
wallet: Optional[str] = None,
|
||||||
|
address: Optional[str] = None,
|
||||||
|
generate_key: Optional[bool] = None,
|
||||||
|
trace: bool = False,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
|
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
||||||
|
) -> List[str]:
|
||||||
|
"""
|
||||||
|
A wrapper for `frostfs-cli container list-objects` call. It returns all the
|
||||||
|
available objects in container.
|
||||||
|
Args:
|
||||||
|
container_id: cid of container
|
||||||
|
endpoint: FrostFS endpoint to send request to, appends to `--rpc-endpoint` key
|
||||||
|
timeout: Timeout for the operation.
|
||||||
|
Returns:
|
||||||
|
(list): list of containers
|
||||||
|
"""
|
||||||
|
result = self.cli.container.list_objects(
|
||||||
|
rpc_endpoint=endpoint,
|
||||||
|
cid=cid,
|
||||||
|
bearer=bearer,
|
||||||
|
wallet=wallet,
|
||||||
|
address=address,
|
||||||
|
generate_key=generate_key,
|
||||||
|
trace=trace,
|
||||||
|
ttl=ttl,
|
||||||
|
xhdr=xhdr,
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
logger.info(f"Container objects: \n{result}")
|
||||||
|
return result.stdout.split()
|
||||||
|
|
||||||
|
@reporter.step("Delete container")
|
||||||
|
def delete(
|
||||||
|
self,
|
||||||
|
endpoint: str,
|
||||||
|
cid: str,
|
||||||
|
address: Optional[str] = None,
|
||||||
|
await_mode: bool = False,
|
||||||
|
session: Optional[str] = None,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
|
force: bool = False,
|
||||||
|
trace: bool = False,
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
return self.cli.container.delete(
|
||||||
|
rpc_endpoint=endpoint,
|
||||||
|
cid=cid,
|
||||||
|
address=address,
|
||||||
|
await_mode=await_mode,
|
||||||
|
session=session,
|
||||||
|
ttl=ttl,
|
||||||
|
xhdr=xhdr,
|
||||||
|
force=force,
|
||||||
|
trace=trace,
|
||||||
|
).stdout
|
||||||
|
except RuntimeError as e:
|
||||||
|
print(f"Error request:\n{e}")
|
||||||
|
|
||||||
|
@reporter.step("Get container")
|
||||||
|
def get(
|
||||||
|
self,
|
||||||
|
endpoint: str,
|
||||||
|
cid: str,
|
||||||
|
address: Optional[str] = None,
|
||||||
|
generate_key: Optional[bool] = None,
|
||||||
|
await_mode: bool = False,
|
||||||
|
to: Optional[str] = None,
|
||||||
|
json_mode: bool = True,
|
||||||
|
trace: bool = False,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
|
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
||||||
|
) -> Union[dict, str]:
|
||||||
|
result = self.cli.container.get(
|
||||||
|
rpc_endpoint=endpoint,
|
||||||
|
cid=cid,
|
||||||
|
address=address,
|
||||||
|
generate_key=generate_key,
|
||||||
|
await_mode=await_mode,
|
||||||
|
to=to,
|
||||||
|
json_mode=json_mode,
|
||||||
|
trace=trace,
|
||||||
|
ttl=ttl,
|
||||||
|
xhdr=xhdr,
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
container_info = json.loads(result.stdout)
|
||||||
|
attributes = dict()
|
||||||
|
for attr in container_info["attributes"]:
|
||||||
|
attributes[attr["key"]] = attr["value"]
|
||||||
|
container_info["attributes"] = attributes
|
||||||
|
container_info["ownerID"] = json_utils.json_reencode(container_info["ownerID"]["value"])
|
||||||
|
return container_info
|
||||||
|
|
||||||
|
@reporter.step("Get eacl container")
|
||||||
|
def get_eacl(
|
||||||
|
self,
|
||||||
|
endpoint: str,
|
||||||
|
cid: str,
|
||||||
|
address: Optional[str] = None,
|
||||||
|
generate_key: Optional[bool] = None,
|
||||||
|
await_mode: bool = False,
|
||||||
|
json_mode: bool = True,
|
||||||
|
trace: bool = False,
|
||||||
|
to: Optional[str] = None,
|
||||||
|
session: Optional[str] = None,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
|
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
||||||
|
):
|
||||||
|
return self.cli.container.get_eacl(
|
||||||
|
rpc_endpoint=endpoint,
|
||||||
|
cid=cid,
|
||||||
|
address=address,
|
||||||
|
generate_key=generate_key,
|
||||||
|
await_mode=await_mode,
|
||||||
|
to=to,
|
||||||
|
session=session,
|
||||||
|
ttl=ttl,
|
||||||
|
xhdr=xhdr,
|
||||||
|
timeout=CLI_DEFAULT_TIMEOUT,
|
||||||
|
).stdout
|
||||||
|
|
||||||
|
@reporter.step("Get nodes container")
|
||||||
|
def nodes(
|
||||||
|
self,
|
||||||
|
endpoint: str,
|
||||||
|
cid: str,
|
||||||
|
address: Optional[str] = None,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
from_file: Optional[str] = None,
|
||||||
|
trace: bool = False,
|
||||||
|
short: Optional[bool] = True,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
|
generate_key: Optional[bool] = None,
|
||||||
|
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
||||||
|
) -> List[ClusterNode]:
|
||||||
|
result = self.cli.container.search_node(
|
||||||
|
rpc_endpoint=endpoint,
|
||||||
|
cid=cid,
|
||||||
|
address=address,
|
||||||
|
ttl=ttl,
|
||||||
|
from_file=from_file,
|
||||||
|
trace=trace,
|
||||||
|
short=short,
|
||||||
|
xhdr=xhdr,
|
||||||
|
generate_key=generate_key,
|
||||||
|
timeout=timeout,
|
||||||
|
).stdout
|
||||||
|
|
||||||
|
pattern = r"[0-9]+(?:\.[0-9]+){3}"
|
||||||
|
nodes_ip = list(set(re.findall(pattern, result)))
|
||||||
|
|
||||||
|
with reporter.step(f"nodes ips = {nodes_ip}"):
|
||||||
|
nodes_list = cluster.get_nodes_by_ip(nodes_ip)
|
||||||
|
|
||||||
|
with reporter.step(f"Return nodes - {nodes_list}"):
|
||||||
|
return nodes_list
|
||||||
|
|
||||||
|
@reporter.step("Resolve container by name")
|
||||||
|
def resolve_container_by_name(name: str, node: ClusterNode):
|
||||||
|
resolver_cls = load_plugin("frostfs.testlib.bucket_cid_resolver", node.host.config.product)
|
||||||
|
resolver: BucketContainerResolver = resolver_cls()
|
||||||
|
return resolver.resolve(node, name)
|
||||||
|
|
||||||
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:
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Any, Optional
|
from typing import Any, List, Optional
|
||||||
|
|
||||||
from frostfs_testlib.resources.cli import CLI_DEFAULT_TIMEOUT
|
|
||||||
from frostfs_testlib.shell.interfaces import CommandResult
|
from frostfs_testlib.shell.interfaces import CommandResult
|
||||||
from frostfs_testlib.storage.cluster import Cluster, ClusterNode
|
from frostfs_testlib.storage.cluster import Cluster, ClusterNode
|
||||||
from frostfs_testlib.storage.constants import PlacementRule
|
from frostfs_testlib.storage.constants import PlacementRule
|
||||||
|
@ -96,7 +95,7 @@ class ObjectInterface(ABC):
|
||||||
bearer: str = "",
|
bearer: str = "",
|
||||||
xhdr: Optional[dict] = None,
|
xhdr: Optional[dict] = None,
|
||||||
session: Optional[str] = None,
|
session: Optional[str] = None,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
timeout: Optional[str] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -111,7 +110,7 @@ class ObjectInterface(ABC):
|
||||||
xhdr: Optional[dict] = None,
|
xhdr: Optional[dict] = None,
|
||||||
no_progress: bool = True,
|
no_progress: bool = True,
|
||||||
session: Optional[str] = None,
|
session: Optional[str] = None,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
timeout: Optional[str] = None,
|
||||||
) -> file_utils.TestFile:
|
) -> file_utils.TestFile:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -126,14 +125,14 @@ class ObjectInterface(ABC):
|
||||||
xhdr: Optional[dict] = None,
|
xhdr: Optional[dict] = None,
|
||||||
no_progress: bool = True,
|
no_progress: bool = True,
|
||||||
session: Optional[str] = None,
|
session: Optional[str] = None,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
timeout: Optional[str] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def hash(
|
def hash(
|
||||||
self,
|
self,
|
||||||
rpc_endpoint: str,
|
endpoint: str,
|
||||||
cid: str,
|
cid: str,
|
||||||
oid: str,
|
oid: str,
|
||||||
address: Optional[str] = None,
|
address: Optional[str] = None,
|
||||||
|
@ -145,7 +144,7 @@ class ObjectInterface(ABC):
|
||||||
session: Optional[str] = None,
|
session: Optional[str] = None,
|
||||||
hash_type: Optional[str] = None,
|
hash_type: Optional[str] = None,
|
||||||
xhdr: Optional[dict] = None,
|
xhdr: Optional[dict] = None,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
timeout: Optional[str] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -161,7 +160,7 @@ class ObjectInterface(ABC):
|
||||||
is_raw: bool = False,
|
is_raw: bool = False,
|
||||||
is_direct: bool = False,
|
is_direct: bool = False,
|
||||||
session: Optional[str] = None,
|
session: Optional[str] = None,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
timeout: Optional[str] = None,
|
||||||
) -> CommandResult | Any:
|
) -> CommandResult | Any:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -178,7 +177,7 @@ class ObjectInterface(ABC):
|
||||||
session: Optional[str] = None,
|
session: Optional[str] = None,
|
||||||
ttl: Optional[int] = None,
|
ttl: Optional[int] = None,
|
||||||
xhdr: Optional[dict] = None,
|
xhdr: Optional[dict] = None,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
timeout: Optional[str] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -195,7 +194,7 @@ class ObjectInterface(ABC):
|
||||||
expire_at: Optional[int] = None,
|
expire_at: Optional[int] = None,
|
||||||
no_progress: bool = True,
|
no_progress: bool = True,
|
||||||
session: Optional[str] = None,
|
session: Optional[str] = None,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
timeout: Optional[str] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -212,7 +211,7 @@ class ObjectInterface(ABC):
|
||||||
expire_at: Optional[int] = None,
|
expire_at: Optional[int] = None,
|
||||||
no_progress: bool = True,
|
no_progress: bool = True,
|
||||||
session: Optional[str] = None,
|
session: Optional[str] = None,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
timeout: Optional[str] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -226,7 +225,7 @@ class ObjectInterface(ABC):
|
||||||
bearer: str = "",
|
bearer: str = "",
|
||||||
xhdr: Optional[dict] = None,
|
xhdr: Optional[dict] = None,
|
||||||
session: Optional[str] = None,
|
session: Optional[str] = None,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
timeout: Optional[str] = None,
|
||||||
) -> tuple[file_utils.TestFile, bytes]:
|
) -> tuple[file_utils.TestFile, bytes]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -242,8 +241,8 @@ class ObjectInterface(ABC):
|
||||||
session: Optional[str] = None,
|
session: Optional[str] = None,
|
||||||
phy: bool = False,
|
phy: bool = False,
|
||||||
root: bool = False,
|
root: bool = False,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
timeout: Optional[str] = None,
|
||||||
) -> list:
|
) -> List:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
@ -257,8 +256,8 @@ class ObjectInterface(ABC):
|
||||||
xhdr: Optional[dict] = None,
|
xhdr: Optional[dict] = None,
|
||||||
is_direct: bool = False,
|
is_direct: bool = False,
|
||||||
verify_presence_all: bool = False,
|
verify_presence_all: bool = False,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
timeout: Optional[str] = None,
|
||||||
) -> list[ClusterNode]:
|
) -> List[ClusterNode]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -267,16 +266,119 @@ class ContainerInterface(ABC):
|
||||||
def create(
|
def create(
|
||||||
self,
|
self,
|
||||||
endpoint: str,
|
endpoint: str,
|
||||||
rule: str = PlacementRule.DEFAULT_PLACEMENT_RULE,
|
nns_zone: Optional[str] = None,
|
||||||
basic_acl: str = "",
|
nns_name: Optional[str] = None,
|
||||||
|
address: Optional[str] = None,
|
||||||
attributes: Optional[dict] = None,
|
attributes: Optional[dict] = None,
|
||||||
session_token: str = "",
|
basic_acl: Optional[str] = None,
|
||||||
|
await_mode: bool = False,
|
||||||
|
disable_timestamp: bool = False,
|
||||||
|
force: bool = False,
|
||||||
|
trace: bool = False,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
options: Optional[dict] = None,
|
nonce: Optional[str] = None,
|
||||||
await_mode: bool = True,
|
policy: Optional[str] = None,
|
||||||
timeout: Optional[str] = CLI_DEFAULT_TIMEOUT,
|
session: Optional[str] = None,
|
||||||
|
subnet: Optional[str] = None,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
|
timeout: Optional[str] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
pass
|
"""
|
||||||
|
Create a new container and register it in the FrostFS.
|
||||||
|
It will be stored in the sidechain when the Inner Ring accepts it.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError("No implemethed method create")
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def delete(
|
||||||
|
self,
|
||||||
|
endpoint: str,
|
||||||
|
cid: str,
|
||||||
|
address: Optional[str] = None,
|
||||||
|
await_mode: bool = False,
|
||||||
|
session: Optional[str] = None,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
|
force: bool = False,
|
||||||
|
trace: bool = False,
|
||||||
|
) -> List[str]:
|
||||||
|
"""
|
||||||
|
Delete an existing container.
|
||||||
|
Only the owner of the container has permission to remove the container.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError("No implemethed method delete")
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get(
|
||||||
|
self,
|
||||||
|
endpoint: str,
|
||||||
|
cid: str,
|
||||||
|
address: Optional[str] = None,
|
||||||
|
generate_key: Optional[bool] = None,
|
||||||
|
await_mode: bool = False,
|
||||||
|
to: Optional[str] = None,
|
||||||
|
json_mode: bool = True,
|
||||||
|
trace: bool = False,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
|
timeout: Optional[str] = None,
|
||||||
|
) -> List[str]:
|
||||||
|
"""Get container field info."""
|
||||||
|
raise NotImplementedError("No implemethed method get")
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_eacl(
|
||||||
|
self,
|
||||||
|
endpoint: str,
|
||||||
|
cid: str,
|
||||||
|
address: Optional[str] = None,
|
||||||
|
generate_key: Optional[bool] = None,
|
||||||
|
await_mode: bool = False,
|
||||||
|
json_mode: bool = True,
|
||||||
|
trace: bool = False,
|
||||||
|
to: Optional[str] = None,
|
||||||
|
session: Optional[str] = None,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
|
timeout: Optional[str] = None,
|
||||||
|
) -> List[str]:
|
||||||
|
"""Get extended ACL table of container."""
|
||||||
|
raise NotImplementedError("No implemethed method get-eacl")
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def list(
|
||||||
|
self,
|
||||||
|
endpoint: str,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
address: Optional[str] = None,
|
||||||
|
generate_key: Optional[bool] = None,
|
||||||
|
trace: bool = False,
|
||||||
|
owner: Optional[str] = None,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
|
timeout: Optional[str] = None,
|
||||||
|
**params,
|
||||||
|
) -> List[str]:
|
||||||
|
"""List all created containers."""
|
||||||
|
raise NotImplementedError("No implemethed method list")
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def nodes(
|
||||||
|
self,
|
||||||
|
endpoint: str,
|
||||||
|
cid: str,
|
||||||
|
address: Optional[str] = None,
|
||||||
|
ttl: Optional[int] = None,
|
||||||
|
from_file: Optional[str] = None,
|
||||||
|
trace: bool = False,
|
||||||
|
short: Optional[bool] = True,
|
||||||
|
xhdr: Optional[dict] = None,
|
||||||
|
generate_key: Optional[bool] = None,
|
||||||
|
timeout: Optional[str] = None,
|
||||||
|
) -> List[str]:
|
||||||
|
"""Show the nodes participating in the container in the current epoch."""
|
||||||
|
raise NotImplementedError("No implemethed method nodes")
|
||||||
|
|
||||||
|
|
||||||
class GrpcClientWrapper(ABC):
|
class GrpcClientWrapper(ABC):
|
||||||
|
|
Loading…
Reference in a new issue