[#314] Format all files with black and isort

Signed-off-by: Vladimir Domnich <v.domnich@yadro.com>
This commit is contained in:
Vladimir Domnich 2022-09-28 16:07:16 +04:00 committed by Vladimir
parent 26032a67ec
commit 147cac0ebc
46 changed files with 1506 additions and 1100 deletions

View file

@ -15,41 +15,41 @@ from cli_utils import NeofsCli
from common import ASSETS_DIR, NEOFS_CLI_EXEC, NEOFS_ENDPOINT, WALLET_CONFIG
from data_formatters import get_wallet_public_key
logger = logging.getLogger('NeoLogger')
logger = logging.getLogger("NeoLogger")
EACL_LIFETIME = 100500
NEOFS_CONTRACT_CACHE_TIMEOUT = 30
class EACLOperation(Enum):
PUT = 'put'
GET = 'get'
HEAD = 'head'
GET_RANGE = 'getrange'
GET_RANGE_HASH = 'getrangehash'
SEARCH = 'search'
DELETE = 'delete'
PUT = "put"
GET = "get"
HEAD = "head"
GET_RANGE = "getrange"
GET_RANGE_HASH = "getrangehash"
SEARCH = "search"
DELETE = "delete"
class EACLAccess(Enum):
ALLOW = 'allow'
DENY = 'deny'
ALLOW = "allow"
DENY = "deny"
class EACLRole(Enum):
OTHERS = 'others'
USER = 'user'
SYSTEM = 'system'
OTHERS = "others"
USER = "user"
SYSTEM = "system"
class EACLHeaderType(Enum):
REQUEST = 'req' # Filter request headers
OBJECT = 'obj' # Filter object headers
SERVICE = 'SERVICE' # Filter service headers. These are not processed by NeoFS nodes and exist for service use only
REQUEST = "req" # Filter request headers
OBJECT = "obj" # Filter object headers
SERVICE = "SERVICE" # Filter service headers. These are not processed by NeoFS nodes and exist for service use only
class EACLMatchType(Enum):
STRING_EQUAL = '=' # Return true if strings are equal
STRING_NOT_EQUAL = '!=' # Return true if strings are different
STRING_EQUAL = "=" # Return true if strings are equal
STRING_NOT_EQUAL = "!=" # Return true if strings are different
@dataclass
@ -60,7 +60,12 @@ class EACLFilter:
value: Optional[str] = None
def to_dict(self) -> Dict[str, Any]:
return {'headerType': self.header_type, 'matchType': self.match_type, 'key': self.key, 'value': self.value}
return {
"headerType": self.header_type,
"matchType": self.match_type,
"key": self.key,
"value": self.value,
}
@dataclass
@ -68,10 +73,16 @@ class EACLFilters:
filters: Optional[List[EACLFilter]] = None
def __str__(self):
return ','.join(
[f'{filter.header_type.value}:{filter.key}{filter.match_type.value}{filter.value}'
for filter in self.filters]
) if self.filters else []
return (
",".join(
[
f"{filter.header_type.value}:{filter.key}{filter.match_type.value}{filter.value}"
for filter in self.filters
]
)
if self.filters
else []
)
@dataclass
@ -87,15 +98,23 @@ class EACLRule:
filters: Optional[EACLFilters] = None
def to_dict(self) -> Dict[str, Any]:
return {'Operation': self.operation, 'Access': self.access, 'Role': self.role,
'Filters': self.filters or []}
return {
"Operation": self.operation,
"Access": self.access,
"Role": self.role,
"Filters": self.filters or [],
}
def __str__(self):
role = self.role.value if isinstance(self.role, EACLRole) else f'pubkey:{get_wallet_public_key(self.role, "")}'
role = (
self.role.value
if isinstance(self.role, EACLRole)
else f'pubkey:{get_wallet_public_key(self.role, "")}'
)
return f'{self.access.value} {self.operation.value} {self.filters or ""} {role}'
@allure.title('Get extended ACL')
@allure.title("Get extended ACL")
def get_eacl(wallet_path: str, cid: str) -> Optional[str]:
cli = NeofsCli(config=WALLET_CONFIG)
try:
@ -104,16 +123,21 @@ def get_eacl(wallet_path: str, cid: str) -> Optional[str]:
logger.info("Extended ACL table is not set for this container")
logger.info(f"Got exception while getting eacl: {exc}")
return None
if 'extended ACL table is not set for this container' in output:
if "extended ACL table is not set for this container" in output:
return None
return output
@allure.title('Set extended ACL')
@allure.title("Set extended ACL")
def set_eacl(wallet_path: str, cid: str, eacl_table_path: str) -> None:
cli = NeofsCli(config=WALLET_CONFIG, timeout=60)
cli.container.set_eacl(wallet=wallet_path, rpc_endpoint=NEOFS_ENDPOINT, cid=cid, table=eacl_table_path,
await_mode=True)
cli.container.set_eacl(
wallet=wallet_path,
rpc_endpoint=NEOFS_ENDPOINT,
cid=cid,
table=eacl_table_path,
await_mode=True,
)
def _encode_cid_for_eacl(cid: str) -> str:
@ -125,14 +149,16 @@ def create_eacl(cid: str, rules_list: List[EACLRule]) -> str:
table_file_path = f"{os.getcwd()}/{ASSETS_DIR}/eacl_table_{str(uuid.uuid4())}.json"
NeofsCli().acl.extended_create(cid=cid, out=table_file_path, rule=rules_list)
with open(table_file_path, 'r') as file:
with open(table_file_path, "r") as file:
table_data = file.read()
logger.info(f"Generated eACL:\n{table_data}")
return table_file_path
def form_bearertoken_file(wif: str, cid: str, eacl_rule_list: List[Union[EACLRule, EACLPubKey]]) -> str:
def form_bearertoken_file(
wif: str, cid: str, eacl_rule_list: List[Union[EACLRule, EACLPubKey]]
) -> str:
"""
This function fetches eACL for given <cid> on behalf of <wif>,
then extends it with filters taken from <eacl_rules>, signs
@ -144,50 +170,29 @@ def form_bearertoken_file(wif: str, cid: str, eacl_rule_list: List[Union[EACLRul
eacl = get_eacl(wif, cid)
json_eacl = dict()
if eacl:
eacl = eacl.replace('eACL: ', '').split('Signature')[0]
eacl = eacl.replace("eACL: ", "").split("Signature")[0]
json_eacl = json.loads(eacl)
logger.info(json_eacl)
eacl_result = {
"body":
{
"eaclTable":
{
"containerID":
{
"value": enc_cid
},
"records": []
},
"lifetime":
{
"exp": EACL_LIFETIME,
"nbf": "1",
"iat": "0"
}
}
"body": {
"eaclTable": {"containerID": {"value": enc_cid}, "records": []},
"lifetime": {"exp": EACL_LIFETIME, "nbf": "1", "iat": "0"},
}
}
assert eacl_rules, 'Got empty eacl_records list'
assert eacl_rules, "Got empty eacl_records list"
for rule in eacl_rule_list:
op_data = {
"operation": rule.operation.value.upper(),
"action": rule.access.value.upper(),
"filters": rule.filters or [],
"targets": []
"targets": [],
}
if isinstance(rule.role, EACLRole):
op_data['targets'] = [
{
"role": rule.role.value.upper()
}
]
op_data["targets"] = [{"role": rule.role.value.upper()}]
elif isinstance(rule.role, EACLPubKey):
op_data['targets'] = [
{
'keys': rule.role.keys
}
]
op_data["targets"] = [{"keys": rule.role.keys}]
eacl_result["body"]["eaclTable"]["records"].append(op_data)
@ -196,7 +201,7 @@ def form_bearertoken_file(wif: str, cid: str, eacl_rule_list: List[Union[EACLRul
for record in json_eacl["records"]:
eacl_result["body"]["eaclTable"]["records"].append(record)
with open(file_path, 'w', encoding='utf-8') as eacl_file:
with open(file_path, "w", encoding="utf-8") as eacl_file:
json.dump(eacl_result, eacl_file, ensure_ascii=False, indent=4)
logger.info(f"Got these extended ACL records: {eacl_result}")
@ -206,17 +211,17 @@ def form_bearertoken_file(wif: str, cid: str, eacl_rule_list: List[Union[EACLRul
def eacl_rules(access: str, verbs: list, user: str) -> list[str]:
"""
This function creates a list of eACL rules.
Args:
access (str): identifies if the following operation(s)
is allowed or denied
verbs (list): a list of operations to set rules for
user (str): a group of users (user/others) or a wallet of
a certain user for whom rules are set
Returns:
(list): a list of eACL rules
This function creates a list of eACL rules.
Args:
access (str): identifies if the following operation(s)
is allowed or denied
verbs (list): a list of operations to set rules for
user (str): a group of users (user/others) or a wallet of
a certain user for whom rules are set
Returns:
(list): a list of eACL rules
"""
if user not in ('others', 'user'):
if user not in ("others", "user"):
pubkey = get_wallet_public_key(user, wallet_password="")
user = f"pubkey:{pubkey}"
@ -229,13 +234,13 @@ def eacl_rules(access: str, verbs: list, user: str) -> list[str]:
def sign_bearer_token(wallet_path: str, eacl_rules_file: str) -> None:
cmd = (
f'{NEOFS_CLI_EXEC} util sign bearer-token --from {eacl_rules_file} '
f'--to {eacl_rules_file} --wallet {wallet_path} --config {WALLET_CONFIG} --json'
f"{NEOFS_CLI_EXEC} util sign bearer-token --from {eacl_rules_file} "
f"--to {eacl_rules_file} --wallet {wallet_path} --config {WALLET_CONFIG} --json"
)
_cmd_run(cmd)
@allure.title('Wait for eACL cache expired')
@allure.title("Wait for eACL cache expired")
def wait_for_cache_expired():
sleep(NEOFS_CONTRACT_CACHE_TIMEOUT)
return

View file

@ -6,8 +6,8 @@ from .completion import NeofsAdmCompletion
from .config import NeofsAdmConfig
from .gendoc import NeofsAdmGenDoc
from .morph import NeofsAdmMorph
from .subnet import NeofsAdmMorphSubnet
from .storage_config import NeofsAdmStorageConfig
from .subnet import NeofsAdmMorphSubnet
from .version import NeofsAdmVersion
@ -23,14 +23,27 @@ class NeofsAdm:
storage_config: Optional[NeofsAdmStorageConfig] = None
version: Optional[NeofsAdmVersion] = None
def __init__(self, neofs_adm_exec_path: Optional[str] = None, config_file: Optional[str] = None, timeout: int = 30):
def __init__(
self,
neofs_adm_exec_path: Optional[str] = None,
config_file: Optional[str] = None,
timeout: int = 30,
):
self.config_file = config_file
self.neofs_adm_exec_path = neofs_adm_exec_path or NEOFS_ADM_EXEC
self.completion = NeofsAdmCompletion(self.neofs_adm_exec_path, timeout=timeout, config=config_file)
self.completion = NeofsAdmCompletion(
self.neofs_adm_exec_path, timeout=timeout, config=config_file
)
self.config = NeofsAdmConfig(self.neofs_adm_exec_path, timeout=timeout, config=config_file)
self.gendoc = NeofsAdmGenDoc(self.neofs_adm_exec_path, timeout=timeout, config=config_file)
self.morph = NeofsAdmMorph(self.neofs_adm_exec_path, timeout=timeout, config=config_file)
self.subnet = NeofsAdmMorphSubnet(self.neofs_adm_exec_path, timeout=timeout, config=config_file)
self.storage_config = NeofsAdmStorageConfig(self.neofs_adm_exec_path, timeout=timeout, config=config_file)
self.version = NeofsAdmVersion(self.neofs_adm_exec_path, timeout=timeout, config=config_file)
self.subnet = NeofsAdmMorphSubnet(
self.neofs_adm_exec_path, timeout=timeout, config=config_file
)
self.storage_config = NeofsAdmStorageConfig(
self.neofs_adm_exec_path, timeout=timeout, config=config_file
)
self.version = NeofsAdmVersion(
self.neofs_adm_exec_path, timeout=timeout, config=config_file
)

View file

@ -27,4 +27,4 @@ class NeofsAdmCompletion(NeofsCliCommand):
str: Command string
"""
return self._execute('completion ' + completion_type.value)
return self._execute("completion " + completion_type.value)

View file

@ -2,7 +2,7 @@ from enum import Enum
class CompletionType(Enum):
BASH = 'bash'
ZHS = 'zsh'
FISH = 'fish'
POWERSHELL = 'powershell'
BASH = "bash"
ZHS = "zsh"
FISH = "fish"
POWERSHELL = "powershell"

View file

@ -2,7 +2,7 @@ from cli_utils.cli_command import NeofsCliCommand
class NeofsAdmConfig(NeofsCliCommand):
def init(self, path: str = '~/.neofs/adm/config.yml') -> str:
def init(self, path: str = "~/.neofs/adm/config.yml") -> str:
"""Initialize basic neofs-adm configuration file.
Args:
@ -14,6 +14,6 @@ class NeofsAdmConfig(NeofsCliCommand):
"""
return self._execute(
'config init',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"config init",
**{param: value for param, value in locals().items() if param not in ["self"]},
)

View file

@ -4,7 +4,9 @@ from cli_utils.cli_command import NeofsCliCommand
class NeofsAdmGenDoc(NeofsCliCommand):
def get(self, doc_file: str, depth: int = 1, doc_type: str = 'md', extension: Optional[str] = None) -> str:
def get(
self, doc_file: str, depth: int = 1, doc_type: str = "md", extension: Optional[str] = None
) -> str:
"""Generate documentation for this command. If the template is not provided,
builtin cobra generator is used and each subcommand is placed in
a separate file in the same directory.
@ -29,6 +31,10 @@ class NeofsAdmGenDoc(NeofsCliCommand):
"""
return self._execute(
f'gendoc {doc_file}',
**{param: param_value for param, param_value in locals().items() if param not in ['self', 'doc_file']}
f"gendoc {doc_file}",
**{
param: value
for param, value in locals().items()
if param not in ["self", "doc_file"]
},
)

View file

@ -4,9 +4,16 @@ from cli_utils.cli_command import NeofsCliCommand
class NeofsAdmMorph(NeofsCliCommand):
def deposit_notary(self, rpc_endpoint: str, account: str, gas: str, storage_wallet: Optional[str] = None,
till: Optional[str] = None) -> str:
"""Deposit GAS for notary service.
def deposit_notary(
self,
rpc_endpoint: str,
account: str,
gas: str,
storage_wallet: Optional[str] = None,
till: Optional[str] = None,
) -> str:
"""
Deposit GAS for notary service.
Args:
account (str): wallet account address
@ -15,19 +22,24 @@ class NeofsAdmMorph(NeofsCliCommand):
storage_wallet (str): path to storage node wallet
till (str): notary deposit duration in blocks
Returns:
str: Command string
"""
return self._execute(
'morph deposit-notary',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph deposit-notary",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def dump_balances(self, rpc_endpoint: str, alphabet: Optional[str] = None, proxy: Optional[str] = None,
script_hash: Optional[str] = None, storage: Optional[str] = None) -> str:
"""Dump GAS balances
def dump_balances(
self,
rpc_endpoint: str,
alphabet: Optional[str] = None,
proxy: Optional[str] = None,
script_hash: Optional[str] = None,
storage: Optional[str] = None,
) -> str:
"""
Dump GAS balances.
Args:
alphabet (str): dump balances of alphabet contracts
@ -36,35 +48,38 @@ class NeofsAdmMorph(NeofsCliCommand):
script_hash (str): use script-hash format for addresses
storage (str): dump balances of storage nodes from the current netmap
Returns:
str: Command string
"""
return self._execute(
'morph dump-balances',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph dump-balances",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def dump_config(self, rpc_endpoint: str) -> str:
"""Section for morph network configuration commands.
"""
Dump NeoFS network config.
Args:
rpc_endpoint (str): N3 RPC node endpoint
Returns:
str: Command string
"""
return self._execute(
'morph dump-config',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph dump-config",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def dump_containers(self, rpc_endpoint: str, cid: Optional[str] = None, container_contract: Optional[str] = None,
dump: Optional[str] = None) -> str:
"""Dump NeoFS containers to file.
def dump_containers(
self,
rpc_endpoint: str,
cid: Optional[str] = None,
container_contract: Optional[str] = None,
dump: Optional[str] = None,
) -> str:
"""
Dump NeoFS containers to file.
Args:
cid (str): containers to dump
@ -72,70 +87,73 @@ class NeofsAdmMorph(NeofsCliCommand):
dump (str): file where to save dumped containers
rpc_endpoint (str): N3 RPC node endpoint
Returns:
str: Command string
"""
return self._execute(
'morph dump-containers',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph dump-containers",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def dump_hashes(self, rpc_endpoint: str) -> str:
"""Dump deployed contract hashes.
"""
Dump deployed contract hashes.
Args:
rpc_endpoint (str): N3 RPC node endpoint
Returns:
str: Command string
"""
return self._execute(
'morph dump-hashes',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph dump-hashes",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def force_new_epoch(self, rpc_endpoint: Optional[str] = None, alphabet: Optional[str] = None) -> str:
"""Create new NeoFS epoch event in the side chain
def force_new_epoch(
self, rpc_endpoint: Optional[str] = None, alphabet: Optional[str] = None
) -> str:
"""
Create new NeoFS epoch event in the side chain
Args:
alphabet (str): path to alphabet wallets dir
rpc_endpoint (str): N3 RPC node endpoint
Returns:
str: Command string
"""
return self._execute(
'morph force-new-epoch',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph force-new-epoch",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def generate_alphabet(self, rpc_endpoint: str, alphabet_wallets: str, size: int = 7) -> str:
"""Generate alphabet wallets for consensus nodes of the morph network
"""
Generate alphabet wallets for consensus nodes of the morph network.
Args:
alphabet_wallets (str): path to alphabet wallets dir
size (int): amount of alphabet wallets to generate (default 7)
rpc_endpoint (str): N3 RPC node endpoint
Returns:
str: Command string
"""
return self._execute(
'morph generate-alphabet',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph generate-alphabet",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def generate_storage_wallet(self, rpc_endpoint: str, alphabet_wallets: str, storage_wallet: str,
initial_gas: Optional[str] = None) -> str:
"""Generate storage node wallet for the morph network
def generate_storage_wallet(
self,
rpc_endpoint: str,
alphabet_wallets: str,
storage_wallet: str,
initial_gas: Optional[str] = None,
) -> str:
"""
Generate storage node wallet for the morph network.
Args:
alphabet_wallets (str): path to alphabet wallets dir
@ -143,21 +161,29 @@ class NeofsAdmMorph(NeofsCliCommand):
rpc_endpoint (str): N3 RPC node endpoint
storage_wallet (str): path to new storage node wallet
Returns:
str: Command string
"""
return self._execute(
'morph generate-storage-wallet',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph generate-storage-wallet",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def init(self, rpc_endpoint: str, alphabet_wallets: str, contracts: str, protocol: str,
container_alias_fee: int = 500, container_fee: int = 1000, epoch_duration: int = 240,
homomorphic_disabled: bool = False, local_dump: Optional[str] = None, max_object_size: int = 67108864
) -> str:
"""Section for morph network configuration commands.
def init(
self,
rpc_endpoint: str,
alphabet_wallets: str,
contracts: str,
protocol: str,
container_alias_fee: int = 500,
container_fee: int = 1000,
epoch_duration: int = 240,
homomorphic_disabled: bool = False,
local_dump: Optional[str] = None,
max_object_size: int = 67108864,
) -> str:
"""
Initialize side chain network with smart-contracts and network settings.
Args:
alphabet_wallets (str): path to alphabet wallets dir
@ -172,19 +198,23 @@ class NeofsAdmMorph(NeofsCliCommand):
protocol (str): path to the consensus node configuration
rpc_endpoint (str): N3 RPC node endpoint
Returns:
str: Command string
"""
return self._execute(
'morph init',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph init",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def refill_gas(self, rpc_endpoint: str, alphabet_wallets: str, storage_wallet: str, gas: Optional[str] = None
) -> str:
"""Refill GAS of storage node's wallet in the morph network
def refill_gas(
self,
rpc_endpoint: str,
alphabet_wallets: str,
storage_wallet: str,
gas: Optional[str] = None,
) -> str:
"""
Refill GAS of storage node's wallet in the morph network.
Args:
alphabet_wallets (str): path to alphabet wallets dir
@ -192,18 +222,19 @@ class NeofsAdmMorph(NeofsCliCommand):
rpc_endpoint (str): N3 RPC node endpoint
storage_wallet (str): path to new storage node wallet
Returns:
str: Command string
"""
return self._execute(
'morph refill-gas',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph refill-gas",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def restore_containers(self, rpc_endpoint: str, alphabet_wallets: str, cid: str, dump: str) -> str:
"""Restore NeoFS containers from file.
def restore_containers(
self, rpc_endpoint: str, alphabet_wallets: str, cid: str, dump: str
) -> str:
"""
Restore NeoFS containers from file.
Args:
alphabet_wallets (str): path to alphabet wallets dir
@ -211,19 +242,24 @@ class NeofsAdmMorph(NeofsCliCommand):
dump (str): file to restore containers from
rpc_endpoint (str): N3 RPC node endpoint
Returns:
str: Command string
"""
return self._execute(
'morph restore-containers',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph restore-containers",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def set_policy(self, rpc_endpoint: str, alphabet_wallets: str, exec_fee_factor: Optional[int] = None,
storage_price: Optional[int] = None, fee_per_byte: Optional[int] = None) -> str:
"""Set global policy values
def set_policy(
self,
rpc_endpoint: str,
alphabet_wallets: str,
exec_fee_factor: Optional[int] = None,
storage_price: Optional[int] = None,
fee_per_byte: Optional[int] = None,
) -> str:
"""
Set global policy values.
Args:
alphabet_wallets (str): path to alphabet wallets dir
@ -232,28 +268,30 @@ class NeofsAdmMorph(NeofsCliCommand):
fee_per_byte (int): FeePerByte=<n3>
rpc_endpoint (str): N3 RPC node endpoint
Returns:
str: Command string
"""
non_param_attribute = ''
non_param_attribute = ""
if exec_fee_factor:
non_param_attribute += f'ExecFeeFactor={exec_fee_factor} '
non_param_attribute += f"ExecFeeFactor={exec_fee_factor} "
if storage_price:
non_param_attribute += f'StoragePrice={storage_price} '
non_param_attribute += f"StoragePrice={storage_price} "
if fee_per_byte:
non_param_attribute += f'FeePerByte={fee_per_byte} '
non_param_attribute += f"FeePerByte={fee_per_byte} "
return self._execute(
f'morph restore-containers {non_param_attribute}',
**{param: param_value for param, param_value in locals().items() if param not in [
'self', 'exec_fee_factor', 'storage_price', 'fee_per_byte'
]}
f"morph restore-containers {non_param_attribute}",
**{
param: value
for param, value in locals().items()
if param not in ["self", "exec_fee_factor", "storage_price", "fee_per_byte"]
},
)
def update_contracts(self, rpc_endpoint: str, alphabet_wallets: str, contracts: Optional[str] = None
) -> str:
"""Update NeoFS contracts.
def update_contracts(
self, rpc_endpoint: str, alphabet_wallets: str, contracts: Optional[str] = None
) -> str:
"""
Update NeoFS contracts.
Args:
alphabet_wallets (str): path to alphabet wallets dir
@ -261,12 +299,10 @@ class NeofsAdmMorph(NeofsCliCommand):
(default fetched from latest github release)
rpc_endpoint (str): N3 RPC node endpoint
Returns:
str: Command string
"""
return self._execute(
'morph update-contracts',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph update-contracts",
**{param: value for param, value in locals().items() if param not in ["self"]},
)

View file

@ -15,6 +15,6 @@ class NeofsAdmStorageConfig(NeofsCliCommand):
"""
return self._execute(
'storage-config',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"storage-config",
**{param: value for param, value in locals().items() if param not in ["self"]},
)

View file

@ -19,29 +19,31 @@ class NeofsAdmMorphSubnet(NeofsCliCommand):
"""
return self._execute(
'morph subnet create',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph subnet create",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def get(self, rpc_endpoint: str, subnet: str) -> str:
"""Read information about the NeoFS subnet.
"""
Read information about the NeoFS subnet.
Args:
rpc_endpoint (str): N3 RPC node endpoint
subnet (str): ID of the subnet to read
Returns:
str: Command string
"""
return self._execute(
'morph subnet get',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph subnet get",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def remove(self, rpc_endpoint: str, wallet: str, subnet: str, address: Optional[str] = None) -> str:
"""Remove NeoFS subnet.
def remove(
self, rpc_endpoint: str, wallet: str, subnet: str, address: Optional[str] = None
) -> str:
"""
Remove NeoFS subnet.
Args:
address (str): Address in the wallet, optional
@ -49,19 +51,26 @@ class NeofsAdmMorphSubnet(NeofsCliCommand):
subnet (str): ID of the subnet to read
wallet (str): Path to file with wallet
Returns:
str: Command string
"""
return self._execute(
'morph subnet remove',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph subnet remove",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def admin_add(self, rpc_endpoint: str, wallet: str, admin: str, subnet: str, client: Optional[str] = None,
group: Optional[str] = None, address: Optional[str] = None) -> str:
"""Add admin to the NeoFS subnet.
def admin_add(
self,
rpc_endpoint: str,
wallet: str,
admin: str,
subnet: str,
client: Optional[str] = None,
group: Optional[str] = None,
address: Optional[str] = None,
) -> str:
"""
Add admin to the NeoFS subnet.
Args:
address (str): Address in the wallet, optional
@ -72,19 +81,25 @@ class NeofsAdmMorphSubnet(NeofsCliCommand):
subnet (str): ID of the subnet to read
wallet (str): Path to file with wallet
Returns:
str: Command string
"""
return self._execute(
'morph subnet admin add',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph subnet admin add",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def admin_remove(self, rpc_endpoint: str, wallet: str, admin: str, subnet: str, client: Optional[str] = None,
address: Optional[str] = None) -> str:
"""Remove admin of the NeoFS subnet.
def admin_remove(
self,
rpc_endpoint: str,
wallet: str,
admin: str,
subnet: str,
client: Optional[str] = None,
address: Optional[str] = None,
) -> str:
"""
Remove admin of the NeoFS subnet.
Args:
address (str): Address in the wallet, optional
@ -94,19 +109,25 @@ class NeofsAdmMorphSubnet(NeofsCliCommand):
subnet (str): ID of the subnet to read
wallet (str): Path to file with wallet
Returns:
str: Command string
"""
return self._execute(
'morph subnet admin remove',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph subnet admin remove",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def client_add(self, rpc_endpoint: str, wallet: str, subnet: str, client: Optional[str] = None,
group: Optional[str] = None, address: Optional[str] = None) -> str:
"""Add client to the NeoFS subnet.
def client_add(
self,
rpc_endpoint: str,
wallet: str,
subnet: str,
client: Optional[str] = None,
group: Optional[str] = None,
address: Optional[str] = None,
) -> str:
"""
Add client to the NeoFS subnet.
Args:
address (str): Address in the wallet, optional
@ -116,19 +137,25 @@ class NeofsAdmMorphSubnet(NeofsCliCommand):
subnet (str): ID of the subnet to read
wallet (str): Path to file with wallet
Returns:
str: Command string
"""
return self._execute(
'morph subnet client add',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph subnet client add",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def client_remove(self, rpc_endpoint: str, wallet: str, client: str, group: str, subnet: str,
address: Optional[str] = None) -> str:
"""Remove client of the NeoFS subnet.
def client_remove(
self,
rpc_endpoint: str,
wallet: str,
client: str,
group: str,
subnet: str,
address: Optional[str] = None,
) -> str:
"""
Remove client of the NeoFS subnet.
Args:
address (str): Address in the wallet, optional
@ -138,18 +165,17 @@ class NeofsAdmMorphSubnet(NeofsCliCommand):
subnet (str): ID of the subnet to read
wallet (str): Path to file with wallet
Returns:
str: Command string
"""
return self._execute(
'morph subnet client remove',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph subnet client remove",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def node_add(self, rpc_endpoint: str, wallet: str, node: str, subnet: str) -> str:
"""Add node to the NeoFS subnet.
"""
Add node to the NeoFS subnet.
Args:
node (str): Hex-encoded public key of the node
@ -157,18 +183,17 @@ class NeofsAdmMorphSubnet(NeofsCliCommand):
subnet (str): ID of the subnet to read
wallet (str): Path to file with wallet
Returns:
str: Command string
"""
return self._execute(
'morph subnet node add',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph subnet node add",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def node_remove(self, rpc_endpoint: str, wallet: str, node: str, subnet: str) -> str:
"""Remove node from the NeoFS subnet.
"""
Remove node from the NeoFS subnet.
Args:
node (str): Hex-encoded public key of the node
@ -176,12 +201,10 @@ class NeofsAdmMorphSubnet(NeofsCliCommand):
subnet (str): ID of the subnet to read
wallet (str): Path to file with wallet
Returns:
str: Command string
"""
return self._execute(
'morph subnet node remove',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"morph subnet node remove",
**{param: value for param, value in locals().items() if param not in ["self"]},
)

View file

@ -9,4 +9,4 @@ class NeofsAdmVersion(NeofsCliCommand):
str: Command string
"""
return self._execute('', version=True)
return self._execute("", version=True)

View file

@ -25,9 +25,5 @@ class NeofsCliAccounting(NeofsCliCommand):
"""
return self._execute(
"accounting balance",
**{
param: param_value
for param, param_value in locals().items()
if param not in ["self"]
}
**{param: value for param, value in locals().items() if param not in ["self"]},
)

View file

@ -4,7 +4,9 @@ from cli_utils.cli_command import NeofsCliCommand
class NeofsCliACL(NeofsCliCommand):
def extended_create(self, cid: str, out: str, file: Optional[str] = None, rule: Optional[list] = None) -> str:
def extended_create(
self, cid: str, out: str, file: Optional[str] = None, rule: Optional[list] = None
) -> str:
"""Create extended ACL from the text representation.
@ -42,6 +44,6 @@ class NeofsCliACL(NeofsCliCommand):
"""
return self._execute(
'acl extended create',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"acl extended create",
**{param: value for param, value in locals().items() if param not in ["self"]},
)

View file

@ -4,12 +4,25 @@ from cli_utils.cli_command import NeofsCliCommand
class NeofsCliContainer(NeofsCliCommand):
def create(self, rpc_endpoint: str, wallet: str, address: Optional[str] = None, attributes: Optional[dict] = None,
basic_acl: Optional[str] = None, await_mode: bool = False, disable_timestamp: bool = False,
name: Optional[str] = None, nonce: Optional[str] = None, policy: Optional[str] = None,
session: Optional[str] = None, subnet: Optional[str] = None, ttl: Optional[int] = None,
xhdr: Optional[dict] = None) -> str:
"""Create a new container and register it in the NeoFS.
def create(
self,
rpc_endpoint: str,
wallet: str,
address: Optional[str] = None,
attributes: Optional[dict] = None,
basic_acl: Optional[str] = None,
await_mode: bool = False,
disable_timestamp: bool = False,
name: Optional[str] = None,
nonce: Optional[str] = None,
policy: Optional[str] = None,
session: Optional[str] = None,
subnet: Optional[str] = None,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
Create a new container and register it in the NeoFS.
It will be stored in the sidechain when the Inner Ring accepts it.
Args:
@ -31,17 +44,26 @@ class NeofsCliContainer(NeofsCliCommand):
Returns:
str: Command string
"""
return self._execute(
'container create',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"container create",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def delete(self, rpc_endpoint: str, wallet: 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) -> str:
"""Delete an existing container.
def delete(
self,
rpc_endpoint: str,
wallet: 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,
) -> str:
"""
Delete an existing container.
Only the owner of the container has permission to remove the container.
Args:
@ -55,20 +77,29 @@ class NeofsCliContainer(NeofsCliCommand):
wallet: WIF (NEP-2) string or path to the wallet or binary key
xhdr: Request X-Headers in form of Key=Value
Returns:
str: Command string
"""
return self._execute(
'container delete',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"container delete",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def get(self, rpc_endpoint: str, wallet: str, cid: str, address: Optional[str] = None, await_mode: bool = False,
to: Optional[str] = None, json_mode: bool = False, ttl: Optional[int] = None,
xhdr: Optional[dict] = None) -> str:
"""Get container field info
def get(
self,
rpc_endpoint: str,
wallet: str,
cid: str,
address: Optional[str] = None,
await_mode: bool = False,
to: Optional[str] = None,
json_mode: bool = False,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
Get container field info.
Args:
address: address of wallet account
@ -83,18 +114,26 @@ class NeofsCliContainer(NeofsCliCommand):
Returns:
str: Command string
"""
return self._execute(
'container get',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"container get",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def get_eacl(self, rpc_endpoint: str, wallet: str, cid: str, address: Optional[str] = None,
await_mode: bool = False, to: Optional[str] = None, session: Optional[str] = None,
ttl: Optional[int] = None, xhdr: Optional[dict] = None) -> str:
"""Get extended ACL talbe of container
def get_eacl(
self,
rpc_endpoint: str,
wallet: str,
cid: str,
address: Optional[str] = None,
await_mode: bool = False,
to: Optional[str] = None,
session: Optional[str] = None,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
Get extended ACL table of container.
Args:
address: address of wallet account
@ -112,13 +151,22 @@ class NeofsCliContainer(NeofsCliCommand):
"""
return self._execute(
'container get-eacl',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"container get-eacl",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def list(self, rpc_endpoint: str, wallet: str, address: Optional[str] = None,
owner: Optional[str] = None, ttl: Optional[int] = None, xhdr: Optional[dict] = None, **params) -> str:
"""List all created containers
def list(
self,
rpc_endpoint: str,
wallet: str,
address: Optional[str] = None,
owner: Optional[str] = None,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
**params,
) -> str:
"""
List all created containers.
Args:
address: address of wallet account
@ -130,16 +178,23 @@ class NeofsCliContainer(NeofsCliCommand):
Returns:
str: Command string
"""
return self._execute(
'container list',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"container list",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def list_objects(self, rpc_endpoint: str, wallet: str, cid: str, address: Optional[str] = None,
ttl: Optional[int] = None, xhdr: Optional[dict] = None) -> str:
"""List existing objects in container
def list_objects(
self,
rpc_endpoint: str,
wallet: str,
cid: str,
address: Optional[str] = None,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
List existing objects in container.
Args:
address: address of wallet account
@ -151,18 +206,26 @@ class NeofsCliContainer(NeofsCliCommand):
Returns:
str: Command string
"""
return self._execute(
'container list-objects',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"container list-objects",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def set_eacl(self, rpc_endpoint: str, wallet: str, cid: str, address: Optional[str] = None,
await_mode: bool = False, table: Optional[str] = None, session: Optional[str] = None,
ttl: Optional[int] = None, xhdr: Optional[dict] = None) -> str:
"""Set a new extended ACL table for the container.
def set_eacl(
self,
rpc_endpoint: str,
wallet: str,
cid: str,
address: Optional[str] = None,
await_mode: bool = False,
table: Optional[str] = None,
session: Optional[str] = None,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
Set a new extended ACL table for the container.
Container ID in the EACL table will be substituted with the ID from the CLI.
Args:
@ -178,9 +241,8 @@ class NeofsCliContainer(NeofsCliCommand):
Returns:
str: Command string
"""
return self._execute(
'container set-eacl',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"container set-eacl",
**{param: value for param, value in locals().items() if param not in ["self"]},
)

View file

@ -4,10 +4,20 @@ from cli_utils.cli_command import NeofsCliCommand
class NeofsCliObject(NeofsCliCommand):
def delete(self, rpc_endpoint: str, wallet: str, cid: str, oid: str, address: Optional[str] = None,
bearer: Optional[str] = None, session: Optional[str] = None, ttl: Optional[int] = None,
xhdr: Optional[dict] = None) -> str:
"""Delete object from NeoFS
def delete(
self,
rpc_endpoint: str,
wallet: str,
cid: str,
oid: str,
address: Optional[str] = None,
bearer: Optional[str] = None,
session: Optional[str] = None,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
Delete object from NeoFS.
Args:
address: address of wallet account
@ -22,18 +32,30 @@ class NeofsCliObject(NeofsCliCommand):
Returns:
str: Command string
"""
return self._execute(
'object delete',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"object delete",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def get(self, rpc_endpoint: str, wallet: str, cid: str, oid: str, address: Optional[str] = None,
bearer: Optional[str] = None, file: Optional[str] = None,
header: Optional[str] = None, no_progress: bool = False, raw: bool = False,
session: Optional[str] = None, ttl: Optional[int] = None, xhdr: Optional[dict] = None) -> str:
"""Get object from NeoFS
def get(
self,
rpc_endpoint: str,
wallet: str,
cid: str,
oid: str,
address: Optional[str] = None,
bearer: Optional[str] = None,
file: Optional[str] = None,
header: Optional[str] = None,
no_progress: bool = False,
raw: bool = False,
session: Optional[str] = None,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
Get object from NeoFS.
Args:
address: address of wallet account
@ -52,17 +74,28 @@ class NeofsCliObject(NeofsCliCommand):
Returns:
str: Command string
"""
return self._execute(
'object get',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"object get",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def hash(self, rpc_endpoint: str, wallet: str, cid: str, oid: str, address: Optional[str] = None,
bearer: Optional[str] = None, range: Optional[str] = None, salt: Optional[str] = None,
ttl: Optional[int] = None, hash_type: Optional[str] = None, xhdr: Optional[dict] = None) -> str:
"""Get object hash
def hash(
self,
rpc_endpoint: str,
wallet: str,
cid: str,
oid: str,
address: Optional[str] = None,
bearer: Optional[str] = None,
range: Optional[str] = None,
salt: Optional[str] = None,
ttl: Optional[int] = None,
hash_type: Optional[str] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
Get object hash.
Args:
address: address of wallet account
@ -79,78 +112,114 @@ class NeofsCliObject(NeofsCliCommand):
Returns:
str: Command string
"""
return self._execute(
'object hash',
**{param: param_value for param, param_value in locals().items() if param not in ['self', 'params']}
"object hash",
**{
param: value for param, value in locals().items() if param not in ["self", "params"]
},
)
def head(self, rpc_endpoint: str, wallet: str, cid: str, oid: str, address: Optional[str] = None,
bearer: Optional[str] = None, file: Optional[str] = None,
json_mode: bool = False, main_only: bool = False, proto: bool = False, raw: bool = False,
session: Optional[str] = None, ttl: Optional[int] = None, xhdr: Optional[dict] = None) -> str:
"""Get object header
def head(
self,
rpc_endpoint: str,
wallet: str,
cid: str,
oid: str,
address: Optional[str] = None,
bearer: Optional[str] = None,
file: Optional[str] = None,
json_mode: bool = False,
main_only: bool = False,
proto: bool = False,
raw: bool = False,
session: Optional[str] = None,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
Get object header.
Args:
address: address of wallet account
bearer: File with signed JSON or binary encoded bearer token
cid: Container ID
file: File to write object payload to. Default: stdout.
json_mode: Marshal output in JSON
main_only: Return only main fields
oid: Object ID
proto: Marshal output in Protobuf
raw: Set raw request option
rpc_endpoint: remote node address (as 'multiaddr' or '<host>:<port>')
session: path to a JSON-encoded container session token
ttl: TTL value in request meta header (default 2)
wallet: WIF (NEP-2) string or path to the wallet or binary key
xhdr: Request X-Headers in form of Key=Value
Args:
address: address of wallet account
bearer: File with signed JSON or binary encoded bearer token
cid: Container ID
file: File to write object payload to. Default: stdout.
json_mode: Marshal output in JSON
main_only: Return only main fields
oid: Object ID
proto: Marshal output in Protobuf
raw: Set raw request option
rpc_endpoint: remote node address (as 'multiaddr' or '<host>:<port>')
session: path to a JSON-encoded container session token
ttl: TTL value in request meta header (default 2)
wallet: WIF (NEP-2) string or path to the wallet or binary key
xhdr: Request X-Headers in form of Key=Value
Returns:
str: Command string
"""
Returns:
str: Command string
"""
return self._execute(
'object head',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"object head",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def lock(self, rpc_endpoint: str, wallet: str, cid: str, oid: str, lifetime: int, address: Optional[str] = None,
bearer: Optional[str] = None, session: Optional[str] = None, ttl: Optional[int] = None,
xhdr: Optional[dict] = None) -> str:
"""Lock object in container
def lock(
self,
rpc_endpoint: str,
wallet: str,
cid: str,
oid: str,
lifetime: int,
address: Optional[str] = None,
bearer: Optional[str] = None,
session: Optional[str] = None,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
Lock object in container.
Args:
address: address of wallet account
bearer: File with signed JSON or binary encoded bearer token
cid: Container ID
oid: Object ID
lifetime: Object lifetime
rpc_endpoint: remote node address (as 'multiaddr' or '<host>:<port>')
session: path to a JSON-encoded container session token
ttl: TTL value in request meta header (default 2)
wallet: WIF (NEP-2) string or path to the wallet or binary key
xhdr: Request X-Headers in form of Key=Value
Args:
address: address of wallet account
bearer: File with signed JSON or binary encoded bearer token
cid: Container ID
oid: Object ID
lifetime: Object lifetime
rpc_endpoint: remote node address (as 'multiaddr' or '<host>:<port>')
session: path to a JSON-encoded container session token
ttl: TTL value in request meta header (default 2)
wallet: WIF (NEP-2) string or path to the wallet or binary key
xhdr: Request X-Headers in form of Key=Value
Returns:
str: Command string
"""
Returns:
str: Command string
"""
return self._execute(
'object lock',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"object lock",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def put(self, rpc_endpoint: str, wallet: str, cid: str, file: str, address: Optional[str] = None,
attributes: Optional[dict] = None, bearer: Optional[str] = None, disable_filename: bool = False,
disable_timestamp: bool = False, expire_at: Optional[int] = None, no_progress: bool = False,
notify: Optional[str] = None, session: Optional[str] = None, ttl: Optional[int] = None,
xhdr: Optional[dict] = None) -> str:
"""Put object to NeoFS
def put(
self,
rpc_endpoint: str,
wallet: str,
cid: str,
file: str,
address: Optional[str] = None,
attributes: Optional[dict] = None,
bearer: Optional[str] = None,
disable_filename: bool = False,
disable_timestamp: bool = False,
expire_at: Optional[int] = None,
no_progress: bool = False,
notify: Optional[str] = None,
session: Optional[str] = None,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
Put object to NeoFS.
Args:
address: address of wallet account
@ -171,69 +240,90 @@ class NeofsCliObject(NeofsCliCommand):
Returns:
str: Command string
"""
return self._execute(
'object put',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"object put",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def range(self, rpc_endpoint: str, wallet: str, cid: str, oid: str, range: str, address: Optional[str] = None,
bearer: Optional[str] = None, file: Optional[str] = None, json_mode: bool = False, raw: bool = False,
session: Optional[str] = None, ttl: Optional[int] = None, xhdr: Optional[dict] = None) -> str:
"""Get payload range data of an object
def range(
self,
rpc_endpoint: str,
wallet: str,
cid: str,
oid: str,
range: str,
address: Optional[str] = None,
bearer: Optional[str] = None,
file: Optional[str] = None,
json_mode: bool = False,
raw: bool = False,
session: Optional[str] = None,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
Get payload range data of an object.
Args:
address: address of wallet account
bearer: File with signed JSON or binary encoded bearer token
cid: Container ID
file: File to write object payload to. Default: stdout.
json_mode: Marshal output in JSON
oid: Object ID
range: Range to take data from in the form offset:length
raw: Set raw request option
rpc_endpoint: remote node address (as 'multiaddr' or '<host>:<port>')
session: path to a JSON-encoded container session token
ttl: TTL value in request meta header (default 2)
wallet: WIF (NEP-2) string or path to the wallet or binary key
xhdr: Request X-Headers in form of Key=Value
Args:
address: address of wallet account
bearer: File with signed JSON or binary encoded bearer token
cid: Container ID
file: File to write object payload to. Default: stdout.
json_mode: Marshal output in JSON
oid: Object ID
range: Range to take data from in the form offset:length
raw: Set raw request option
rpc_endpoint: remote node address (as 'multiaddr' or '<host>:<port>')
session: path to a JSON-encoded container session token
ttl: TTL value in request meta header (default 2)
wallet: WIF (NEP-2) string or path to the wallet or binary key
xhdr: Request X-Headers in form of Key=Value
Returns:
str: Command string
"""
Returns:
str: Command string
"""
return self._execute(
'object range',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"object range",
**{param: value for param, value in locals().items() if param not in ["self"]},
)
def search(self, rpc_endpoint: str, wallet: str, cid: str, address: Optional[str] = None,
bearer: Optional[str] = None, filters: Optional[list] = None, oid: Optional[str] = None,
phy: bool = False, root: bool = False, session: Optional[str] = None, ttl: Optional[int] = None,
xhdr: Optional[dict] = None) -> str:
"""Search object
def search(
self,
rpc_endpoint: str,
wallet: str,
cid: str,
address: Optional[str] = None,
bearer: Optional[str] = None,
filters: Optional[list] = None,
oid: Optional[str] = None,
phy: bool = False,
root: bool = False,
session: Optional[str] = None,
ttl: Optional[int] = None,
xhdr: Optional[dict] = None,
) -> str:
"""
Search object.
Args:
address: address of wallet account
bearer: File with signed JSON or binary encoded bearer token
cid: Container ID
filters: Repeated filter expressions or files with protobuf JSON
oid: Object ID
phy: Search physically stored objects
root: Search for user objects
rpc_endpoint: remote node address (as 'multiaddr' or '<host>:<port>')
session: path to a JSON-encoded container session token
ttl: TTL value in request meta header (default 2)
wallet: WIF (NEP-2) string or path to the wallet or binary key
xhdr: Request X-Headers in form of Key=Value
Args:
address: address of wallet account
bearer: File with signed JSON or binary encoded bearer token
cid: Container ID
filters: Repeated filter expressions or files with protobuf JSON
oid: Object ID
phy: Search physically stored objects
root: Search for user objects
rpc_endpoint: remote node address (as 'multiaddr' or '<host>:<port>')
session: path to a JSON-encoded container session token
ttl: TTL value in request meta header (default 2)
wallet: WIF (NEP-2) string or path to the wallet or binary key
xhdr: Request X-Headers in form of Key=Value
Returns:
str: Command string
"""
Returns:
str: Command string
"""
return self._execute(
'object search',
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
"object search",
**{param: value for param, value in locals().items() if param not in ["self"]},
)

View file

@ -3,10 +3,10 @@ from cli_utils.cli_command import NeofsCliCommand
class NeofsCliVersion(NeofsCliCommand):
def get(self) -> str:
"""Application version and NeoFS API compatibility
"""
Application version and NeoFS API compatibility.
Returns:
str: Command string
"""
return self._execute('', version=True)
return self._execute("", version=True)

View file

@ -7,31 +7,40 @@ class NeofsCliCommand:
neofs_cli_exec: Optional[str] = None
timeout: Optional[int] = None
__base_params: Optional[str] = None
map_params = {'json_mode': 'json', 'await_mode': 'await', 'hash_type': 'hash', 'doc_type': 'type'}
map_params = {
"json_mode": "json",
"await_mode": "await",
"hash_type": "hash",
"doc_type": "type",
}
def __init__(self, neofs_cli_exec: str, timeout: int, **base_params):
self.neofs_cli_exec = neofs_cli_exec
self.timeout = timeout
self.__base_params = ' '.join([f'--{param} {value}' for param, value in base_params.items() if value])
self.__base_params = " ".join(
[f"--{param} {value}" for param, value in base_params.items() if value]
)
def _format_command(self, command: str, **params) -> str:
param_str = []
for param, value in params.items():
if param in self.map_params.keys():
param = self.map_params[param]
param = param.replace('_', '-')
param = param.replace("_", "-")
if not value:
continue
if isinstance(value, bool):
param_str.append(f'--{param}')
param_str.append(f"--{param}")
elif isinstance(value, int):
param_str.append(f'--{param} {value}')
param_str.append(f"--{param} {value}")
elif isinstance(value, list):
for value_item in value:
val_str = str(value_item).replace("'", "\\'")
param_str.append(f"--{param} '{val_str}'")
elif isinstance(value, dict):
param_str.append(f'--{param} \'{",".join(f"{key}={val}" for key, val in value.items())}\'')
param_str.append(
f"--{param} '{','.join(f'{key}={val}' for key, val in value.items())}'"
)
else:
if "'" in str(value):
value_str = str(value).replace('"', '\\"')
@ -39,7 +48,7 @@ class NeofsCliCommand:
else:
param_str.append(f"--{param} '{value}'")
param_str = ' '.join(param_str)
param_str = " ".join(param_str)
return f'{self.neofs_cli_exec} {self.__base_params} {command or ""} {param_str}'

View file

@ -1,13 +1,26 @@
from typing import List, Optional
from acl import EACLOperation
from python_keywords.object_access import (can_get_object, can_put_object, can_delete_object, can_get_head_object,
can_get_range_hash_of_object, can_get_range_of_object, can_search_object)
from python_keywords.object_access import (
can_delete_object,
can_get_head_object,
can_get_object,
can_get_range_hash_of_object,
can_get_range_of_object,
can_put_object,
can_search_object,
)
def check_full_access_to_container(wallet: str, cid: str, oid: str, file_name: str,
bearer: Optional[str] = None, wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None):
def check_full_access_to_container(
wallet: str,
cid: str,
oid: str,
file_name: str,
bearer: Optional[str] = None,
wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None,
):
assert can_put_object(wallet, cid, file_name, bearer, wallet_config, xhdr)
assert can_get_head_object(wallet, cid, oid, bearer, wallet_config, xhdr)
assert can_get_range_of_object(wallet, cid, oid, bearer, wallet_config, xhdr)
@ -17,9 +30,15 @@ def check_full_access_to_container(wallet: str, cid: str, oid: str, file_name: s
assert can_delete_object(wallet, cid, oid, bearer, wallet_config, xhdr)
def check_no_access_to_container(wallet: str, cid: str, oid: str, file_name: str,
bearer: Optional[str] = None, wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None):
def check_no_access_to_container(
wallet: str,
cid: str,
oid: str,
file_name: str,
bearer: Optional[str] = None,
wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None,
):
assert not can_put_object(wallet, cid, file_name, bearer, wallet_config, xhdr)
assert not can_get_head_object(wallet, cid, oid, bearer, wallet_config, xhdr)
assert not can_get_range_of_object(wallet, cid, oid, bearer, wallet_config, xhdr)
@ -29,42 +48,78 @@ def check_no_access_to_container(wallet: str, cid: str, oid: str, file_name: str
assert not can_delete_object(wallet, cid, oid, bearer, wallet_config, xhdr)
def check_custom_access_to_container(wallet: str, cid: str, oid: str, file_name: str,
deny_operations: Optional[List[EACLOperation]] = None,
ignore_operations: Optional[List[EACLOperation]] = None,
bearer: Optional[str] = None, wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None):
def check_custom_access_to_container(
wallet: str,
cid: str,
oid: str,
file_name: str,
deny_operations: Optional[List[EACLOperation]] = None,
ignore_operations: Optional[List[EACLOperation]] = None,
bearer: Optional[str] = None,
wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None,
):
deny_operations = [op.value for op in deny_operations or []]
ignore_operations = [op.value for op in ignore_operations or []]
checks: dict = {}
if EACLOperation.PUT.value not in ignore_operations:
checks[EACLOperation.PUT.value] = can_put_object(wallet, cid, file_name, bearer, wallet_config, xhdr)
checks[EACLOperation.PUT.value] = can_put_object(
wallet, cid, file_name, bearer, wallet_config, xhdr
)
if EACLOperation.HEAD.value not in ignore_operations:
checks[EACLOperation.HEAD.value] = can_get_head_object(wallet, cid, oid, bearer, wallet_config, xhdr)
checks[EACLOperation.HEAD.value] = can_get_head_object(
wallet, cid, oid, bearer, wallet_config, xhdr
)
if EACLOperation.GET_RANGE.value not in ignore_operations:
checks[EACLOperation.GET_RANGE.value] = can_get_range_of_object(wallet, cid, oid, bearer, wallet_config, xhdr)
checks[EACLOperation.GET_RANGE.value] = can_get_range_of_object(
wallet, cid, oid, bearer, wallet_config, xhdr
)
if EACLOperation.GET_RANGE_HASH.value not in ignore_operations:
checks[EACLOperation.GET_RANGE_HASH.value] = can_get_range_hash_of_object(wallet, cid, oid, bearer,
wallet_config, xhdr)
checks[EACLOperation.GET_RANGE_HASH.value] = can_get_range_hash_of_object(
wallet, cid, oid, bearer, wallet_config, xhdr
)
if EACLOperation.SEARCH.value not in ignore_operations:
checks[EACLOperation.SEARCH.value] = can_search_object(wallet, cid, oid, bearer, wallet_config, xhdr)
checks[EACLOperation.SEARCH.value] = can_search_object(
wallet, cid, oid, bearer, wallet_config, xhdr
)
if EACLOperation.GET.value not in ignore_operations:
checks[EACLOperation.GET.value] = can_get_object(wallet, cid, oid, file_name, bearer, wallet_config, xhdr)
checks[EACLOperation.GET.value] = can_get_object(
wallet, cid, oid, file_name, bearer, wallet_config, xhdr
)
if EACLOperation.DELETE.value not in ignore_operations:
checks[EACLOperation.DELETE.value] = can_delete_object(wallet, cid, oid, bearer, wallet_config, xhdr)
checks[EACLOperation.DELETE.value] = can_delete_object(
wallet, cid, oid, bearer, wallet_config, xhdr
)
failed_checks = (
[f'allowed {action} failed' for action, success in checks.items() if
not success and action not in deny_operations] +
[f'denied {action} succeeded' for action, success in checks.items() if
success and action in deny_operations])
failed_checks = [
f"allowed {action} failed"
for action, success in checks.items()
if not success and action not in deny_operations
] + [
f"denied {action} succeeded"
for action, success in checks.items()
if success and action in deny_operations
]
assert not failed_checks, ", ".join(failed_checks)
def check_read_only_container(wallet: str, cid: str, oid: str, file_name: str,
bearer: Optional[str] = None, wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None):
return check_custom_access_to_container(wallet, cid, oid, file_name,
deny_operations=[EACLOperation.PUT, EACLOperation.DELETE],
bearer=bearer, wallet_config=wallet_config, xhdr=xhdr)
def check_read_only_container(
wallet: str,
cid: str,
oid: str,
file_name: str,
bearer: Optional[str] = None,
wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None,
):
return check_custom_access_to_container(
wallet,
cid,
oid,
file_name,
deny_operations=[EACLOperation.PUT, EACLOperation.DELETE],
bearer=bearer,
wallet_config=wallet_config,
xhdr=xhdr,
)

View file

@ -3,17 +3,21 @@ from time import sleep
from typing import Optional
import allure
from common import NEOFS_NETMAP_DICT
from python_keywords.node_management import node_healthcheck
from storage_policy import get_nodes_with_object
logger = logging.getLogger('NeoLogger')
logger = logging.getLogger("NeoLogger")
@allure.step('Wait for object replication')
def wait_object_replication_on_nodes(wallet: str, cid: str, oid: str, expected_copies: int,
excluded_nodes: Optional[list[str]] = None) -> list[str]:
@allure.step("Wait for object replication")
def wait_object_replication_on_nodes(
wallet: str,
cid: str,
oid: str,
expected_copies: int,
excluded_nodes: Optional[list[str]] = None,
) -> list[str]:
excluded_nodes = excluded_nodes or []
sleep_interval, attempts = 10, 18
nodes = []
@ -22,28 +26,30 @@ def wait_object_replication_on_nodes(wallet: str, cid: str, oid: str, expected_c
if len(nodes) == expected_copies:
return nodes
sleep(sleep_interval)
raise AssertionError(f'Expected {expected_copies} copies of object, but found {len(nodes)}. '
f'Waiting time {sleep_interval * attempts}')
raise AssertionError(
f"Expected {expected_copies} copies of object, but found {len(nodes)}. "
f"Waiting time {sleep_interval * attempts}"
)
@allure.step('Wait for storage node returned to cluster')
@allure.step("Wait for storage node returned to cluster")
def wait_all_storage_node_returned():
sleep_interval, attempts = 10, 12
for __attempt in range(attempts):
if is_all_storage_node_returned():
return
sleep(sleep_interval)
raise AssertionError('Storage node(s) is broken')
raise AssertionError("Storage node(s) is broken")
def is_all_storage_node_returned() -> bool:
with allure.step('Run health check for all storage nodes'):
with allure.step("Run health check for all storage nodes"):
for node_name in NEOFS_NETMAP_DICT.keys():
try:
health_check = node_healthcheck(node_name)
except Exception as err:
logger.warning(f'Node healthcheck fails with error {err}')
logger.warning(f"Node healthcheck fails with error {err}")
return False
if health_check.health_status != 'READY' or health_check.network_status != 'ONLINE':
if health_check.health_status != "READY" or health_check.network_status != "ONLINE":
return False
return True

View file

@ -1,99 +1,181 @@
from typing import Optional
import allure
from grpc_responses import OBJECT_ACCESS_DENIED, error_matches_status
from python_keywords.neofs_verbs import (delete_object, get_object, get_range, get_range_hash, head_object, put_object,
search_object)
from python_keywords.neofs_verbs import (
delete_object,
get_object,
get_range,
get_range_hash,
head_object,
put_object,
search_object,
)
from python_keywords.utility_keywords import get_file_hash
OPERATION_ERROR_TYPE = RuntimeError
def can_get_object(wallet: str, cid: str, oid: str, file_name: str, bearer: Optional[str] = None,
wallet_config: Optional[str] = None, xhdr: Optional[dict] = None
) -> bool:
with allure.step('Try get object from container'):
def can_get_object(
wallet: str,
cid: str,
oid: str,
file_name: str,
bearer: Optional[str] = None,
wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None,
) -> bool:
with allure.step("Try get object from container"):
try:
got_file_path = get_object(wallet, cid, oid, bearer_token=bearer, wallet_config=wallet_config, xhdr=xhdr)
got_file_path = get_object(
wallet, cid, oid, bearer_token=bearer, wallet_config=wallet_config, xhdr=xhdr
)
except OPERATION_ERROR_TYPE as err:
assert error_matches_status(err, OBJECT_ACCESS_DENIED), f'Expected {err} to match {OBJECT_ACCESS_DENIED}'
assert error_matches_status(
err, OBJECT_ACCESS_DENIED
), f"Expected {err} to match {OBJECT_ACCESS_DENIED}"
return False
assert get_file_hash(file_name) == get_file_hash(got_file_path)
return True
def can_put_object(wallet: str, cid: str, file_name: str, bearer: Optional[str] = None,
wallet_config: Optional[str] = None, xhdr: Optional[dict] = None, attributes: Optional[dict] = None,
) -> bool:
with allure.step('Try put object to container'):
def can_put_object(
wallet: str,
cid: str,
file_name: str,
bearer: Optional[str] = None,
wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None,
attributes: Optional[dict] = None,
) -> bool:
with allure.step("Try put object to container"):
try:
put_object(wallet, file_name, cid, bearer=bearer, wallet_config=wallet_config, xhdr=xhdr,
attributes=attributes)
put_object(
wallet,
file_name,
cid,
bearer=bearer,
wallet_config=wallet_config,
xhdr=xhdr,
attributes=attributes,
)
except OPERATION_ERROR_TYPE as err:
assert error_matches_status(err, OBJECT_ACCESS_DENIED), f'Expected {err} to match {OBJECT_ACCESS_DENIED}'
assert error_matches_status(
err, OBJECT_ACCESS_DENIED
), f"Expected {err} to match {OBJECT_ACCESS_DENIED}"
return False
return True
def can_delete_object(wallet: str, cid: str, oid: str, bearer: Optional[str] = None,
wallet_config: Optional[str] = None, xhdr: Optional[dict] = None
) -> bool:
with allure.step('Try delete object from container'):
def can_delete_object(
wallet: str,
cid: str,
oid: str,
bearer: Optional[str] = None,
wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None,
) -> bool:
with allure.step("Try delete object from container"):
try:
delete_object(wallet, cid, oid, bearer=bearer, wallet_config=wallet_config, xhdr=xhdr)
except OPERATION_ERROR_TYPE as err:
assert error_matches_status(err, OBJECT_ACCESS_DENIED), f'Expected {err} to match {OBJECT_ACCESS_DENIED}'
assert error_matches_status(
err, OBJECT_ACCESS_DENIED
), f"Expected {err} to match {OBJECT_ACCESS_DENIED}"
return False
return True
def can_get_head_object(wallet: str, cid: str, oid: str, bearer: Optional[str] = None,
wallet_config: Optional[str] = None, xhdr: Optional[dict] = None
) -> bool:
with allure.step('Try get head of object'):
def can_get_head_object(
wallet: str,
cid: str,
oid: str,
bearer: Optional[str] = None,
wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None,
) -> bool:
with allure.step("Try get head of object"):
try:
head_object(wallet, cid, oid, bearer_token=bearer, wallet_config=wallet_config, xhdr=xhdr)
head_object(
wallet, cid, oid, bearer_token=bearer, wallet_config=wallet_config, xhdr=xhdr
)
except OPERATION_ERROR_TYPE as err:
assert error_matches_status(err, OBJECT_ACCESS_DENIED), f'Expected {err} to match {OBJECT_ACCESS_DENIED}'
assert error_matches_status(
err, OBJECT_ACCESS_DENIED
), f"Expected {err} to match {OBJECT_ACCESS_DENIED}"
return False
return True
def can_get_range_of_object(wallet: str, cid: str, oid: str, bearer: Optional[str] = None,
wallet_config: Optional[str] = None, xhdr: Optional[dict] = None
) -> bool:
with allure.step('Try get range of object'):
def can_get_range_of_object(
wallet: str,
cid: str,
oid: str,
bearer: Optional[str] = None,
wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None,
) -> bool:
with allure.step("Try get range of object"):
try:
get_range(wallet, cid, oid, bearer=bearer, range_cut='0:10', wallet_config=wallet_config,
xhdr=xhdr)
get_range(
wallet,
cid,
oid,
bearer=bearer,
range_cut="0:10",
wallet_config=wallet_config,
xhdr=xhdr,
)
except OPERATION_ERROR_TYPE as err:
assert error_matches_status(err, OBJECT_ACCESS_DENIED), f'Expected {err} to match {OBJECT_ACCESS_DENIED}'
assert error_matches_status(
err, OBJECT_ACCESS_DENIED
), f"Expected {err} to match {OBJECT_ACCESS_DENIED}"
return False
return True
def can_get_range_hash_of_object(wallet: str, cid: str, oid: str, bearer: Optional[str] = None,
wallet_config: Optional[str] = None, xhdr: Optional[dict] = None
) -> bool:
with allure.step('Try get range hash of object'):
def can_get_range_hash_of_object(
wallet: str,
cid: str,
oid: str,
bearer: Optional[str] = None,
wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None,
) -> bool:
with allure.step("Try get range hash of object"):
try:
get_range_hash(wallet, cid, oid, bearer_token=bearer, range_cut='0:10', wallet_config=wallet_config,
xhdr=xhdr)
get_range_hash(
wallet,
cid,
oid,
bearer_token=bearer,
range_cut="0:10",
wallet_config=wallet_config,
xhdr=xhdr,
)
except OPERATION_ERROR_TYPE as err:
assert error_matches_status(err, OBJECT_ACCESS_DENIED), f'Expected {err} to match {OBJECT_ACCESS_DENIED}'
assert error_matches_status(
err, OBJECT_ACCESS_DENIED
), f"Expected {err} to match {OBJECT_ACCESS_DENIED}"
return False
return True
def can_search_object(wallet: str, cid: str, oid: Optional[str] = None, bearer: Optional[str] = None,
wallet_config: Optional[str] = None, xhdr: Optional[dict] = None
) -> bool:
with allure.step('Try search object in container'):
def can_search_object(
wallet: str,
cid: str,
oid: Optional[str] = None,
bearer: Optional[str] = None,
wallet_config: Optional[str] = None,
xhdr: Optional[dict] = None,
) -> bool:
with allure.step("Try search object in container"):
try:
oids = search_object(wallet, cid, bearer=bearer, wallet_config=wallet_config, xhdr=xhdr)
except OPERATION_ERROR_TYPE as err:
assert error_matches_status(err, OBJECT_ACCESS_DENIED), f'Expected {err} to match {OBJECT_ACCESS_DENIED}'
assert error_matches_status(
err, OBJECT_ACCESS_DENIED
), f"Expected {err} to match {OBJECT_ACCESS_DENIED}"
return False
if oid:
return oid in oids

View file

@ -6,22 +6,16 @@
"""
import logging
import allure
from cli_helpers import _cmd_run
from common import (
COMPLEX_OBJ_SIZE,
NEOFS_CLI_EXEC,
NEOFS_ENDPOINT,
SIMPLE_OBJ_SIZE,
WALLET_CONFIG,
)
from common import COMPLEX_OBJ_SIZE, NEOFS_CLI_EXEC, NEOFS_ENDPOINT, SIMPLE_OBJ_SIZE, WALLET_CONFIG
from complex_object_actions import get_link_object
from neofs_verbs import head_object
import allure
logger = logging.getLogger("NeoLogger")
@allure.step('Put Storagegroup')
@allure.step("Put Storagegroup")
def put_storagegroup(
wallet: str,
cid: str,
@ -55,7 +49,7 @@ def put_storagegroup(
return oid
@allure.step('List Storagegroup')
@allure.step("List Storagegroup")
def list_storagegroup(
wallet: str, cid: str, bearer_token: str = "", wallet_config: str = WALLET_CONFIG
):
@ -82,7 +76,7 @@ def list_storagegroup(
return found_objects
@allure.step('Get Storagegroup')
@allure.step("Get Storagegroup")
def get_storagegroup(
wallet: str,
cid: str,
@ -128,7 +122,7 @@ def get_storagegroup(
return sg_dict
@allure.step('Delete Storagegroup')
@allure.step("Delete Storagegroup")
def delete_storagegroup(
wallet: str,
cid: str,
@ -159,7 +153,7 @@ def delete_storagegroup(
return tombstone_id
@allure.step('Verify list operation over Storagegroup')
@allure.step("Verify list operation over Storagegroup")
def verify_list_storage_group(
wallet: str,
cid: str,
@ -173,7 +167,7 @@ def verify_list_storage_group(
assert storagegroup in storage_groups
@allure.step('Verify get operation over Storagegroup')
@allure.step("Verify get operation over Storagegroup")
def verify_get_storage_group(
wallet: str,
cid: str,