forked from TrueCloudLab/frostfs-testcases
Implemented neofs-adm lib
Signed-off-by: Vladimir Avdeev <v.avdeev@yadro.com>
This commit is contained in:
parent
b6a451dc8d
commit
f40111dc4a
24 changed files with 662 additions and 28 deletions
|
@ -6,15 +6,15 @@ from datetime import datetime
|
||||||
|
|
||||||
import allure
|
import allure
|
||||||
import pytest
|
import pytest
|
||||||
from robot.api import deco
|
|
||||||
|
|
||||||
import wallet
|
import wallet
|
||||||
from cli_helpers import _cmd_run
|
from cli_helpers import _cmd_run
|
||||||
|
from cli_utils import NeofsAdm, NeofsCli
|
||||||
from common import (ASSETS_DIR, FREE_STORAGE, INFRASTRUCTURE_TYPE, MAINNET_WALLET_PATH,
|
from common import (ASSETS_DIR, FREE_STORAGE, INFRASTRUCTURE_TYPE, MAINNET_WALLET_PATH,
|
||||||
NEOFS_NETMAP_DICT)
|
NEOFS_NETMAP_DICT)
|
||||||
from env_properties import save_env_properties
|
from env_properties import save_env_properties
|
||||||
from payment_neogo import neofs_deposit, transfer_mainnet_gas
|
from payment_neogo import neofs_deposit, transfer_mainnet_gas
|
||||||
from python_keywords.node_management import node_healthcheck
|
from python_keywords.node_management import node_healthcheck
|
||||||
|
from robot.api import deco
|
||||||
from service_helper import get_storage_service_helper
|
from service_helper import get_storage_service_helper
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,9 +38,15 @@ def cloud_infrastructure_check():
|
||||||
@allure.title('Check binary versions')
|
@allure.title('Check binary versions')
|
||||||
def check_binary_versions(request):
|
def check_binary_versions(request):
|
||||||
# Collect versions of local binaries
|
# Collect versions of local binaries
|
||||||
binaries = ['neo-go', 'neofs-cli', 'neofs-authmate']
|
binaries = ['neo-go', 'neofs-authmate']
|
||||||
local_binaries = _get_binaries_version_local(binaries)
|
local_binaries = _get_binaries_version_local(binaries)
|
||||||
|
|
||||||
|
try:
|
||||||
|
local_binaries['neofs-adm'] = NeofsAdm().version.get()
|
||||||
|
except RuntimeError:
|
||||||
|
logger.info(f'neofs-adm not installed')
|
||||||
|
local_binaries['neofs-cli'] = NeofsCli().version.get()
|
||||||
|
|
||||||
# Collect versions of remote binaries
|
# Collect versions of remote binaries
|
||||||
helper = get_storage_service_helper()
|
helper = get_storage_service_helper()
|
||||||
remote_binaries = helper.get_binaries_version()
|
remote_binaries = helper.get_binaries_version()
|
||||||
|
|
|
@ -10,8 +10,8 @@ from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
import allure
|
import allure
|
||||||
import base58
|
import base58
|
||||||
from cli import NeofsCli
|
|
||||||
from cli_helpers import _cmd_run
|
from cli_helpers import _cmd_run
|
||||||
|
from cli_utils import NeofsCli
|
||||||
from common import ASSETS_DIR, NEOFS_CLI_EXEC, NEOFS_ENDPOINT, WALLET_CONFIG
|
from common import ASSETS_DIR, NEOFS_CLI_EXEC, NEOFS_ENDPOINT, WALLET_CONFIG
|
||||||
from data_formatters import get_wallet_public_key
|
from data_formatters import get_wallet_public_key
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
from .adm import CompletionType, NeofsAdm
|
||||||
|
from .cli import NeofsCli
|
|
@ -0,0 +1,2 @@
|
||||||
|
from .adm import NeofsAdm
|
||||||
|
from .completion_type import CompletionType
|
36
robot/resources/lib/python_keywords/cli_utils/adm/adm.py
Normal file
36
robot/resources/lib/python_keywords/cli_utils/adm/adm.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from common import NEOFS_ADM_EXEC
|
||||||
|
|
||||||
|
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 .version import NeofsAdmVersion
|
||||||
|
|
||||||
|
|
||||||
|
class NeofsAdm:
|
||||||
|
neofs_adm_exec_path: Optional[str] = None
|
||||||
|
config_file: Optional[str] = None
|
||||||
|
|
||||||
|
completion: Optional[NeofsAdmCompletion] = None
|
||||||
|
config: Optional[NeofsAdmConfig] = None
|
||||||
|
gendoc: Optional[NeofsAdmGenDoc] = None
|
||||||
|
morph: Optional[NeofsAdmMorph] = None
|
||||||
|
subnet: Optional[NeofsAdmMorphSubnet] = None
|
||||||
|
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):
|
||||||
|
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.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)
|
|
@ -0,0 +1,30 @@
|
||||||
|
from cli_utils.cli_command import NeofsCliCommand
|
||||||
|
|
||||||
|
from .completion_type import CompletionType
|
||||||
|
|
||||||
|
|
||||||
|
class NeofsAdmCompletion(NeofsCliCommand):
|
||||||
|
def get(self, completion_type: CompletionType = CompletionType.FISH) -> str:
|
||||||
|
"""To load completions:
|
||||||
|
Bash:
|
||||||
|
$ source <(neofs-adm completion bash)
|
||||||
|
|
||||||
|
Zsh:
|
||||||
|
If shell completion is not already enabled in your environment you will need
|
||||||
|
to enable it. You can execute the following once:
|
||||||
|
$ echo "autoload -U compinit; compinit" >> ~/.zshrc
|
||||||
|
|
||||||
|
You will need to start a new shell for this setup to take effect.
|
||||||
|
|
||||||
|
Fish:
|
||||||
|
$ neofs-adm completion fish | source
|
||||||
|
|
||||||
|
Args:
|
||||||
|
completion_type (CompletionType): Select completion type (default: Fish)
|
||||||
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Command string
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self._execute('completion ' + completion_type.value)
|
|
@ -0,0 +1,8 @@
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class CompletionType(Enum):
|
||||||
|
BASH = 'bash'
|
||||||
|
ZHS = 'zsh'
|
||||||
|
FISH = 'fish'
|
||||||
|
POWERSHELL = 'powershell'
|
19
robot/resources/lib/python_keywords/cli_utils/adm/config.py
Normal file
19
robot/resources/lib/python_keywords/cli_utils/adm/config.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
from cli_utils.cli_command import NeofsCliCommand
|
||||||
|
|
||||||
|
|
||||||
|
class NeofsAdmConfig(NeofsCliCommand):
|
||||||
|
def init(self, path: str = '~/.neofs/adm/config.yml') -> str:
|
||||||
|
"""Initialize basic neofs-adm configuration file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path (str): path to config (default ~/.neofs/adm/config.yml)
|
||||||
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Command string
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self._execute(
|
||||||
|
'config init',
|
||||||
|
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
|
||||||
|
)
|
34
robot/resources/lib/python_keywords/cli_utils/adm/gendoc.py
Normal file
34
robot/resources/lib/python_keywords/cli_utils/adm/gendoc.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
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:
|
||||||
|
"""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.
|
||||||
|
|
||||||
|
The last optional argument specifies the template to use with text/template.
|
||||||
|
In this case there is a number of helper functions which can be used:
|
||||||
|
replace STR FROM TO -- same as strings.ReplaceAll
|
||||||
|
join ARRAY SEPARATOR -- same as strings.Join
|
||||||
|
split STR SEPARATOR -- same as strings.Split
|
||||||
|
fullUse CMD -- slice of all command names starting from the parent
|
||||||
|
listFlags CMD -- list of command flags
|
||||||
|
|
||||||
|
Args:
|
||||||
|
depth (int): if template is specified, unify all commands starting from depth in a single file.
|
||||||
|
Default = 1.
|
||||||
|
doc_file (str): file where to save generated documentation
|
||||||
|
extension (str): if the template is specified, string to append to the output file names
|
||||||
|
doc_type (str): type for the documentation ('md' or 'man') (default "md")
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Command string
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self._execute(
|
||||||
|
f'gendoc {doc_file}',
|
||||||
|
**{param: param_value for param, param_value in locals().items() if param not in ['self', 'doc_file']}
|
||||||
|
)
|
272
robot/resources/lib/python_keywords/cli_utils/adm/morph.py
Normal file
272
robot/resources/lib/python_keywords/cli_utils/adm/morph.py
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
account (str): wallet account address
|
||||||
|
gas (str): amount of GAS to deposit
|
||||||
|
rpc_endpoint (str): N3 RPC node endpoint
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
proxy (str): dump balances of the proxy contract
|
||||||
|
rpc_endpoint (str): N3 RPC node endpoint
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
def dump_config(self, rpc_endpoint: str) -> str:
|
||||||
|
"""Section for morph network configuration commands.
|
||||||
|
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
container_contract (str): container contract hash (for networks without NNS)
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
def dump_hashes(self, rpc_endpoint: str) -> str:
|
||||||
|
"""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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
def generate_alphabet(self, rpc_endpoint: str, alphabet_wallets: str, size: int = 7) -> str:
|
||||||
|
"""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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
initial_gas (str): initial amount of GAS to transfer
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
alphabet_wallets (str): path to alphabet wallets dir
|
||||||
|
container_alias_fee (int): container alias fee (default 500)
|
||||||
|
container_fee (int): container registration fee (default 1000)
|
||||||
|
contracts (str): path to archive with compiled NeoFS contracts
|
||||||
|
(default fetched from latest github release)
|
||||||
|
epoch_duration (int): amount of side chain blocks in one NeoFS epoch (default 240)
|
||||||
|
homomorphic_disabled: (bool): disable object homomorphic hashing
|
||||||
|
local_dump (str): path to the blocks dump file
|
||||||
|
max_object_size (int): max single object size in bytes (default 67108864)
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
gas (str): additional amount of GAS to transfer
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
cid (str): containers to restore
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
exec_fee_factor (int): ExecFeeFactor=<n1>
|
||||||
|
storage_price (int): StoragePrice=<n2>
|
||||||
|
fee_per_byte (int): FeePerByte=<n3>
|
||||||
|
rpc_endpoint (str): N3 RPC node endpoint
|
||||||
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Command string
|
||||||
|
|
||||||
|
"""
|
||||||
|
non_param_attribute = ''
|
||||||
|
if exec_fee_factor:
|
||||||
|
non_param_attribute += f'ExecFeeFactor={exec_fee_factor} '
|
||||||
|
if storage_price:
|
||||||
|
non_param_attribute += f'StoragePrice={storage_price} '
|
||||||
|
if 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'
|
||||||
|
]}
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
contracts (str): path to archive with compiled NeoFS contracts
|
||||||
|
(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']}
|
||||||
|
)
|
|
@ -0,0 +1,20 @@
|
||||||
|
from cli_utils.cli_command import NeofsCliCommand
|
||||||
|
|
||||||
|
|
||||||
|
class NeofsAdmStorageConfig(NeofsCliCommand):
|
||||||
|
def set(self, account: str, wallet: str) -> str:
|
||||||
|
"""Initialize basic neofs-adm configuration file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
account (str): wallet account
|
||||||
|
wallet (str): path to wallet
|
||||||
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Command string
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self._execute(
|
||||||
|
'storage-config',
|
||||||
|
**{param: param_value for param, param_value in locals().items() if param not in ['self']}
|
||||||
|
)
|
187
robot/resources/lib/python_keywords/cli_utils/adm/subnet.py
Normal file
187
robot/resources/lib/python_keywords/cli_utils/adm/subnet.py
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from cli_utils.cli_command import NeofsCliCommand
|
||||||
|
|
||||||
|
|
||||||
|
class NeofsAdmMorphSubnet(NeofsCliCommand):
|
||||||
|
def create(self, rpc_endpoint: str, address: str, wallet: str, notary: bool = False) -> str:
|
||||||
|
"""Create NeoFS subnet.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
address (str): Address in the wallet, optional
|
||||||
|
notary (bool): Flag to create subnet in notary environment
|
||||||
|
rpc_endpoint (str): N3 RPC node endpoint
|
||||||
|
wallet (str): Path to file with wallet
|
||||||
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Command string
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self._execute(
|
||||||
|
'morph subnet create',
|
||||||
|
**{param: param_value for param, 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.
|
||||||
|
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
rpc_endpoint (str): N3 RPC node endpoint
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
admin (str): Hex-encoded public key of the admin
|
||||||
|
client (str): Add client admin instead of node one
|
||||||
|
group (str): Client group ID in text format (needed with --client only)
|
||||||
|
rpc_endpoint (str): N3 RPC node endpoint
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
admin (str): Hex-encoded public key of the admin
|
||||||
|
client (str): Remove client admin instead of node one
|
||||||
|
rpc_endpoint (str): N3 RPC node endpoint
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
client (str): Add client admin instead of node one
|
||||||
|
group (str): Client group ID in text format (needed with --client only)
|
||||||
|
rpc_endpoint (str): N3 RPC node endpoint
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
client (str): Remove client admin instead of node one
|
||||||
|
group (str): ID of the client group to work with
|
||||||
|
rpc_endpoint (str): N3 RPC node endpoint
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
def node_add(self, rpc_endpoint: str, wallet: str, node: str, subnet: str) -> str:
|
||||||
|
"""Add node to the NeoFS subnet.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node (str): Hex-encoded public key of the node
|
||||||
|
rpc_endpoint (str): N3 RPC node endpoint
|
||||||
|
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']}
|
||||||
|
)
|
||||||
|
|
||||||
|
def node_remove(self, rpc_endpoint: str, wallet: str, node: str, subnet: str) -> str:
|
||||||
|
"""Remove node from the NeoFS subnet.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node (str): Hex-encoded public key of the node
|
||||||
|
rpc_endpoint (str): N3 RPC node endpoint
|
||||||
|
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']}
|
||||||
|
)
|
12
robot/resources/lib/python_keywords/cli_utils/adm/version.py
Normal file
12
robot/resources/lib/python_keywords/cli_utils/adm/version.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
from cli_utils.cli_command import NeofsCliCommand
|
||||||
|
|
||||||
|
|
||||||
|
class NeofsAdmVersion(NeofsCliCommand):
|
||||||
|
def get(self) -> str:
|
||||||
|
"""Application version
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Command string
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self._execute('', version=True)
|
|
@ -1,9 +1,9 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from .cli_command import NeofsCliCommandBase
|
from cli_utils.cli_command import NeofsCliCommand
|
||||||
|
|
||||||
|
|
||||||
class NeofsCliAccounting(NeofsCliCommandBase):
|
class NeofsCliAccounting(NeofsCliCommand):
|
||||||
def balance(self, wallet: str, rpc_endpoint: str, address: Optional[str] = None,
|
def balance(self, wallet: str, rpc_endpoint: str, address: Optional[str] = None,
|
||||||
owner: Optional[str] = None) -> str:
|
owner: Optional[str] = None) -> str:
|
||||||
"""Get internal balance of NeoFS account
|
"""Get internal balance of NeoFS account
|
|
@ -1,9 +1,9 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from .cli_command import NeofsCliCommandBase
|
from cli_utils.cli_command import NeofsCliCommand
|
||||||
|
|
||||||
|
|
||||||
class NeofsCliACL(NeofsCliCommandBase):
|
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.
|
"""Create extended ACL from the text representation.
|
|
@ -4,9 +4,9 @@ from common import NEOFS_CLI_EXEC
|
||||||
|
|
||||||
from .accounting import NeofsCliAccounting
|
from .accounting import NeofsCliAccounting
|
||||||
from .acl import NeofsCliACL
|
from .acl import NeofsCliACL
|
||||||
from .cli_command import NeofsCliCommandBase
|
|
||||||
from .container import NeofsCliContainer
|
from .container import NeofsCliContainer
|
||||||
from .object import NeofsCliObject
|
from .object import NeofsCliObject
|
||||||
|
from .version import NeofsCliVersion
|
||||||
|
|
||||||
|
|
||||||
class NeofsCli:
|
class NeofsCli:
|
||||||
|
@ -16,6 +16,7 @@ class NeofsCli:
|
||||||
acl: Optional[NeofsCliACL] = None
|
acl: Optional[NeofsCliACL] = None
|
||||||
container: Optional[NeofsCliContainer] = None
|
container: Optional[NeofsCliContainer] = None
|
||||||
object: Optional[NeofsCliObject] = None
|
object: Optional[NeofsCliObject] = None
|
||||||
|
version: Optional[NeofsCliVersion] = None
|
||||||
|
|
||||||
def __init__(self, neofs_cli_exec_path: Optional[str] = None, config: Optional[str] = None, timeout: int = 30):
|
def __init__(self, neofs_cli_exec_path: Optional[str] = None, config: Optional[str] = None, timeout: int = 30):
|
||||||
self.config = config # config(str): config file (default is $HOME/.config/neofs-cli/config.yaml)
|
self.config = config # config(str): config file (default is $HOME/.config/neofs-cli/config.yaml)
|
||||||
|
@ -24,12 +25,4 @@ class NeofsCli:
|
||||||
self.acl = NeofsCliACL(self.neofs_cli_exec_path, timeout=timeout, config=config)
|
self.acl = NeofsCliACL(self.neofs_cli_exec_path, timeout=timeout, config=config)
|
||||||
self.container = NeofsCliContainer(self.neofs_cli_exec_path, timeout=timeout, config=config)
|
self.container = NeofsCliContainer(self.neofs_cli_exec_path, timeout=timeout, config=config)
|
||||||
self.object = NeofsCliObject(self.neofs_cli_exec_path, timeout=timeout, config=config)
|
self.object = NeofsCliObject(self.neofs_cli_exec_path, timeout=timeout, config=config)
|
||||||
|
self.version = NeofsCliVersion(self.neofs_cli_exec_path, timeout=timeout, config=config)
|
||||||
def version(self) -> str:
|
|
||||||
"""Application version and NeoFS API compatibility
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: Command string
|
|
||||||
|
|
||||||
"""
|
|
||||||
return NeofsCliCommandBase(self.neofs_cli_exec_path, config=self.config)._execute(command=None, version=True)
|
|
|
@ -1,9 +1,9 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from .cli_command import NeofsCliCommandBase
|
from cli_utils.cli_command import NeofsCliCommand
|
||||||
|
|
||||||
|
|
||||||
class NeofsCliContainer(NeofsCliCommandBase):
|
class NeofsCliContainer(NeofsCliCommand):
|
||||||
def create(self, rpc_endpoint: str, wallet: str, address: Optional[str] = None, attributes: Optional[dict] = None,
|
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,
|
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,
|
name: Optional[str] = None, nonce: Optional[str] = None, policy: Optional[str] = None,
|
|
@ -1,9 +1,9 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from .cli_command import NeofsCliCommandBase
|
from cli_utils.cli_command import NeofsCliCommand
|
||||||
|
|
||||||
|
|
||||||
class NeofsCliObject(NeofsCliCommandBase):
|
class NeofsCliObject(NeofsCliCommand):
|
||||||
def delete(self, rpc_endpoint: str, wallet: str, cid: str, oid: str, address: Optional[str] = None,
|
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,
|
bearer: Optional[str] = None, session: Optional[str] = None, ttl: Optional[int] = None,
|
||||||
xhdr: Optional[dict] = None) -> str:
|
xhdr: Optional[dict] = None) -> str:
|
12
robot/resources/lib/python_keywords/cli_utils/cli/version.py
Normal file
12
robot/resources/lib/python_keywords/cli_utils/cli/version.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
from cli_utils.cli_command import NeofsCliCommand
|
||||||
|
|
||||||
|
|
||||||
|
class NeofsCliVersion(NeofsCliCommand):
|
||||||
|
def get(self) -> str:
|
||||||
|
"""Application version and NeoFS API compatibility
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Command string
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self._execute('', version=True)
|
|
@ -3,13 +3,13 @@ from typing import Optional
|
||||||
from cli_helpers import _cmd_run
|
from cli_helpers import _cmd_run
|
||||||
|
|
||||||
|
|
||||||
class NeofsCliCommandBase:
|
class NeofsCliCommand:
|
||||||
neofs_cli_exec: Optional[str] = None
|
neofs_cli_exec: Optional[str] = None
|
||||||
timeout: Optional[int] = None
|
timeout: Optional[int] = None
|
||||||
__base_params: Optional[str] = None
|
__base_params: Optional[str] = None
|
||||||
map_params = {'json_mode': 'json', 'await_mode': 'await', 'hash_type': 'hash'}
|
map_params = {'json_mode': 'json', 'await_mode': 'await', 'hash_type': 'hash', 'doc_type': 'type'}
|
||||||
|
|
||||||
def __init__(self, neofs_cli_exec: str, timeout: int = 30, **base_params):
|
def __init__(self, neofs_cli_exec: str, timeout: int, **base_params):
|
||||||
self.neofs_cli_exec = neofs_cli_exec
|
self.neofs_cli_exec = neofs_cli_exec
|
||||||
self.timeout = timeout
|
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])
|
|
@ -9,7 +9,7 @@ from time import sleep
|
||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
|
|
||||||
import json_transformers
|
import json_transformers
|
||||||
from cli import NeofsCli
|
from cli_utils import NeofsCli
|
||||||
from common import NEOFS_ENDPOINT, WALLET_CONFIG
|
from common import NEOFS_ENDPOINT, WALLET_CONFIG
|
||||||
from robot.api import logger
|
from robot.api import logger
|
||||||
from robot.api.deco import keyword
|
from robot.api.deco import keyword
|
||||||
|
|
|
@ -11,7 +11,7 @@ import uuid
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import json_transformers
|
import json_transformers
|
||||||
from cli import NeofsCli
|
from cli_utils import NeofsCli
|
||||||
from common import ASSETS_DIR, NEOFS_ENDPOINT, NEOFS_NETMAP, WALLET_CONFIG
|
from common import ASSETS_DIR, NEOFS_ENDPOINT, NEOFS_NETMAP, WALLET_CONFIG
|
||||||
from robot.api import logger
|
from robot.api import logger
|
||||||
from robot.api.deco import keyword
|
from robot.api.deco import keyword
|
||||||
|
|
|
@ -107,7 +107,8 @@ STORAGE_NODE_SSH_PRIVATE_KEY_PATH = os.getenv("STORAGE_NODE_SSH_PRIVATE_KEY_PATH
|
||||||
STORAGE_NODE_BIN_PATH = os.getenv("STORAGE_NODE_BIN_PATH", f"{DEVENV_PATH}/vendor")
|
STORAGE_NODE_BIN_PATH = os.getenv("STORAGE_NODE_BIN_PATH", f"{DEVENV_PATH}/vendor")
|
||||||
|
|
||||||
# Path and config for neofs-adm utility. Optional if tests are running against devenv
|
# Path and config for neofs-adm utility. Optional if tests are running against devenv
|
||||||
NEOFS_ADM_EXEC = os.getenv("NEOFS_ADM_EXEC")
|
NEOFS_ADM_EXEC = os.getenv('NEOFS_ADM_EXEC', 'neofs-adm')
|
||||||
|
|
||||||
NEOFS_ADM_CONFIG_PATH = os.getenv("NEOFS_ADM_CONFIG_PATH")
|
NEOFS_ADM_CONFIG_PATH = os.getenv("NEOFS_ADM_CONFIG_PATH")
|
||||||
|
|
||||||
INFRASTRUCTURE_TYPE = os.getenv("INFRASTRUCTURE_TYPE", "LOCAL_DEVENV")
|
INFRASTRUCTURE_TYPE = os.getenv("INFRASTRUCTURE_TYPE", "LOCAL_DEVENV")
|
||||||
|
|
Loading…
Reference in a new issue