[#184]: neofs verbs divided from neofs.py; HEAD responses are now

proccessed as JSON

Signed-off-by: anastasia prasolova <anastasia@nspcc.ru>
This commit is contained in:
anastasia prasolova 2022-03-15 14:58:59 +03:00 committed by Anastasia Prasolova
parent e5d6662905
commit 7a21456201
43 changed files with 667 additions and 494 deletions

View file

@ -19,6 +19,7 @@ def _cmd_run(cmd, timeout=30):
in case of failure returns error message. in case of failure returns error message.
""" """
try: try:
logger.info(f"Executing command: {cmd}")
compl_proc = subprocess.run(cmd, check=True, universal_newlines=True, compl_proc = subprocess.run(cmd, check=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, timeout=timeout, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, timeout=timeout,
shell=True) shell=True)

View file

@ -0,0 +1,113 @@
#!/usr/bin/python3
'''
When doing requests to NeoFS, we get JSON output as an automatically decoded
structure from protobuf. Some fields are decoded with boilerplates and binary
values are Base64-encoded.
This module contains functions which rearrange the structure and reencode binary
data from Base64 to Base58.
'''
import base64
import base58
ROBOT_AUTO_KEYWORDS = False
def decode_simple_header(data: dict):
'''
This function reencodes Simple Object header and its attributes.
'''
try:
data = decode_common_fields(data)
# object attributes view normalization
ugly_attrs = data["header"]["attributes"]
data["header"]["attributes"] = {}
for attr in ugly_attrs:
data["header"]["attributes"][attr["key"]] = attr["value"]
except Exception as exc:
raise ValueError(f"failed to decode JSON output: {exc}") from exc
return data
def decode_split_header(data: dict):
'''
This function rearranges Complex Object header.
The header holds SplitID, a random unique
number, which is common among all splitted objects, and IDs of the Linking
Object and the last splitted Object.
'''
try:
data["splitId"] = json_reencode(data["splitId"])
data["lastPart"] = json_reencode(data["lastPart"]["value"])
data["link"] = json_reencode(data["link"]["value"])
except Exception as exc:
raise ValueError(f"failed to decode JSON output: {exc}") from exc
return data
def decode_linking_object(data: dict):
'''
This function reencodes Linking Object header.
It contains IDs of child Objects and Split Chain data.
'''
try:
data = decode_simple_header(data)
# reencoding Child Object IDs
# { 'value': <Base58 encoded OID> } -> <Base64 encoded OID>
for ind, val in enumerate(data['header']['split']['children']):
data['header']['split']['children'][ind] = json_reencode(val['value'])
data['header']['split']['splitID'] = json_reencode(data['header']['split']['splitID'])
data['header']['split']['previous'] = (
json_reencode(data['header']['split']['previous']['value'])
if data['header']['split']['previous'] else None
)
data['header']['split']['parent'] = (
json_reencode(data['header']['split']['parent']['value'])
if data['header']['split']['parent'] else None
)
except Exception as exc:
raise ValueError(f"failed to decode JSON output: {exc}") from exc
return data
def decode_storage_group(data: dict):
'''
This function reencodes Storage Group header.
'''
try:
data = decode_common_fields(data)
except Exception as exc:
raise ValueError(f"failed to decode JSON output: {exc}") from exc
return data
def json_reencode(data: str):
'''
According to JSON protocol, binary data (Object/Container/Storage Group IDs, etc)
is converted to string via Base58 encoder. But we usually operate with Base64-encoded
format.
This function reencodes given Base58 string into the Base64 one.
'''
return base58.b58encode(base64.b64decode(data)).decode("utf-8")
def decode_common_fields(data: dict):
'''
Despite of type (simple/complex Object, Storage Group, etc) every Object
header contains several common fields.
This function rearranges these fields.
'''
# reencoding binary IDs
data["objectID"] = json_reencode(data["objectID"]["value"])
data["header"]["containerID"] = json_reencode(data["header"]["containerID"]["value"])
data["header"]["ownerID"] = json_reencode(data["header"]["ownerID"]["value"])
data["header"]["homomorphicHash"] = json_reencode(data["header"]["homomorphicHash"]["sum"])
data["header"]["payloadHash"] = json_reencode(data["header"]["payloadHash"]["sum"])
data["header"]["version"] = (
f"{data['header']['version']['major']}{data['header']['version']['minor']}"
)
return data

View file

@ -1,7 +1,6 @@
#!/usr/bin/python3.8 #!/usr/bin/python3
import base64 import base64
import binascii
from datetime import datetime from datetime import datetime
import hashlib import hashlib
import json import json
@ -11,13 +10,15 @@ import random
import uuid import uuid
import docker import docker
import base58 import base58
from functools import reduce
from neo3 import wallet from neo3 import wallet
from common import * from common import *
from robot.api.deco import keyword from robot.api.deco import keyword
from robot.api import logger from robot.api import logger
from cli_helpers import _run_with_passwd, _cmd_run from cli_helpers import _run_with_passwd, _cmd_run
import neofs_verbs
import json_transformers
ROBOT_AUTO_KEYWORDS = False ROBOT_AUTO_KEYWORDS = False
@ -67,7 +68,7 @@ def get_nodes_with_object(private_key: str, cid: str, oid: str):
for node in NEOFS_NETMAP: for node in NEOFS_NETMAP:
search_res = _search_object(node, private_key, cid, oid) search_res = _search_object(node, private_key, cid, oid)
if search_res: if search_res:
if re.search(fr'({oid})', search_res): if oid in search_res:
nodes_list.append(node) nodes_list.append(node)
logger.info(f"Nodes with object: {nodes_list}") logger.info(f"Nodes with object: {nodes_list}")
@ -98,11 +99,12 @@ def validate_storage_policy_for_object(private_key: str, expected_copies: int, c
storage_nodes = storage_nodes if len(storage_nodes) != 0 else NEOFS_NETMAP storage_nodes = storage_nodes if len(storage_nodes) != 0 else NEOFS_NETMAP
copies = 0 copies = 0
found_nodes = [] found_nodes = []
oid = oid.strip()
for node in storage_nodes: for node in storage_nodes:
search_res = _search_object(node, private_key, cid, oid) search_res = _search_object(node, private_key, cid, oid)
if search_res: if search_res:
if re.search(fr'({oid})', search_res): if oid in search_res:
copies += 1 copies += 1
found_nodes.append(node) found_nodes.append(node)
@ -121,21 +123,6 @@ def validate_storage_policy_for_object(private_key: str, expected_copies: int, c
raise Exception(f"Found node list '{found_nodes}' is not equal to expected list '{expected_node_list}'") raise Exception(f"Found node list '{found_nodes}' is not equal to expected list '{expected_node_list}'")
@keyword('Get Range')
def get_range(private_key: str, cid: str, oid: str, range_file: str, bearer: str,
range_cut: str, options:str=""):
bearer_token = ""
if bearer:
bearer_token = f"--bearer {bearer}"
Cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {NEOFS_ENDPOINT} --wallet {private_key} '
f'object range --cid {cid} --oid {oid} {bearer_token} --range {range_cut} '
f'--file {ASSETS_DIR}/{range_file} {options}'
)
logger.info(f"Cmd: {Cmd}")
_cmd_run(Cmd)
@keyword('Create container') @keyword('Create container')
def create_container(private_key: str, basic_acl:str, rule:str, user_headers: str='', session: str=''): def create_container(private_key: str, basic_acl:str, rule:str, user_headers: str='', session: str=''):
@ -187,39 +174,6 @@ def container_existing(private_key: str, cid: str):
return return
@keyword('Search object')
def search_object(private_key: str, cid: str, keys: str="", bearer: str="", filters: dict={},
expected_objects_list=[], options:str=""):
bearer_token = ""
filters_result = ""
if bearer:
bearer_token = f"--bearer {bearer}"
if filters:
filters_result += "--filters "
logger.info(filters)
for k, v in filters.items():
filters_result += f"'{k} EQ {v}' "
object_cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {NEOFS_ENDPOINT} --wallet {private_key} '
f'object search {keys} --cid {cid} {bearer_token} {filters_result} {options}'
)
logger.info(f"Cmd: {object_cmd}")
output = _cmd_run(object_cmd)
found_objects = re.findall(r'(\w{43,44})', output)
if expected_objects_list:
if sorted(found_objects) == sorted(expected_objects_list):
logger.info(f"Found objects list '{found_objects}' ",
f"is equal for expected list '{expected_objects_list}'")
else:
raise Exception(f"Found object list {found_objects} ",
f"is not equal to expected list '{expected_objects_list}'")
return found_objects
@keyword('Get Split objects') @keyword('Get Split objects')
def get_component_objects(private_key: str, cid: str, oid: str): def get_component_objects(private_key: str, cid: str, oid: str):
@ -227,36 +181,36 @@ def get_component_objects(private_key: str, cid: str, oid: str):
split_id = "" split_id = ""
for node in NEOFS_NETMAP: for node in NEOFS_NETMAP:
try: try:
header_virtual = head_object(private_key, cid, oid, options=' --ttl 1', parsed_header_virtual = neofs_verbs.head_object(private_key, cid, oid, options=' --ttl 1',
endpoint=node, is_raw=True) endpoint=node, is_raw=True)
if header_virtual:
parsed_header_virtual = parse_object_virtual_raw_header(header_virtual)
if 'Linking object' in parsed_header_virtual.keys(): if 'link' in parsed_header_virtual.keys():
return _collect_split_objects_from_header(private_key, cid, parsed_header_virtual) return _collect_split_objects_from_header(private_key, cid, parsed_header_virtual)
elif 'Split ID' in parsed_header_virtual.keys(): elif 'split' in parsed_header_virtual['header'].keys():
logger.info(f"parsed_header_virtual: !@ {parsed_header_virtual}" ) logger.info(f"parsed_header_virtual: !@ {parsed_header_virtual}" )
split_id = parsed_header_virtual['Split ID'] split_id = parsed_header_virtual['header']['splitID']
except: except:
logger.warn("Linking object has not been found.") logger.warn("Linking object has not been found.")
# Get all existing objects # Get all existing objects
full_obj_list = search_object(private_key, cid, None, None, None, None, '--phy') full_obj_list = neofs_verbs.search_object(private_key, cid, None, None, None, None, '--phy')
# Search expected Linking object # Search expected Linking object
for targer_oid in full_obj_list: for targer_oid in full_obj_list:
header_parsed = head_object(private_key, cid, targer_oid, is_raw=True) header_parsed = neofs_verbs.head_object(private_key, cid, targer_oid, is_raw=True)
if header_parsed['Split ID'] == split_id and 'Split ChildID' in header_parsed.keys(): if header_parsed['header']['split']:
logger.info("Linking object has been found in additional check (head of all objects).") if header_parsed['header']['split']['splitID'] == split_id and 'children' in header_parsed['header']['split'].keys():
return _collect_split_objects_from_header(private_key, cid, parsed_header_virtual) logger.info("Linking object has been found in additional check (head of all objects).")
return _collect_split_objects_from_header(private_key, cid, parsed_header_virtual)
raise Exception("Linking object is not found at all - all existed objects have been headed.") raise Exception("Linking object is not found at all - all existed objects have been headed.")
def _collect_split_objects_from_header(private_key, cid, parsed_header): def _collect_split_objects_from_header(private_key, cid, parsed_header):
header_link_parsed = head_object(private_key, cid, parsed_header['Linking object'], is_raw=True) header_link_parsed = neofs_verbs.head_object(private_key, cid, parsed_header['link'])
return header_link_parsed['Split ChildID'] return header_link_parsed['header']['split']['children']
@keyword('Verify Split Chain') @keyword('Verify Split Chain')
@ -274,19 +228,18 @@ def verify_split_chain(wif: str, cid: str, oid: str):
logger.info("Collect Split objects information and verify chain of the objects.") logger.info("Collect Split objects information and verify chain of the objects.")
for node in NEOFS_NETMAP: for node in NEOFS_NETMAP:
try: try:
header_virtual = head_object(wif, cid, oid, options=' --ttl 1', parsed_header_virtual = neofs_verbs.head_object(wif, cid, oid, options=' --ttl 1',
endpoint=node, json_output=False, is_raw=True) endpoint=node, is_raw=True)
parsed_header_virtual = parse_object_virtual_raw_header(header_virtual) logger.info(f"header {parsed_header_virtual}")
if 'Last object' in parsed_header_virtual.keys(): if 'lastPart' in parsed_header_virtual.keys():
header_last = head_object(wif, cid, header_last_parsed = neofs_verbs.head_object(wif, cid,
parsed_header_virtual['Last object'], parsed_header_virtual['lastPart'],
is_raw=True, json_output=False) is_raw=True)
header_last_parsed = _get_raw_split_information(header_last)
marker_last_obj = 1 marker_last_obj = 1
# Recursive chain validation up to the first object # Recursive chain validation up to the first object
final_verif_data = _verify_child_link(wif, cid, oid, header_last_parsed, final_verif_data) final_verif_data = _verify_child_link(wif, cid, oid, header_last_parsed['header'], final_verif_data)
break break
logger.info(f"Found Split Object with header:\n\t{parsed_header_virtual}") logger.info(f"Found Split Object with header:\n\t{parsed_header_virtual}")
logger.info("Continue to search Last Split Object") logger.info("Continue to search Last Split Object")
@ -302,41 +255,39 @@ def verify_split_chain(wif: str, cid: str, oid: str):
logger.info("Compare Split objects result information with Linking object.") logger.info("Compare Split objects result information with Linking object.")
for node in NEOFS_NETMAP: for node in NEOFS_NETMAP:
try: try:
header_virtual = head_object(wif, cid, oid, options=' --ttl 1', parsed_header_virtual = neofs_verbs.head_object(wif, cid, oid, options=' --ttl 1',
endpoint=node, json_output=False, is_raw=True) endpoint=node, is_raw=True)
parsed_header_virtual = parse_object_virtual_raw_header(header_virtual) if 'link' in parsed_header_virtual.keys():
if 'Linking object' in parsed_header_virtual.keys(): header_link_parsed = neofs_verbs.head_object(wif, cid,
header_link = head_object(wif, cid, parsed_header_virtual['link'],
parsed_header_virtual['Linking object'], is_raw=True)
is_raw=True, json_output=False)
header_link_parsed = _get_raw_split_information(header_link)
marker_link_obj = 1 marker_link_obj = 1
reversed_list = final_verif_data['ID List'][::-1] reversed_list = final_verif_data['header']['split']['children'][::-1]
if header_link_parsed['Split ChildID'] == reversed_list: if header_link_parsed['header']['split']['children'] == reversed_list:
logger.info(f"Split objects list from Linked Object is equal to expected " logger.info(f"Split objects list from Linked Object is equal to expected "
f"{', '.join(header_link_parsed['Split ChildID'])}") f"{', '.join(header_link_parsed['header']['split']['children'])}")
else: else:
raise Exception(f"Split objects list from Linking Object " raise Exception(f"Split objects list from Linking Object "
f"({', '.join(header_link_parsed['Split ChildID'])}) " f"({', '.join(header_link_parsed['header']['split']['children'])}) "
f"is not equal to expected ({', '.join(reversed_list)})") f"is not equal to expected ({', '.join(reversed_list)})")
if int(header_link_parsed['PayloadLength']) == 0: if int(header_link_parsed['header']['payloadLength']) == 0:
logger.info("Linking object Payload is equal to expected - zero size.") logger.info("Linking object Payload is equal to expected - zero size.")
else: else:
raise Exception("Linking object Payload is not equal to expected. Should be zero.") raise Exception("Linking object Payload is not equal to expected. Should be zero.")
if header_link_parsed['Type'] == 'regular': if header_link_parsed['header']['objectType'] == 'REGULAR':
logger.info("Linking Object Type is 'regular' as expected.") logger.info("Linking Object Type is 'regular' as expected.")
else: else:
raise Exception("Object Type is not 'regular'.") raise Exception("Object Type is not 'regular'.")
if header_link_parsed['Split ID'] == final_verif_data['Split ID']: if header_link_parsed['header']['split']['children'] == final_verif_data['split']['children']:
logger.info(f"Linking Object Split ID is equal to expected {final_verif_data['Split ID']}.") logger.info(f"Linking Object Split ID is equal to expected {final_verif_data['split']['children']}.")
else: else:
raise Exception(f"Split ID from Linking Object ({header_link_parsed['Split ID']}) " raise Exception(f"Split ID from Linking Object ({header_link_parsed['header']['split']['children']}) "
f"is not equal to expected ({final_verif_data['Split ID']})") f"is not equal to expected ({final_verif_data['split']['children']})")
break break
logger.info(f"Found Linking Object with header:\n\t{parsed_header_virtual}") logger.info(f"Found Linking Object with header:\n\t{parsed_header_virtual}")
@ -351,100 +302,47 @@ def verify_split_chain(wif: str, cid: str, oid: str):
logger.info("Compare Split objects result information with Virtual object.") logger.info("Compare Split objects result information with Virtual object.")
header_virtual = head_object(wif, cid, oid, json_output=False) header_virtual_parsed = neofs_verbs.head_object(wif, cid, oid)
header_virtual_parsed = _get_raw_split_information(header_virtual)
if int(header_virtual_parsed['PayloadLength']) == int(final_verif_data['PayloadLength']): if int(header_virtual_parsed['header']['payloadLength']) == int(final_verif_data['payloadLength']):
logger.info(f"Split objects PayloadLength are equal to Virtual Object Payload " logger.info(f"Split objects PayloadLength are equal to Virtual Object Payload "
f"{header_virtual_parsed['PayloadLength']}") f"{header_virtual_parsed['header']['payloadLength']}")
else: else:
raise Exception(f"Split objects PayloadLength from Virtual Object " raise Exception(f"Split objects PayloadLength from Virtual Object "
f"({header_virtual_parsed['PayloadLength']}) is not equal " f"({header_virtual_parsed['header']['payloadLength']}) is not equal "
f"to expected ({final_verif_data['PayloadLength']})") f"to expected ({final_verif_data['payloadLength']})")
if header_link_parsed['Type'] == 'regular': if header_link_parsed['header']['objectType'] == 'REGULAR':
logger.info("Virtual Object Type is 'regular' as expected.") logger.info("Virtual Object Type is 'regular' as expected.")
else: else:
raise Exception("Object Type is not 'regular'.") raise Exception("Object Type is not 'regular'.")
def _get_raw_split_information(header):
result_header = dict()
# Header - Constant attributes
# ID
m = re.search(r'^ID: (\w+)', header)
if m is not None:
result_header['ID'] = m.group(1)
else:
raise Exception(f"no ID was parsed from object header: \t{header}")
# Type
m = re.search(r'Type:\s+(\w+)', header)
if m is not None:
result_header['Type'] = m.group(1)
else:
raise Exception(f"no Type was parsed from object header: \t{header}")
# PayloadLength
m = re.search(r'Size: (\d+)', header)
if m is not None:
result_header['PayloadLength'] = m.group(1)
else:
raise Exception(f"no PayloadLength was parsed from object header: \t{header}")
# Header - Optional attributes
# SplitID
m = re.search(r'Split ID:\s+([\w-]+)', header)
if m is not None:
result_header['Split ID'] = m.group(1)
# Split PreviousID
m = re.search(r'Split PreviousID:\s+(\w+)', header)
if m is not None:
result_header['Split PreviousID'] = m.group(1)
# Split ParentID
m = re.search(r'Split ParentID:\s+(\w+)', header)
if m is not None:
result_header['Split ParentID'] = m.group(1)
# Split ChildID list
found_objects = re.findall(r'Split ChildID:\s+(\w+)', header)
if found_objects:
result_header['Split ChildID'] = found_objects
logger.info(f"Result: {result_header}")
return result_header
def _verify_child_link(wif: str, cid: str, oid: str, header_last_parsed: dict, final_verif_data: dict): def _verify_child_link(wif: str, cid: str, oid: str, header_last_parsed: dict, final_verif_data: dict):
if 'PayloadLength' in final_verif_data.keys(): if 'payloadLength' in final_verif_data.keys():
final_verif_data['PayloadLength'] = int(final_verif_data['PayloadLength']) + int(header_last_parsed['PayloadLength']) final_verif_data['payloadLength'] = int(final_verif_data['payloadLength']) + int(header_last_parsed['payloadLength'])
else: else:
final_verif_data['PayloadLength'] = int(header_last_parsed['PayloadLength']) final_verif_data['payloadLength'] = int(header_last_parsed['payloadLength'])
if header_last_parsed['Type'] != 'regular': if header_last_parsed['objectType'] != 'REGULAR':
raise Exception("Object Type is not 'regular'.") raise Exception("Object Type is not 'regular'.")
if 'Split ID' in final_verif_data.keys(): if 'split' in final_verif_data.keys():
if final_verif_data['Split ID'] != header_last_parsed['Split ID']: if final_verif_data['split']['splitID'] != header_last_parsed['split']['splitID']:
raise Exception(f"Object Split ID ({header_last_parsed['Split ID']}) is not expected ({final_verif_data['Split ID']}).") raise Exception(f"Object Split ID ({header_last_parsed['split']['splitID']}) "
f"is not expected ({final_verif_data['split']['splitID']}).")
else: else:
final_verif_data['Split ID'] = header_last_parsed['Split ID'] final_verif_data['split']['splitID'] = header_last_parsed['split']['splitID']
if 'ID List' in final_verif_data.keys(): if 'children' in final_verif_data['split'].keys():
final_verif_data['ID List'].append(header_last_parsed['ID']) final_verif_data['split']['children'].append(header_last_parsed['split']['children'])
else: else:
final_verif_data['ID List'] = [] final_verif_data['split']['children'] = []
final_verif_data['ID List'].append(header_last_parsed['ID']) final_verif_data['split']['children'].append(header_last_parsed['split']['children'])
if 'Split PreviousID' in header_last_parsed.keys(): if 'previous' in header_last_parsed['split'].keys():
header_virtual = head_object(wif, cid, header_last_parsed['Split PreviousID'], is_raw=True, json_output=False) parsed_header_virtual = neofs_verbs.head_object(wif, cid, header_last_parsed['split']['previous'], is_raw=True)
parsed_header_virtual = _get_raw_split_information(header_virtual)
final_verif_data = _verify_child_link(wif, cid, oid, parsed_header_virtual, final_verif_data) final_verif_data = _verify_child_link(wif, cid, oid, parsed_header_virtual, final_verif_data)
else: else:
@ -455,9 +353,10 @@ def _verify_child_link(wif: str, cid: str, oid: str, header_last_parsed: dict, f
@keyword('Verify Head Tombstone') @keyword('Verify Head Tombstone')
def verify_head_tombstone(private_key: str, cid: str, oid_ts: str, oid: str, addr: str): def verify_head_tombstone(private_key: str, cid: str, oid_ts: str, oid: str, addr: str):
# TODO: replace with HEAD from neofs_verbs.py
object_cmd = ( object_cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {NEOFS_ENDPOINT} --wallet {private_key} ' f'{NEOFS_CLI_EXEC} --rpc-endpoint {NEOFS_ENDPOINT} --wallet {private_key} '
f'object head --cid {cid} --oid {oid_ts} --json --no-progress' f'object head --cid {cid} --oid {oid_ts} --json'
) )
logger.info(f"Cmd: {object_cmd}") logger.info(f"Cmd: {object_cmd}")
output = _cmd_run(object_cmd) output = _cmd_run(object_cmd)
@ -466,13 +365,13 @@ def verify_head_tombstone(private_key: str, cid: str, oid_ts: str, oid: str, add
# Header verification # Header verification
header_cid = full_headers["header"]["containerID"]["value"] header_cid = full_headers["header"]["containerID"]["value"]
if (_json_cli_decode(header_cid) == cid): if (json_transformers.json_reencode(header_cid) == cid):
logger.info(f"Header CID is expected: {cid} ({header_cid} in the output)") logger.info(f"Header CID is expected: {cid} ({header_cid} in the output)")
else: else:
raise Exception("Header CID is not expected.") raise Exception("Header CID is not expected.")
header_owner = full_headers["header"]["ownerID"]["value"] header_owner = full_headers["header"]["ownerID"]["value"]
if (_json_cli_decode(header_owner) == addr): if (json_transformers.json_reencode(header_owner) == addr):
logger.info(f"Header ownerID is expected: {addr} ({header_owner} in the output)") logger.info(f"Header ownerID is expected: {addr} ({header_owner} in the output)")
else: else:
raise Exception("Header ownerID is not expected.") raise Exception("Header ownerID is not expected.")
@ -490,79 +389,18 @@ def verify_head_tombstone(private_key: str, cid: str, oid_ts: str, oid: str, add
raise Exception("Header Session Type is not expected.") raise Exception("Header Session Type is not expected.")
header_session_cid = full_headers["header"]["sessionToken"]["body"]["object"]["address"]["containerID"]["value"] header_session_cid = full_headers["header"]["sessionToken"]["body"]["object"]["address"]["containerID"]["value"]
if (_json_cli_decode(header_session_cid) == cid): if (json_transformers.json_reencode(header_session_cid) == cid):
logger.info(f"Header ownerID is expected: {addr} ({header_session_cid} in the output)") logger.info(f"Header ownerID is expected: {addr} ({header_session_cid} in the output)")
else: else:
raise Exception("Header Session CID is not expected.") raise Exception("Header Session CID is not expected.")
header_session_oid = full_headers["header"]["sessionToken"]["body"]["object"]["address"]["objectID"]["value"] header_session_oid = full_headers["header"]["sessionToken"]["body"]["object"]["address"]["objectID"]["value"]
if (_json_cli_decode(header_session_oid) == oid): if (json_transformers.json_reencode(header_session_oid) == oid):
logger.info(f"Header Session OID (deleted object) is expected: {oid} ({header_session_oid} in the output)") logger.info(f"Header Session OID (deleted object) is expected: {oid} ({header_session_oid} in the output)")
else: else:
raise Exception("Header Session OID (deleted object) is not expected.") raise Exception("Header Session OID (deleted object) is not expected.")
def _json_cli_decode(data: str):
return base58.b58encode(base64.b64decode(data)).decode("utf-8")
@keyword('Head object')
def head_object(private_key: str, cid: str, oid: str, bearer_token: str="",
options:str="", endpoint: str="", json_output: bool = True,
is_raw: bool = False):
cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {endpoint if endpoint else NEOFS_ENDPOINT} '
f'--wallet {private_key} '
f'object head --cid {cid} --oid {oid} {options} '
f'{"--bearer " + bearer_token if bearer_token else ""} '
f'{"--json" if json_output else ""} '
f'{"--raw" if is_raw else ""}'
)
logger.info(f"cmd: {cmd}")
output = _cmd_run(cmd)
if json_output:
decoded = json.loads(output)
output = _decode_json_output(decoded)
return output
def _decode_json_output(data: dict):
'''
We get JSON output as an automatically decoded structure from
protobuf. Some fields are decoded with boilerplates and binary
values are Base64-encoded.
This function rearranges the structure and reencodes binary
data from Base64 to Base58.
Args:
data (dict): a dictionary which neofs-cli returns to reencode.
Returns:
dict: dictionary which contains data in a more organized form.
'''
try:
# reencoding binary IDs
data["objectID"] = _json_cli_decode(data["objectID"]["value"])
data["header"]["containerID"] = _json_cli_decode(data["header"]["containerID"]["value"])
data["header"]["ownerID"] = _json_cli_decode(data["header"]["ownerID"]["value"])
data["header"]["homomorphicHash"] = _json_cli_decode(data["header"]["homomorphicHash"]["sum"])
data["header"]["payloadHash"] = _json_cli_decode(data["header"]["payloadHash"]["sum"])
data["header"]["version"] = f"{data['header']['version']['major']}{data['header']['version']['minor']}"
# object attributes view normalization
ugly_attrs = data["header"]["attributes"]
data["header"]["attributes"] = {}
for attr in ugly_attrs:
data["header"]["attributes"][attr["key"]] = attr["value"]
except Exception as exc:
raise RuntimeError(f"failed to decode JSON output: {exc}") from exc
return data
@keyword('Get container attributes') @keyword('Get container attributes')
def get_container_attributes(private_key: str, cid: str, endpoint: str="", json_output: bool = False): def get_container_attributes(private_key: str, cid: str, endpoint: str="", json_output: bool = False):
@ -577,28 +415,6 @@ def get_container_attributes(private_key: str, cid: str, endpoint: str="", json_
output = _cmd_run(container_cmd) output = _cmd_run(container_cmd)
return output return output
# TODO: replace with JSON parser when https://github.com/nspcc-dev/neofs-node/issues/1233
# is done
@keyword('Parse Object Virtual Raw Header')
def parse_object_virtual_raw_header(header: str):
result_header = dict()
m = re.search(r'Split ID:\s+([\w-]+)', header)
if m != None:
if m.start() != m.end(): # e.g., if match found something
result_header['Split ID'] = m.group(1)
m = re.search(r'Linking object:\s+(\w+)', header)
if m != None:
if m.start() != m.end(): # e.g., if match found something
result_header['Linking object'] = m.group(1)
m = re.search(r'Last object:\s+(\w+)', header)
if m != None:
if m.start() != m.end(): # e.g., if match found something
result_header['Last object'] = m.group(1)
logger.info(f"Result: {result_header}")
@keyword('Decode Container Attributes Json') @keyword('Decode Container Attributes Json')
def decode_container_attributes_json(header): def decode_container_attributes_json(header):
@ -619,22 +435,6 @@ def decode_container_attributes_json(header):
return result_header return result_header
@keyword('Delete object')
def delete_object(private_key: str, cid: str, oid: str, bearer: str="", options: str=""):
bearer_token = ""
if bearer:
bearer_token = f"--bearer {bearer}"
object_cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {NEOFS_ENDPOINT} --wallet {private_key} '
f'object delete --cid {cid} --oid {oid} {bearer_token} {options}'
)
logger.info(f"Cmd: {object_cmd}")
output = _cmd_run(object_cmd)
tombstone = _parse_oid(output)
return tombstone
@keyword('Delete Container') @keyword('Delete Container')
# TODO: make the error message about a non-found container more user-friendly https://github.com/nspcc-dev/neofs-contract/issues/121 # TODO: make the error message about a non-found container more user-friendly https://github.com/nspcc-dev/neofs-contract/issues/121
@ -654,41 +454,6 @@ def get_file_hash(filename : str):
return file_hash return file_hash
@keyword('Put object')
def put_object(private_key: str, path: str, cid: str, bearer: str="", user_headers: dict={},
endpoint: str="", options: str="" ):
if not endpoint:
endpoint = random.sample(NEOFS_NETMAP, 1)[0]
if bearer:
bearer = f"--bearer {bearer}"
putobject_cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {endpoint} --wallet {private_key} object '
f'put --no-progress --file {path} --cid {cid} {bearer} {options} '
f'{"--attributes " + _dict_to_attrs(user_headers) if user_headers else ""}'
)
logger.info(f"cmd: {putobject_cmd}")
output = _cmd_run(putobject_cmd)
oid = _parse_oid(output)
return oid
def _dict_to_attrs(attrs: dict):
'''
This function takes dictionary of object attributes and converts them
into the string. The string is passed to `--attibutes` key of the
neofs-cli.
Args:
attrs (dict): object attirbutes in {"a": "b", "c": "d"} format.
Returns:
(str): string in "a=b,c=d" format.
'''
return reduce(lambda a,b: f"{a},{b}", map(lambda i: f"{i}={attrs[i]}", attrs))
@keyword('Get control endpoint with wif') @keyword('Get control endpoint with wif')
def get_control_endpoint_with_wif(endpoint_number: str = ''): def get_control_endpoint_with_wif(endpoint_number: str = ''):
if endpoint_number == '': if endpoint_number == '':
@ -775,45 +540,6 @@ def find_in_nodes_Log(line: str, nodes_logs_time: dict):
return 1 return 1
@keyword('Get Range Hash')
def get_range_hash(private_key: str, cid: str, oid: str, bearer_token: str,
range_cut: str, options: str=""):
if bearer_token:
bearer_token = f"--bearer {bearer_token}"
object_cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {NEOFS_ENDPOINT} --wallet {private_key} '
f'object hash --cid {cid} --oid {oid} --range {range_cut} '
f'{bearer_token} {options}'
)
logger.info(f"Cmd: {object_cmd}")
_cmd_run(object_cmd)
@keyword('Get object')
def get_object(private_key: str, cid: str, oid: str, bearer_token: str="",
write_object: str="", endpoint: str="", options: str="" ):
if not write_object:
write_object = str(uuid.uuid4())
file_path = f"{ASSETS_DIR}/{write_object}"
logger.info("Going to get the object")
if not endpoint:
endpoint = random.sample(NEOFS_NETMAP, 1)[0]
if bearer_token:
bearer_token = f"--bearer {bearer_token}"
object_cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {endpoint} --wallet {private_key} '
f'object get --cid {cid} --oid {oid} --file {file_path} {bearer_token} '
f'{options}'
)
logger.info(f"Cmd: {object_cmd}")
_cmd_run(object_cmd)
return file_path
@ -1022,20 +748,10 @@ def _parse_cid(input_str: str):
def _search_object(node:str, private_key: str, cid:str, oid: str): def _search_object(node:str, private_key: str, cid:str, oid: str):
if oid:
oid_cmd = "--oid %s" % oid
Cmd = ( Cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {node} --wallet {private_key} --ttl 1 ' f'{NEOFS_CLI_EXEC} --rpc-endpoint {node} --wallet {private_key} --ttl 1 '
f'object search --root --cid {cid} {oid_cmd}' f'object search --root --cid {cid} --oid {oid}'
) )
output = _cmd_run(Cmd) output = _cmd_run(Cmd)
if re.search(fr'{oid}', output): return output
return oid
else:
logger.info("Object is not found.")
if re.search(r'local node is outside of object placement', output):
logger.info("Server is not presented in container.")
elif ( re.search(r'timed out after 30 seconds', output) or re.search(r'no route to host', output) or re.search(r'i/o timeout', output)):
logger.warn("Node is unavailable")

View file

@ -0,0 +1,297 @@
#!/usr/bin/python3
'''
This module contains wrappers for NeoFS verbs executed via neofs-cli.
'''
import json
import os
import re
import random
import uuid
from functools import reduce
from common import NEOFS_ENDPOINT, ASSETS_DIR, NEOFS_NETMAP
from cli_helpers import _cmd_run
import json_transformers
from robot.api.deco import keyword
from robot.api import logger
ROBOT_AUTO_KEYWORDS = False
# path to neofs-cli executable
NEOFS_CLI_EXEC = os.getenv('NEOFS_CLI_EXEC', 'neofs-cli')
@keyword('Get object')
def get_object(wif: str, cid: str, oid: str, bearer_token: str="",
write_object: str="", endpoint: str="", options: str="" ):
'''
GET from NeoFS.
Args:
wif (str): WIF of the wallet on whose behalf GET is done
cid (str): ID of Container where we get the Object from
oid (str): Object ID
bearer_token (optional, str): path to Bearer Token file, appends to `--bearer` key
write_object (optional, str): path to downloaded file, appends to `--file` key
endpoint (optional, str): NeoFS endpoint to send request to, appends to `--rpc-endpoint` key
options (optional, str): any options which `neofs-cli object get` accepts
Returns:
(str): path to downloaded file
'''
if not write_object:
write_object = str(uuid.uuid4())
file_path = f"{ASSETS_DIR}/{write_object}"
if not endpoint:
endpoint = random.sample(NEOFS_NETMAP, 1)[0]
cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {endpoint} --wallet {wif} '
f'object get --cid {cid} --oid {oid} --file {file_path} '
f'{"--bearer " + bearer_token if bearer_token else ""} '
f'{options}'
)
_cmd_run(cmd)
return file_path
@keyword('Get Range Hash')
def get_range_hash(wif: str, cid: str, oid: str, bearer_token: str,
range_cut: str, options: str=""):
'''
GETRANGEHASH of given Object.
Args:
wif (str): WIF of the wallet on whose behalf GETRANGEHASH is done
cid (str): ID of Container where we get the Object from
oid (str): Object ID
bearer_token (str): path to Bearer Token file, appends to `--bearer` key
range_cut (str): Range to take hash from in the form offset1:length1,...,
value to pass to the `--range` parameter
options (optional, str): any options which `neofs-cli object hash` accepts
Returns:
None
'''
cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {NEOFS_ENDPOINT} --wallet {wif} '
f'object hash --cid {cid} --oid {oid} --range {range_cut} '
f'{"--bearer " + bearer_token if bearer_token else ""} '
f'{options}'
)
_cmd_run(cmd)
@keyword('Put object')
def put_object(wif: str, path: str, cid: str, bearer: str="", user_headers: dict={},
endpoint: str="", options: str="" ):
'''
PUT of given file.
Args:
wif (str): WIF of the wallet on whose behalf PUT is done
path (str): path to file to be PUT
cid (str): ID of Container where we get the Object from
bearer (optional, str): path to Bearer Token file, appends to `--bearer` key
user_headers (optional, dict): Object attributes, append to `--attributes` key
endpoint(optional, str): NeoFS endpoint to send request to
options (optional, str): any options which `neofs-cli object put` accepts
Returns:
(str): ID of uploaded Object
'''
if not endpoint:
endpoint = random.sample(NEOFS_NETMAP, 1)[0]
cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {endpoint} --wallet {wif} '
f'object put --file {path} --cid {cid} {options} '
f'{"--bearer " + bearer if bearer else ""} '
f'{"--attributes " + _dict_to_attrs(user_headers) if user_headers else ""}'
)
output = _cmd_run(cmd)
# splitting CLI output to lines and taking the penultimate line
id_str = output.strip().split('\n')[-2]
oid = id_str.split(':')[1]
return oid.strip()
@keyword('Delete object')
def delete_object(wif: str, cid: str, oid: str, bearer: str="", options: str=""):
'''
DELETE an Object.
Args:
wif (str): WIF of the wallet on whose behalf DELETE is done
cid (str): ID of Container where we get the Object from
oid (str): ID of Object we are going to delete
bearer (optional, str): path to Bearer Token file, appends to `--bearer` key
options (optional, str): any options which `neofs-cli object delete` accepts
Returns:
(str): Tombstone ID
'''
cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {NEOFS_ENDPOINT} --wallet {wif} '
f'object delete --cid {cid} --oid {oid} {options}'
f'{"--bearer " + bearer if bearer else ""} '
)
output = _cmd_run(cmd)
id_str = output.split('\n')[1]
tombstone = id_str.split(':')[1]
return tombstone.strip()
@keyword('Get Range')
def get_range(wif: str, cid: str, oid: str, range_file: str, bearer: str,
range_cut: str, options:str=""):
'''
GETRANGE an Object.
Args:
wif (str): WIF of the wallet on whose behalf GETRANGE is done
cid (str): ID of Container where we get the Object from
oid (str): ID of Object we are going to request
range_file (str): file where payload range data will be written
bearer (str): path to Bearer Token file, appends to `--bearer` key
range_cut (str): range to take data from in the form offset:length
options (optional, str): any options which `neofs-cli object range` accepts
Returns:
None
'''
cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {NEOFS_ENDPOINT} --wallet {wif} '
f'object range --cid {cid} --oid {oid} --range {range_cut} '
f'--file {ASSETS_DIR}/{range_file} {options}'
f'{"--bearer " + bearer if bearer else ""} '
)
_cmd_run(cmd)
@keyword('Search object')
def search_object(wif: str, cid: str, keys: str="", bearer: str="", filters: dict={},
expected_objects_list=[], options:str=""):
'''
GETRANGE an Object.
Args:
wif (str): WIF of the wallet on whose behalf SEARCH is done
cid (str): ID of Container where we get the Object from
keys(optional, str): any keys for Object SEARCH which `neofs-cli object search`
accepts, e.g. `--oid`
bearer (optional, str): path to Bearer Token file, appends to `--bearer` key
filters (optional, dict): key=value pairs to filter Objects
expected_objects_list (optional, list): a list of ObjectIDs to compare found Objects with
options (optional, str): any options which `neofs-cli object search` accepts
Returns:
(list): list of found ObjectIDs
'''
filters_result = ""
if filters:
filters_result += "--filters "
logger.info(filters)
for key, value in filters.items():
filters_result += f"'{key} EQ {value}' "
cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {NEOFS_ENDPOINT} --wallet {wif} '
f'object search {keys} --cid {cid} {filters_result} {options}'
f'{"--bearer " + bearer if bearer else ""} '
)
output = _cmd_run(cmd)
found_objects = re.findall(r'(\w{43,44})', output)
if expected_objects_list:
if sorted(found_objects) == sorted(expected_objects_list):
logger.info(f"Found objects list '{found_objects}' ",
f"is equal for expected list '{expected_objects_list}'")
else:
raise Exception(f"Found object list {found_objects} ",
f"is not equal to expected list '{expected_objects_list}'")
return found_objects
@keyword('Head object')
def head_object(wif: str, cid: str, oid: str, bearer_token: str="",
options:str="", endpoint: str="", json_output: bool = True,
is_raw: bool = False):
'''
HEAD an Object.
Args:
wif (str): WIF of the wallet on whose behalf HEAD is done
cid (str): ID of Container where we get the Object from
oid (str): ObjectID to HEAD
bearer_token (optional, str): path to Bearer Token file, appends to `--bearer` key
options (optional, str): any options which `neofs-cli object head` accepts
endpoint(optional, str): NeoFS endpoint to send request to
json_output(optional, bool): return reponse in JSON format or not; this flag
turns into `--json` key
is_raw(optional, bool): send "raw" request or not; this flag
turns into `--raw` key
Returns:
depending on the `json_output` parameter value, the function returns
(dict): HEAD response in JSON format
or
(str): HEAD response as a plain text
'''
cmd = (
f'{NEOFS_CLI_EXEC} --rpc-endpoint {endpoint if endpoint else NEOFS_ENDPOINT} '
f'--wallet {wif} '
f'object head --cid {cid} --oid {oid} {options} '
f'{"--bearer " + bearer_token if bearer_token else ""} '
f'{"--json" if json_output else ""} '
f'{"--raw" if is_raw else ""}'
)
output = _cmd_run(cmd)
if not json_output:
return output
decoded = ""
try:
decoded = json.loads(output)
except Exception as exc:
# If we failed to parse output as JSON, the cause might be
# the plain text string in the beginning of the output.
# Here we cut off first string and try to parse again.
logger.info(f"failed to parse output: {exc}")
logger.info("parsing output in another way")
fst_line_idx = output.find('\n')
decoded = json.loads(output[fst_line_idx:])
# If response is Complex Object header, it has `splitId` key
if 'splitId' in decoded.keys():
logger.info("decoding split header")
return json_transformers.decode_split_header(decoded)
# If response is Last or Linking Object header,
# it has `header` dictionary and non-null `split` dictionary
if 'split' in decoded['header'].keys():
if decoded['header']['split']:
logger.info("decoding linking object")
return json_transformers.decode_linking_object(decoded)
if decoded['header']['objectType'] == 'STORAGE_GROUP':
logger.info("decoding storage group")
return json_transformers.decode_storage_group(decoded)
logger.info("decoding simple header")
return json_transformers.decode_simple_header(decoded)
def _dict_to_attrs(attrs: dict):
'''
This function takes dictionary of object attributes and converts them
into the string. The string is passed to `--attibutes` key of the
neofs-cli.
Args:
attrs (dict): object attirbutes in {"a": "b", "c": "d"} format.
Returns:
(str): string in "a=b,c=d" format.
'''
return reduce(lambda a,b: f"{a},{b}", map(lambda i: f"{i}={attrs[i]}", attrs))

View file

@ -4,6 +4,7 @@ Variables eacl_object_filters.py
Library acl.py Library acl.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library Collections Library Collections
Resource common_steps_acl_basic.robot Resource common_steps_acl_basic.robot
@ -91,7 +92,7 @@ Check eACL Deny and Allow All
Compose eACL Custom Compose eACL Custom
[Arguments] ${CID} ${HEADER_DICT} ${MATCH_TYPE} ${FILTER} ${ACCESS} ${ROLE} [Arguments] ${CID} ${HEADER_DICT} ${MATCH_TYPE} ${FILTER} ${ACCESS} ${ROLE}
${filter_value} = Get From dictionary ${HEADER_DICT}[header] ${EACL_OBJ_FILTERS}[${FILTER}] ${filter_value} = Get From dictionary ${HEADER_DICT} ${EACL_OBJ_FILTERS}[${FILTER}]
${filters} = Set Variable obj:${FILTER}${MATCH_TYPE}${filter_value} ${filters} = Set Variable obj:${FILTER}${MATCH_TYPE}${filter_value}
${rule_get}= Set Variable ${ACCESS} get ${filters} ${ROLE} ${rule_get}= Set Variable ${ACCESS} get ${filters} ${ROLE}
@ -112,8 +113,12 @@ Object Header Decoded
[Arguments] ${USER_KEY} ${CID} ${OID} [Arguments] ${USER_KEY} ${CID} ${OID}
&{HEADER} = Head Object ${USER_KEY} ${CID} ${OID} &{HEADER} = Head Object ${USER_KEY} ${CID} ${OID}
# FIXME
# 'objectID' key repositioning in dictionary for the calling keyword might
# work uniformly with any key from 'header'
Set To Dictionary ${HEADER}[header] objectID ${HEADER}[objectID]
[Return] &{HEADER} [Return] &{HEADER}[header]
Check eACL Filters with MatchType String Equal Check eACL Filters with MatchType String Equal
[Arguments] ${FILTER} [Arguments] ${FILTER}

View file

@ -2,6 +2,7 @@
Variables common.py Variables common.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Resource common_steps_acl_basic.robot Resource common_steps_acl_basic.robot

View file

@ -2,6 +2,7 @@
Variables common.py Variables common.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Library Collections Library Collections
@ -13,20 +14,20 @@ Resource setup_teardown.robot
*** Test cases *** *** Test cases ***
Basic ACL Operations for Private Container Basic ACL Operations for Private Container
[Documentation] Testcase to validate NeoFS operations with ACL for Private Container. [Documentation] Testcase to validate NeoFS operations with ACL for Private Container.
[Tags] ACL NeoFS NeoCLI [Tags] ACL
[Timeout] 20 min [Timeout] 20 min
[Setup] Setup [Setup] Setup
${WALLET} ${ADDR} ${USER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${USER_KEY} = Prepare Wallet And Deposit
${WALLET_OTH} ${ADDR_OTH} ${OTHER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${OTHER_KEY} = Prepare Wallet And Deposit
${PRIV_CID} = Create Private Container ${USER_KEY} ${PRIV_CID} = Create Private Container ${USER_KEY}
${FILE_S} ${FILE_S_HASH} = Generate file ${SIMPLE_OBJ_SIZE} ${FILE_S} ${_} = Generate file ${SIMPLE_OBJ_SIZE}
Check Private Container Simple ${USER_KEY} ${FILE_S} ${PRIV_CID} ${OTHER_KEY} Check Private Container Simple ${USER_KEY} ${FILE_S} ${PRIV_CID} ${OTHER_KEY}
${PRIV_CID} = Create Private Container ${USER_KEY} ${PRIV_CID} = Create Private Container ${USER_KEY}
${FILE_S} ${FILE_S_HASH} = Generate file ${COMPLEX_OBJ_SIZE} ${FILE_S} ${_} = Generate file ${COMPLEX_OBJ_SIZE}
Check Private Container Complex ${USER_KEY} ${FILE_S} ${PRIV_CID} ${OTHER_KEY} Check Private Container Complex ${USER_KEY} ${FILE_S} ${PRIV_CID} ${OTHER_KEY}
[Teardown] Teardown acl_basic_private_container_storagegroup [Teardown] Teardown acl_basic_private_container_storagegroup
@ -38,7 +39,7 @@ Check Private Container
[Arguments] ${RUN_TYPE} ${USER_KEY} ${FILE_S} ${PRIV_CID} ${OTHER_KEY} [Arguments] ${RUN_TYPE} ${USER_KEY} ${FILE_S} ${PRIV_CID} ${OTHER_KEY}
# Put target object to use in storage groups # Put target object to use in storage groups
${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${PRIV_CID} ${EMPTY} ${EMPTY} ${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${PRIV_CID}
# Storage group Operations (Put, List, Get, Delete) with different Keys # Storage group Operations (Put, List, Get, Delete) with different Keys

View file

@ -2,6 +2,7 @@
Variables common.py Variables common.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Resource common_steps_acl_basic.robot Resource common_steps_acl_basic.robot
@ -12,20 +13,20 @@ Resource setup_teardown.robot
*** Test cases *** *** Test cases ***
Basic ACL Operations for Public Container Basic ACL Operations for Public Container
[Documentation] Testcase to validate NeoFS operations with ACL for Public Container. [Documentation] Testcase to validate NeoFS operations with ACL for Public Container.
[Tags] ACL NeoFS NeoCLI [Tags] ACL
[Timeout] 20 min [Timeout] 20 min
[Setup] Setup [Setup] Setup
${WALLET} ${ADDR} ${USER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${USER_KEY} = Prepare Wallet And Deposit
${WALLET_OTH} ${ADDR_OTH} ${OTHER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${OTHER_KEY} = Prepare Wallet And Deposit
${PUBLIC_CID} = Create Public Container ${USER_KEY} ${PUBLIC_CID} = Create Public Container ${USER_KEY}
${FILE_S} ${FILE_S_HASH} = Generate file ${SIMPLE_OBJ_SIZE} ${FILE_S} ${_} = Generate file ${SIMPLE_OBJ_SIZE}
Check Public Container ${USER_KEY} ${FILE_S} ${PUBLIC_CID} ${OTHER_KEY} Check Public Container ${USER_KEY} ${FILE_S} ${PUBLIC_CID} ${OTHER_KEY}
${PUBLIC_CID} = Create Public Container ${USER_KEY} ${PUBLIC_CID} = Create Public Container ${USER_KEY}
${FILE_S} ${FILE_S_HASH} = Generate file ${COMPLEX_OBJ_SIZE} ${FILE_S} ${_} = Generate file ${COMPLEX_OBJ_SIZE}
Check Public Container ${USER_KEY} ${FILE_S} ${PUBLIC_CID} ${OTHER_KEY} Check Public Container ${USER_KEY} ${FILE_S} ${PUBLIC_CID} ${OTHER_KEY}
[Teardown] Teardown acl_basic_public_container [Teardown] Teardown acl_basic_public_container
@ -37,10 +38,10 @@ Check Public Container
[Arguments] ${USER_KEY} ${FILE_S} ${PUBLIC_CID} ${OTHER_KEY} [Arguments] ${USER_KEY} ${FILE_S} ${PUBLIC_CID} ${OTHER_KEY}
# Put # Put
${S_OID_USER} = Put Object ${USER_KEY} ${FILE_S} ${PUBLIC_CID} ${EMPTY} ${EMPTY} ${S_OID_USER} = Put Object ${USER_KEY} ${FILE_S} ${PUBLIC_CID}
${S_OID_OTHER} = Put Object ${OTHER_KEY} ${FILE_S} ${PUBLIC_CID} ${EMPTY} ${EMPTY} ${S_OID_OTHER} = Put Object ${OTHER_KEY} ${FILE_S} ${PUBLIC_CID}
${S_OID_SYS_IR} = Put Object ${NEOFS_IR_WIF} ${FILE_S} ${PUBLIC_CID} ${EMPTY} ${EMPTY} ${S_OID_SYS_IR} = Put Object ${NEOFS_IR_WIF} ${FILE_S} ${PUBLIC_CID}
${S_OID_SYS_SN} = Put Object ${NEOFS_SN_WIF} ${FILE_S} ${PUBLIC_CID} ${EMPTY} ${EMPTY} ${S_OID_SYS_SN} = Put Object ${NEOFS_SN_WIF} ${FILE_S} ${PUBLIC_CID}
# Get # Get
Get Object ${USER_KEY} ${PUBLIC_CID} ${S_OID_USER} ${EMPTY} s_file_read Get Object ${USER_KEY} ${PUBLIC_CID} ${S_OID_USER} ${EMPTY} s_file_read
@ -65,32 +66,32 @@ Check Public Container
# Search # Search
@{S_OBJ_PRIV} = Create List ${S_OID_USER} ${S_OID_OTHER} ${S_OID_SYS_SN} ${S_OID_SYS_IR} @{S_OBJ_PRIV} = Create List ${S_OID_USER} ${S_OID_OTHER} ${S_OID_SYS_SN} ${S_OID_SYS_IR}
Search object ${USER_KEY} ${PUBLIC_CID} --root ${EMPTY} ${EMPTY} ${S_OBJ_PRIV} Search object ${USER_KEY} ${PUBLIC_CID} keys=--root expected_objects_list=${S_OBJ_PRIV}
Search object ${OTHER_KEY} ${PUBLIC_CID} --root ${EMPTY} ${EMPTY} ${S_OBJ_PRIV} Search object ${OTHER_KEY} ${PUBLIC_CID} keys=--root expected_objects_list=${S_OBJ_PRIV}
Search object ${NEOFS_IR_WIF} ${PUBLIC_CID} --root ${EMPTY} ${EMPTY} ${S_OBJ_PRIV} Search object ${NEOFS_IR_WIF} ${PUBLIC_CID} keys=--root expected_objects_list=${S_OBJ_PRIV}
Search object ${NEOFS_SN_WIF} ${PUBLIC_CID} --root ${EMPTY} ${EMPTY} ${S_OBJ_PRIV} Search object ${NEOFS_SN_WIF} ${PUBLIC_CID} keys=--root expected_objects_list=${S_OBJ_PRIV}
# Head # Head
Head Object ${USER_KEY} ${PUBLIC_CID} ${S_OID_USER} ${EMPTY} ${EMPTY} Head Object ${USER_KEY} ${PUBLIC_CID} ${S_OID_USER}
Head Object ${OTHER_KEY} ${PUBLIC_CID} ${S_OID_USER} ${EMPTY} ${EMPTY} Head Object ${OTHER_KEY} ${PUBLIC_CID} ${S_OID_USER}
Head Object ${NEOFS_IR_WIF} ${PUBLIC_CID} ${S_OID_USER} ${EMPTY} ${EMPTY} Head Object ${NEOFS_IR_WIF} ${PUBLIC_CID} ${S_OID_USER}
Head Object ${NEOFS_SN_WIF} ${PUBLIC_CID} ${S_OID_USER} ${EMPTY} ${EMPTY} Head Object ${NEOFS_SN_WIF} ${PUBLIC_CID} ${S_OID_USER}
Head Object ${USER_KEY} ${PUBLIC_CID} ${S_OID_OTHER} ${EMPTY} ${EMPTY} Head Object ${USER_KEY} ${PUBLIC_CID} ${S_OID_OTHER}
Head Object ${OTHER_KEY} ${PUBLIC_CID} ${S_OID_OTHER} ${EMPTY} ${EMPTY} Head Object ${OTHER_KEY} ${PUBLIC_CID} ${S_OID_OTHER}
Head Object ${NEOFS_IR_WIF} ${PUBLIC_CID} ${S_OID_OTHER} ${EMPTY} ${EMPTY} Head Object ${NEOFS_IR_WIF} ${PUBLIC_CID} ${S_OID_OTHER}
Head Object ${NEOFS_SN_WIF} ${PUBLIC_CID} ${S_OID_OTHER} ${EMPTY} ${EMPTY} Head Object ${NEOFS_SN_WIF} ${PUBLIC_CID} ${S_OID_OTHER}
Head Object ${USER_KEY} ${PUBLIC_CID} ${S_OID_SYS_SN} ${EMPTY} ${EMPTY} Head Object ${USER_KEY} ${PUBLIC_CID} ${S_OID_SYS_SN}
Head Object ${OTHER_KEY} ${PUBLIC_CID} ${S_OID_SYS_SN} ${EMPTY} ${EMPTY} Head Object ${OTHER_KEY} ${PUBLIC_CID} ${S_OID_SYS_SN}
Head Object ${NEOFS_IR_WIF} ${PUBLIC_CID} ${S_OID_SYS_SN} ${EMPTY} ${EMPTY} Head Object ${NEOFS_IR_WIF} ${PUBLIC_CID} ${S_OID_SYS_SN}
Head Object ${NEOFS_SN_WIF} ${PUBLIC_CID} ${S_OID_SYS_SN} ${EMPTY} ${EMPTY} Head Object ${NEOFS_SN_WIF} ${PUBLIC_CID} ${S_OID_SYS_SN}
# Delete # Delete
Delete object ${USER_KEY} ${PUBLIC_CID} ${S_OID_SYS_IR} ${EMPTY} Delete object ${USER_KEY} ${PUBLIC_CID} ${S_OID_SYS_IR}
Delete Object ${OTHER_KEY} ${PUBLIC_CID} ${S_OID_SYS_SN} ${EMPTY} Delete Object ${OTHER_KEY} ${PUBLIC_CID} ${S_OID_SYS_SN}
Run Keyword And Expect Error * Run Keyword And Expect Error *
... Delete object ${NEOFS_IR_WIF} ${PUBLIC_CID} ${S_OID_USER} ${EMPTY} ... Delete object ${NEOFS_IR_WIF} ${PUBLIC_CID} ${S_OID_USER}
Run Keyword And Expect Error * Run Keyword And Expect Error *
... Delete object ${NEOFS_SN_WIF} ${PUBLIC_CID} ${S_OID_OTHER} ${EMPTY} ... Delete object ${NEOFS_SN_WIF} ${PUBLIC_CID} ${S_OID_OTHER}

View file

@ -2,6 +2,7 @@
Variables common.py Variables common.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Library contract_keywords.py Library contract_keywords.py
@ -13,20 +14,20 @@ Resource setup_teardown.robot
*** Test cases *** *** Test cases ***
Basic ACL Operations for Public Container Basic ACL Operations for Public Container
[Documentation] Testcase to validate NeoFS operations with ACL for Public Container. [Documentation] Testcase to validate NeoFS operations with ACL for Public Container.
[Tags] ACL NeoFS NeoCLI [Tags] ACL
[Timeout] 20 min [Timeout] 20 min
[Setup] Setup [Setup] Setup
${WALLET} ${ADDR} ${USER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${USER_KEY} = Prepare Wallet And Deposit
${WALLET_OTH} ${ADDR_OTH} ${OTHER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${OTHER_KEY} = Prepare Wallet And Deposit
${PUBLIC_CID} = Create Public Container ${USER_KEY} ${PUBLIC_CID} = Create Public Container ${USER_KEY}
${FILE_S} ${FILE_S_HASH} = Generate file ${SIMPLE_OBJ_SIZE} ${FILE_S} ${_} = Generate file ${SIMPLE_OBJ_SIZE}
Check Public Container Simple ${USER_KEY} ${FILE_S} ${PUBLIC_CID} ${OTHER_KEY} Check Public Container Simple ${USER_KEY} ${FILE_S} ${PUBLIC_CID} ${OTHER_KEY}
${PUBLIC_CID} = Create Public Container ${USER_KEY} ${PUBLIC_CID} = Create Public Container ${USER_KEY}
${FILE_S} ${FILE_S_HASH} = Generate file ${COMPLEX_OBJ_SIZE} ${FILE_S} ${_} = Generate file ${COMPLEX_OBJ_SIZE}
Check Public Container Complex ${USER_KEY} ${FILE_S} ${PUBLIC_CID} ${OTHER_KEY} Check Public Container Complex ${USER_KEY} ${FILE_S} ${PUBLIC_CID} ${OTHER_KEY}
[Teardown] Teardown acl_basic_public_container_storagegroup [Teardown] Teardown acl_basic_public_container_storagegroup
@ -41,7 +42,7 @@ Check Public Container
Log Storage group Operations for each Role keys Log Storage group Operations for each Role keys
# Put target object to use in storage groups # Put target object to use in storage groups
${S_OID} = Put object ${USER_KEY} ${FILE_S} ${PUBLIC_CID} ${EMPTY} ${EMPTY} ${S_OID} = Put object ${USER_KEY} ${FILE_S} ${PUBLIC_CID}
@{ROLES_KEYS_PASS} = Create List ${USER_KEY} ${OTHER_KEY} @{ROLES_KEYS_PASS} = Create List ${USER_KEY} ${OTHER_KEY}
@{ROLES_KEYS_SYS} = Create List ${NEOFS_IR_WIF} ${NEOFS_SN_WIF} @{ROLES_KEYS_SYS} = Create List ${NEOFS_IR_WIF} ${NEOFS_SN_WIF}

View file

@ -2,6 +2,7 @@
Variables common.py Variables common.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Resource common_steps_acl_basic.robot Resource common_steps_acl_basic.robot
@ -12,20 +13,20 @@ Resource setup_teardown.robot
*** Test cases *** *** Test cases ***
Basic ACL Operations for Read-Only Container Basic ACL Operations for Read-Only Container
[Documentation] Testcase to validate NeoFS operations with ACL for Read-Only Container. [Documentation] Testcase to validate NeoFS operations with ACL for Read-Only Container.
[Tags] ACL NeoFS NeoCLI [Tags] ACL
[Timeout] 20 min [Timeout] 20 min
[Setup] Setup [Setup] Setup
${WALLET} ${ADDR} ${USER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${USER_KEY} = Prepare Wallet And Deposit
${WALLET_OTH} ${ADDR_OTH} ${OTHER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${OTHER_KEY} = Prepare Wallet And Deposit
${READONLY_CID} = Create Read-Only Container ${USER_KEY} ${READONLY_CID} = Create Read-Only Container ${USER_KEY}
${FILE_S} ${FILE_S_HASH} = Generate file ${SIMPLE_OBJ_SIZE} ${FILE_S} ${_} = Generate file ${SIMPLE_OBJ_SIZE}
Check Read-Only Container Simple ${USER_KEY} ${FILE_S} ${READONLY_CID} ${OTHER_KEY} Check Read-Only Container Simple ${USER_KEY} ${FILE_S} ${READONLY_CID} ${OTHER_KEY}
${READONLY_CID} = Create Read-Only Container ${USER_KEY} ${READONLY_CID} = Create Read-Only Container ${USER_KEY}
${FILE_S} ${FILE_S_HASH} = Generate file ${COMPLEX_OBJ_SIZE} ${FILE_S} ${_} = Generate file ${COMPLEX_OBJ_SIZE}
Check Read-Only Container Complex ${USER_KEY} ${FILE_S} ${READONLY_CID} ${OTHER_KEY} Check Read-Only Container Complex ${USER_KEY} ${FILE_S} ${READONLY_CID} ${OTHER_KEY}
[Teardown] Teardown acl_basic_readonly_container [Teardown] Teardown acl_basic_readonly_container
@ -38,11 +39,11 @@ Check Read-Only Container
[Arguments] ${RUN_TYPE} ${USER_KEY} ${FILE_S} ${READONLY_CID} ${OTHER_KEY} [Arguments] ${RUN_TYPE} ${USER_KEY} ${FILE_S} ${READONLY_CID} ${OTHER_KEY}
# Put # Put
${S_OID_USER} = Put Object ${USER_KEY} ${FILE_S} ${READONLY_CID} ${EMPTY} ${EMPTY} ${S_OID_USER} = Put Object ${USER_KEY} ${FILE_S} ${READONLY_CID}
Run Keyword And Expect Error * Run Keyword And Expect Error *
... Put object ${OTHER_KEY} ${FILE_S} ${READONLY_CID} ${EMPTY} ${EMPTY} ... Put object ${OTHER_KEY} ${FILE_S} ${READONLY_CID}
${S_OID_SYS_IR} = Put Object ${NEOFS_IR_WIF} ${FILE_S} ${READONLY_CID} ${EMPTY} ${EMPTY} ${S_OID_SYS_IR} = Put Object ${NEOFS_IR_WIF} ${FILE_S} ${READONLY_CID}
${S_OID_SYS_SN} = Put object ${NEOFS_SN_WIF} ${FILE_S} ${READONLY_CID} ${EMPTY} ${EMPTY} ${S_OID_SYS_SN} = Put object ${NEOFS_SN_WIF} ${FILE_S} ${READONLY_CID}
# Storage group Operations (Put, List, Get, Delete) # Storage group Operations (Put, List, Get, Delete)
@ -94,23 +95,23 @@ Check Read-Only Container
# Search # Search
@{S_OBJ_RO} = Create List ${S_OID_USER} ${S_OID_SYS_SN} ${S_OID_SYS_IR} @{S_OBJ_RO} = Create List ${S_OID_USER} ${S_OID_SYS_SN} ${S_OID_SYS_IR}
Search Object ${USER_KEY} ${READONLY_CID} --root ${EMPTY} ${EMPTY} ${S_OBJ_RO} Search Object ${USER_KEY} ${READONLY_CID} keys=--root expected_objects_list=${S_OBJ_RO}
Search Object ${OTHER_KEY} ${READONLY_CID} --root ${EMPTY} ${EMPTY} ${S_OBJ_RO} Search Object ${OTHER_KEY} ${READONLY_CID} keys=--root expected_objects_list=${S_OBJ_RO}
Search Object ${NEOFS_IR_WIF} ${READONLY_CID} --root ${EMPTY} ${EMPTY} ${S_OBJ_RO} Search Object ${NEOFS_IR_WIF} ${READONLY_CID} keys=--root expected_objects_list=${S_OBJ_RO}
Search Object ${NEOFS_SN_WIF} ${READONLY_CID} --root ${EMPTY} ${EMPTY} ${S_OBJ_RO} Search Object ${NEOFS_SN_WIF} ${READONLY_CID} keys=--root expected_objects_list=${S_OBJ_RO}
# Head # Head
Head Object ${USER_KEY} ${READONLY_CID} ${S_OID_USER} ${EMPTY} ${EMPTY} Head Object ${USER_KEY} ${READONLY_CID} ${S_OID_USER}
Head Object ${OTHER_KEY} ${READONLY_CID} ${S_OID_USER} ${EMPTY} ${EMPTY} Head Object ${OTHER_KEY} ${READONLY_CID} ${S_OID_USER}
Head Object ${NEOFS_IR_WIF} ${READONLY_CID} ${S_OID_USER} ${EMPTY} ${EMPTY} Head Object ${NEOFS_IR_WIF} ${READONLY_CID} ${S_OID_USER}
Head Object ${NEOFS_SN_WIF} ${READONLY_CID} ${S_OID_USER} ${EMPTY} ${EMPTY} Head Object ${NEOFS_SN_WIF} ${READONLY_CID} ${S_OID_USER}
# Delete # Delete
Run Keyword And Expect Error * Run Keyword And Expect Error *
... Delete object ${OTHER_KEY} ${READONLY_CID} ${S_OID_USER} ${EMPTY} ... Delete object ${OTHER_KEY} ${READONLY_CID} ${S_OID_USER}
Run Keyword And Expect Error * Run Keyword And Expect Error *
... Delete object ${NEOFS_IR_WIF} ${READONLY_CID} ${S_OID_USER} ${EMPTY} ... Delete object ${NEOFS_IR_WIF} ${READONLY_CID} ${S_OID_USER}
Run Keyword And Expect Error * Run Keyword And Expect Error *
... Delete object ${NEOFS_SN_WIF} ${READONLY_CID} ${S_OID_USER} ${EMPTY} ... Delete object ${NEOFS_SN_WIF} ${READONLY_CID} ${S_OID_USER}
Delete Object ${USER_KEY} ${READONLY_CID} ${S_OID_USER} ${EMPTY} Delete Object ${USER_KEY} ${READONLY_CID} ${S_OID_USER}

View file

@ -2,6 +2,7 @@
Variables common.py Variables common.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Resource common_steps_acl_basic.robot Resource common_steps_acl_basic.robot
@ -12,20 +13,20 @@ Resource setup_teardown.robot
*** Test cases *** *** Test cases ***
Basic ACL Operations for Read-Only Container Basic ACL Operations for Read-Only Container
[Documentation] Testcase to validate NeoFS operations with ACL for Read-Only Container. [Documentation] Testcase to validate NeoFS operations with ACL for Read-Only Container.
[Tags] ACL NeoFS NeoCLI [Tags] ACL
[Timeout] 20 min [Timeout] 20 min
[Setup] Setup [Setup] Setup
${WALLET} ${ADDR} ${USER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${USER_KEY} = Prepare Wallet And Deposit
${WALLET_OTH} ${ADDR_OTH} ${OTHER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${OTHER_KEY} = Prepare Wallet And Deposit
${READONLY_CID} = Create Read-Only Container ${USER_KEY} ${READONLY_CID} = Create Read-Only Container ${USER_KEY}
${FILE_S} ${FILE_S_HASH} = Generate file ${SIMPLE_OBJ_SIZE} ${FILE_S} ${_} = Generate file ${SIMPLE_OBJ_SIZE}
Check Read-Only Container Simple ${USER_KEY} ${FILE_S} ${READONLY_CID} ${OTHER_KEY} Check Read-Only Container Simple ${USER_KEY} ${FILE_S} ${READONLY_CID} ${OTHER_KEY}
${READONLY_CID} = Create Read-Only Container ${USER_KEY} ${READONLY_CID} = Create Read-Only Container ${USER_KEY}
${FILE_S} ${FILE_S_HASH} = Generate file ${COMPLEX_OBJ_SIZE} ${FILE_S} ${_} = Generate file ${COMPLEX_OBJ_SIZE}
Check Read-Only Container Complex ${USER_KEY} ${FILE_S} ${READONLY_CID} ${OTHER_KEY} Check Read-Only Container Complex ${USER_KEY} ${FILE_S} ${READONLY_CID} ${OTHER_KEY}
@ -39,7 +40,7 @@ Check Read-Only Container
[Arguments] ${RUN_TYPE} ${USER_KEY} ${FILE_S} ${READONLY_CID} ${OTHER_KEY} [Arguments] ${RUN_TYPE} ${USER_KEY} ${FILE_S} ${READONLY_CID} ${OTHER_KEY}
# Put target object to use in storage groups # Put target object to use in storage groups
${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${READONLY_CID} ${EMPTY} ${EMPTY} ${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${READONLY_CID}
# Storage group Operations (Put, List, Get, Delete) for Read-only container # Storage group Operations (Put, List, Get, Delete) for Read-only container

View file

@ -3,6 +3,7 @@ Variables common.py
Library Collections Library Collections
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library acl.py Library acl.py
Library payment_neogo.py Library payment_neogo.py

View file

@ -4,6 +4,7 @@ Variables common.py
Library Collections Library Collections
Library acl.py Library acl.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Resource eacl_tables.robot Resource eacl_tables.robot
@ -15,13 +16,13 @@ Resource setup_teardown.robot
*** Test cases *** *** Test cases ***
BearerToken Operations BearerToken Operations
[Documentation] Testcase to validate NeoFS operations with BearerToken. [Documentation] Testcase to validate NeoFS operations with BearerToken.
[Tags] ACL NeoFS NeoCLI BearerToken [Tags] ACL BearerToken
[Timeout] 20 min [Timeout] 20 min
[Setup] Setup [Setup] Setup
${WALLET} ${ADDR} ${USER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${USER_KEY} = Prepare Wallet And Deposit
Log Check Bearer token with simple object Log Check Bearer token with simple object
${FILE_S} = Generate file ${SIMPLE_OBJ_SIZE} ${FILE_S} = Generate file ${SIMPLE_OBJ_SIZE}
Check eACL Deny and Allow All Bearer Simple ${USER_KEY} ${FILE_S} Check eACL Deny and Allow All Bearer Simple ${USER_KEY} ${FILE_S}
@ -39,10 +40,10 @@ BearerToken Operations
Check eACL Deny and Allow All Bearer Check eACL Deny and Allow All Bearer
[Arguments] ${RUN_TYPE} ${USER_KEY} ${FILE_S} [Arguments] ${RUN_TYPE} ${USER_KEY} ${FILE_S}
${CID} = Create Container Public ${USER_KEY} ${CID} = Create Container Public ${USER_KEY}
${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} ${EMPTY} ${FILE_USR_HEADER} ${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID}
Prepare eACL Role rules ${CID} Prepare eACL Role rules ${CID}
# Storage group Operations (Put, List, Get, Delete) # Storage group Operations (Put, List, Get, Delete)

View file

@ -4,6 +4,7 @@ Variables common.py
Library Collections Library Collections
Library acl.py Library acl.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Resource eacl_tables.robot Resource eacl_tables.robot
@ -59,7 +60,7 @@ Check Bearer Сompound Get
${CID} = Create Container Public ${USER_KEY} ${CID} = Create Container Public ${USER_KEY}
Prepare eACL Role rules ${CID} Prepare eACL Role rules ${CID}
${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER} ${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER}
@{S_OBJ_H} = Create List ${S_OID_USER} @{S_OBJ_H} = Create List ${S_OID_USER}
${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER} ${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER}
Put object ${KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_HEADER} Put object ${KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_HEADER}

View file

@ -3,6 +3,7 @@ Variables common.py
Library Collections Library Collections
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library acl.py Library acl.py
Library payment_neogo.py Library payment_neogo.py
@ -50,7 +51,7 @@ Check eACL Deny and Allow All Bearer Filter OID Equal
${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER} ${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER}
${S_OID_USER_2} = Put object ${USER_KEY} ${FILE_S} ${CID} ${S_OID_USER_2} = Put object ${USER_KEY} ${FILE_S} ${CID}
${D_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER_DEL} ${D_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER_DEL}
@{S_OBJ_H} = Create List ${S_OID_USER} @{S_OBJ_H} = Create List ${S_OID_USER}
Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_HEADER} Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_HEADER}
Get object ${USER_KEY} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl Get object ${USER_KEY} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl

View file

@ -3,6 +3,7 @@ Variables common.py
Library Collections Library Collections
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library acl.py Library acl.py
Library payment_neogo.py Library payment_neogo.py
@ -47,7 +48,7 @@ Check eACL Deny and Allow All Bearer Filter OID NotEqual
${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER} ${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER}
${S_OID_USER_2} = Put object ${USER_KEY} ${FILE_S} ${CID} ${S_OID_USER_2} = Put object ${USER_KEY} ${FILE_S} ${CID}
${D_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} ${D_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID}
@{S_OBJ_H} = Create List ${S_OID_USER} @{S_OBJ_H} = Create List ${S_OID_USER}
Put object ${USER_KEY} ${FILE_S} ${CID} Put object ${USER_KEY} ${FILE_S} ${CID}
Get object ${USER_KEY} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl Get object ${USER_KEY} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl

View file

@ -4,6 +4,7 @@ Variables common.py
Library Collections Library Collections
Library acl.py Library acl.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Resource eacl_tables.robot Resource eacl_tables.robot
@ -45,7 +46,7 @@ Check eACL Deny and Allow All Bearer Filter UserHeader Equal
${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER} ${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER}
${S_OID_USER_2} = Put object ${USER_KEY} ${FILE_S} ${CID} ${S_OID_USER_2} = Put object ${USER_KEY} ${FILE_S} ${CID}
${D_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER_DEL} ${D_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER_DEL}
@{S_OBJ_H} = Create List ${S_OID_USER} @{S_OBJ_H} = Create List ${S_OID_USER}
Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_HEADER} Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_HEADER}
Get object ${USER_KEY} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl Get object ${USER_KEY} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl

View file

@ -3,6 +3,7 @@ Variables common.py
Library Collections Library Collections
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library acl.py Library acl.py
Library payment_neogo.py Library payment_neogo.py
@ -46,7 +47,7 @@ Check eACL Deny and Allow All Bearer Filter UserHeader NotEqual
${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_HEADER} ${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_HEADER}
${S_OID_USER_2} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER} ${S_OID_USER_2} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER}
${D_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER_DEL} ${D_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER_DEL}
@{S_OBJ_H} = Create List ${S_OID_USER_2} @{S_OBJ_H} = Create List ${S_OID_USER_2}
Put object ${USER_KEY} ${FILE_S} ${CID} Put object ${USER_KEY} ${FILE_S} ${CID}
Get object ${USER_KEY} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl Get object ${USER_KEY} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl

View file

@ -3,6 +3,7 @@ Variables common.py
Library Collections Library Collections
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library acl.py Library acl.py
Library payment_neogo.py Library payment_neogo.py

View file

@ -3,6 +3,7 @@ Variables common.py
Library Collections Library Collections
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library acl.py Library acl.py
Library payment_neogo.py Library payment_neogo.py

View file

@ -4,6 +4,7 @@ Variables common.py
Library Collections Library Collections
Library acl.py Library acl.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Resource eacl_tables.robot Resource eacl_tables.robot
@ -48,7 +49,7 @@ Check eACL Deny and Allow All Bearer Filter Requst Equal
${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER} ${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER}
${S_OID_USER_2} = Put object ${USER_KEY} ${FILE_S} ${CID} ${S_OID_USER_2} = Put object ${USER_KEY} ${FILE_S} ${CID}
${D_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER_DEL} ${D_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER_DEL}
@{S_OBJ_H} = Create List ${S_OID_USER} @{S_OBJ_H} = Create List ${S_OID_USER}
Put object ${USER_KEY} ${FILE_S} ${CID} Put object ${USER_KEY} ${FILE_S} ${CID}
Get object ${USER_KEY} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl Get object ${USER_KEY} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl
@ -71,7 +72,7 @@ Check eACL Deny and Allow All Bearer Filter Requst Equal
${rule6}= Create Dictionary Operation=GETRANGE Access=ALLOW Role=USER Filters=${filters} ${rule6}= Create Dictionary Operation=GETRANGE Access=ALLOW Role=USER Filters=${filters}
${rule7}= Create Dictionary Operation=GETRANGEHASH Access=ALLOW Role=USER Filters=${filters} ${rule7}= Create Dictionary Operation=GETRANGEHASH Access=ALLOW Role=USER Filters=${filters}
${eACL_gen}= Create List ${rule1} ${rule2} ${rule3} ${rule4} ${rule5} ${rule6} ${rule7} ${eACL_gen}= Create List ${rule1} ${rule2} ${rule3} ${rule4} ${rule5} ${rule6} ${rule7}
${EACL_TOKEN} = Form BearerToken File ${USER_KEY} ${CID} ${eACL_gen} ${EACL_TOKEN} = Form BearerToken File ${USER_KEY} ${CID} ${eACL_gen}
Run Keyword And Expect Error ${EACL_ERROR_MSG} Run Keyword And Expect Error ${EACL_ERROR_MSG}

View file

@ -4,6 +4,7 @@ Variables common.py
Library Collections Library Collections
Library acl.py Library acl.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Resource eacl_tables.robot Resource eacl_tables.robot
@ -46,7 +47,7 @@ Check eACL Deny and Allow All Bearer Filter Requst NotEqual
${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER} ${S_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER}
${S_OID_USER_2} = Put object ${USER_KEY} ${FILE_S} ${CID} ${S_OID_USER_2} = Put object ${USER_KEY} ${FILE_S} ${CID}
${D_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER_DEL} ${D_OID_USER} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${USER_HEADER_DEL}
@{S_OBJ_H} = Create List ${S_OID_USER} @{S_OBJ_H} = Create List ${S_OID_USER}
Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_USER_HEADER} Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_USER_HEADER}
Get object ${USER_KEY} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl Get object ${USER_KEY} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl

View file

@ -1,10 +1,8 @@
*** Settings *** *** Settings ***
Variables common.py Variables common.py
Library Collections
Library neofs.py Library neofs.py
Library payment_neogo.py Library payment_neogo.py
Library acl.py
Resource common_steps_acl_extended.robot Resource common_steps_acl_extended.robot
Resource payment_operations.robot Resource payment_operations.robot
@ -19,7 +17,7 @@ Extended ACL Operations
[Setup] Setup [Setup] Setup
${WALLET} ${ADDR} ${USER_KEY} = Prepare Wallet And Deposit ${WALLET} ${ADDR} ${USER_KEY} = Prepare Wallet And Deposit
${WALLET_OTH} ${ADDR_OTH} ${OTHER_KEY} = Prepare Wallet And Deposit ${WALLET_OTH} ${ADDR_OTH} ${OTHER_KEY} = Prepare Wallet And Deposit
Log Check extended ACL with simple object Log Check extended ACL with simple object
@ -37,4 +35,4 @@ Extended ACL Operations
Check eACL Deny and Allow All Other Check eACL Deny and Allow All Other
[Arguments] ${USER_KEY} ${OTHER_KEY} [Arguments] ${USER_KEY} ${OTHER_KEY}
Check eACL Deny and Allow All ${OTHER_KEY} ${EACL_DENY_ALL_OTHERS} ${EACL_ALLOW_ALL_OTHERS} ${USER_KEY} Check eACL Deny and Allow All ${OTHER_KEY} ${EACL_DENY_ALL_OTHERS} ${EACL_ALLOW_ALL_OTHERS} ${USER_KEY}

View file

@ -4,6 +4,7 @@ Variables common.py
Library Collections Library Collections
Library acl.py Library acl.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Resource common_steps_acl_extended.robot Resource common_steps_acl_extended.robot

View file

@ -3,6 +3,7 @@ Variables common.py
Library Collections Library Collections
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Library acl.py Library acl.py
@ -19,7 +20,7 @@ Resource eacl_tables.robot
*** Test cases *** *** Test cases ***
Extended ACL Operations Extended ACL Operations
[Documentation] Testcase to validate NeoFS operations with extended ACL. [Documentation] Testcase to validate NeoFS operations with extended ACL.
[Tags] ACL eACL NeoFS NeoCLI [Tags] ACL eACL
[Timeout] 20 min [Timeout] 20 min
[Setup] Setup [Setup] Setup

View file

@ -14,7 +14,7 @@ Resource eacl_tables.robot
*** Test cases *** *** Test cases ***
Extended ACL Operations Extended ACL Operations
[Documentation] Testcase to validate NeoFS operations with extended ACL. [Documentation] Testcase to validate NeoFS operations with extended ACL.
[Tags] ACL eACL NeoFS NeoCLI [Tags] ACL eACL
[Timeout] 20 min [Timeout] 20 min
[Setup] Setup [Setup] Setup

View file

@ -3,6 +3,7 @@ Variables common.py
Library Collections Library Collections
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Library acl.py Library acl.py

View file

@ -3,6 +3,7 @@ Variables common.py
Library Collections Library Collections
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library acl.py Library acl.py
Library payment_neogo.py Library payment_neogo.py

View file

@ -3,6 +3,7 @@ Variables common.py
Library acl.py Library acl.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Library Collections Library Collections
Library contract_keywords.py Library contract_keywords.py
@ -16,8 +17,8 @@ Resource eacl_tables.robot
${PATH} = testfile ${PATH} = testfile
&{USER_HEADER} = key1=1 key2=abc &{USER_HEADER} = key1=1 key2=abc
&{ANOTHER_HEADER} = key1=oth key2=oth &{ANOTHER_HEADER} = key1=oth key2=oth
${ID_FILTER} = $Object:objectID ${ID_FILTER} = $Object:objectID
${CUSTOM_FILTER} = $Object:key1 ${CUSTOM_FILTER} = $Object:key1
*** Test cases *** *** Test cases ***
Extended ACL Operations Extended ACL Operations
@ -96,7 +97,7 @@ Check eACL MatchType String Equal Request Allow
${CID} = Create Container Public ${USER_KEY} ${CID} = Create Container Public ${USER_KEY}
${S_OID_USER} = Put Object ${USER_KEY} ${FILE_S} ${CID} ${S_OID_USER} = Put Object ${USER_KEY} ${FILE_S} ${CID}
Get Object ${OTHER_KEY} ${CID} ${S_OID_USER} ${EMPTY} ${PATH} Get Object ${OTHER_KEY} ${CID} ${S_OID_USER} ${EMPTY} ${PATH}
Set eACL ${USER_KEY} ${CID} ${EACL_XHEADER_ALLOW_ALL} Set eACL ${USER_KEY} ${CID} ${EACL_XHEADER_ALLOW_ALL}
# The current ACL cache lifetime is 30 sec # The current ACL cache lifetime is 30 sec
@ -141,7 +142,7 @@ Check eACL MatchType String Equal Object
&{HEADER_DICT} = Head Object ${USER_KEY} ${CID} ${S_OID_USER} &{HEADER_DICT} = Head Object ${USER_KEY} ${CID} ${S_OID_USER}
${ID_value} = Get From dictionary ${HEADER_DICT} ${EACL_OBJ_FILTERS}[${ID_FILTER}] ${ID_value} = Get From dictionary ${HEADER_DICT} ${EACL_OBJ_FILTERS}[${ID_FILTER}]
${filters} = Set Variable obj:${ID_FILTER}=${ID_value} ${filters} = Set Variable obj:${ID_FILTER}=${ID_value}
${rule1} = Set Variable deny get ${filters} others ${rule1} = Set Variable deny get ${filters} others
${eACL_gen} = Create List ${rule1} ${eACL_gen} = Create List ${rule1}
@ -154,7 +155,7 @@ Check eACL MatchType String Equal Object
Log Set eACL for Deny GET operation with StringEqual Object Extended User Header Log Set eACL for Deny GET operation with StringEqual Object Extended User Header
${S_OID_USER_OTH} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_HEADER} ${S_OID_USER_OTH} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_HEADER}
${filters} = Set Variable obj:${CUSTOM_FILTER}=1 ${filters} = Set Variable obj:${CUSTOM_FILTER}=1
${rule1} = Set Variable deny get ${filters} others ${rule1} = Set Variable deny get ${filters} others
${eACL_gen} = Create List ${rule1} ${eACL_gen} = Create List ${rule1}
@ -178,10 +179,10 @@ Check eACL MatchType String Not Equal Object
Get object ${OTHER_KEY} ${CID} ${S_OID_OTHER} ${EMPTY} ${PATH} Get object ${OTHER_KEY} ${CID} ${S_OID_OTHER} ${EMPTY} ${PATH}
Log Set eACL for Deny GET operation with StringNotEqual Object ID Log Set eACL for Deny GET operation with StringNotEqual Object ID
&{HEADER_DICT} = Head object ${USER_KEY} ${CID} ${S_OID_USER} &{HEADER_DICT} = Head object ${USER_KEY} ${CID} ${S_OID_USER}
${ID_value} = Get From Dictionary ${HEADER_DICT} ${EACL_OBJ_FILTERS}[${ID_FILTER}] ${ID_value} = Get From Dictionary ${HEADER_DICT} ${EACL_OBJ_FILTERS}[${ID_FILTER}]
${filters} = Set Variable obj:${ID_FILTER}!=${ID_value} ${filters} = Set Variable obj:${ID_FILTER}!=${ID_value}
${rule1} = Set Variable deny get ${filters} others ${rule1} = Set Variable deny get ${filters} others
${eACL_gen} = Create List ${rule1} ${eACL_gen} = Create List ${rule1}
@ -194,8 +195,8 @@ Check eACL MatchType String Not Equal Object
Log Set eACL for Deny GET operation with StringEqual Object Extended User Header Log Set eACL for Deny GET operation with StringEqual Object Extended User Header
${S_OID_USER_OTH} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_HEADER} ${S_OID_USER_OTH} = Put object ${USER_KEY} ${FILE_S} ${CID} user_headers=${ANOTHER_HEADER}
${filters} = Set Variable obj:${CUSTOM_FILTER}!=1 ${filters} = Set Variable obj:${CUSTOM_FILTER}!=1
${rule1} = Set Variable deny get ${filters} others ${rule1} = Set Variable deny get ${filters} others
${eACL_gen} = Create List ${rule1} ${eACL_gen} = Create List ${rule1}

View file

@ -5,11 +5,11 @@ Resource setup_teardown.robot
*** Test cases *** *** Test cases ***
Container ID Object Filter for Extended ACL Container ID Object Filter for Extended ACL
[Documentation] Testcase to validate if $Object:containerID eACL filter is correctly handled. [Documentation] Testcase to validate if $Object:containerID eACL filter is correctly handled.
[Tags] ACL eACL NeoFS NeoCLI [Tags] ACL eACL
[Timeout] 20 min [Timeout] 20 min
[Setup] Setup [Setup] Setup
Log Check eACL containerID Filter with MatchType String Equal Log Check eACL containerID Filter with MatchType String Equal
Check eACL Filters with MatchType String Equal $Object:containerID Check eACL Filters with MatchType String Equal $Object:containerID

View file

@ -1,10 +1,10 @@
*** Settings *** *** Settings ***
Variables common.py Variables common.py
Library Collections
Library neofs.py Library neofs.py
Library payment_neogo.py Library payment_neogo.py
Library String Library String
Library Collections
Resource setup_teardown.robot Resource setup_teardown.robot
Resource payment_operations.robot Resource payment_operations.robot
@ -26,7 +26,7 @@ Duplicated Container Attributes
[Setup] Setup [Setup] Setup
${WALLET} ${ADDR} ${USER_KEY} = Init Wallet with Address ${ASSETS_DIR} ${_} ${ADDR} ${USER_KEY} = Init Wallet with Address ${ASSETS_DIR}
Payment Operations ${ADDR} ${USER_KEY} Payment Operations ${ADDR} ${USER_KEY}
###################################################### ######################################################
@ -53,7 +53,10 @@ Duplicated Container Attributes
Wait Until Keyword Succeeds ${MORPH_BLOCK_TIME} ${CONTAINER_WAIT_INTERVAL} Wait Until Keyword Succeeds ${MORPH_BLOCK_TIME} ${CONTAINER_WAIT_INTERVAL}
... Container Existing ${USER_KEY} ${CID} ... Container Existing ${USER_KEY} ${CID}
${ATTRIBUTES} = Get container attributes ${USER_KEY} ${CID} ${EMPTY} json_output=True ${ATTRIBUTES} = Get container attributes ${USER_KEY} ${CID} ${EMPTY} json_output=True
${ATTRIBUTES_DICT} = Decode Container Attributes Json ${ATTRIBUTES} &{ATTRIBUTES_DICT} = Decode Container Attributes Json ${ATTRIBUTES}
Verify Head Attribute ${ATTRIBUTES_DICT} ${ATTR_SINGLE} List Should Contain Value
... ${ATTRIBUTES_DICT}[Attributes]
... ${ATTR_SINGLE}
... "No expected container attributes found"
[Teardown] Teardown container_attributes [Teardown] Teardown container_attributes

View file

@ -16,13 +16,13 @@ ${CONTAINER_WAIT_INTERVAL} = 1 min
*** Test Cases *** *** Test Cases ***
Delete Containers Delete Containers
[Documentation] Testcase to check if containers can be deleted. [Documentation] Testcase to check if containers can be deleted.
[Tags] Container NeoFS NeoCLI [Tags] Container
[Timeout] 10 min [Timeout] 10 min
[Setup] Setup [Setup] Setup
${WALLET} ${ADDR} ${USER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${USER_KEY} = Prepare Wallet And Deposit
${WALLET_OTH} ${ADDR_OTH} ${OTHER_KEY} = Prepare Wallet And Deposit ${_} ${_} ${OTHER_KEY} = Prepare Wallet And Deposit
${CID} = Create container ${USER_KEY} ${PRIVATE_ACL_F} ${COMMON_PLACEMENT_RULE} ${CID} = Create container ${USER_KEY} ${PRIVATE_ACL_F} ${COMMON_PLACEMENT_RULE}
Wait Until Keyword Succeeds ${MORPH_BLOCK_TIME} ${CONTAINER_WAIT_INTERVAL} Wait Until Keyword Succeeds ${MORPH_BLOCK_TIME} ${CONTAINER_WAIT_INTERVAL}
@ -41,6 +41,6 @@ Delete Containers
... Get container attributes ${USER_KEY} ${CID} ... Get container attributes ${USER_KEY} ${CID}
Log If one tries to delete an already deleted container, they should expect success. Log If one tries to delete an already deleted container, they should expect success.
Delete Container ${CID} ${USER_KEY} Delete Container ${CID} ${USER_KEY}
[Teardown] Teardown container_delete [Teardown] Teardown container_delete

View file

@ -2,12 +2,13 @@
Variables common.py Variables common.py
Variables wellknown_acl.py Variables wellknown_acl.py
Library Process
Library contract_keywords.py Library contract_keywords.py
Library neofs.py Library neofs.py
Library String Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Library String
Library Process
Resource setup_teardown.robot Resource setup_teardown.robot
Resource payment_operations.robot Resource payment_operations.robot

View file

@ -2,6 +2,7 @@
Variables common.py Variables common.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Library wallet_keywords.py Library wallet_keywords.py
Library rpc_call_keywords.py Library rpc_call_keywords.py
@ -92,6 +93,6 @@ Validate Policy
${CID} = Create container ${PRIV_KEY} ${EMPTY} ${POLICY} ${CID} = Create container ${PRIV_KEY} ${EMPTY} ${POLICY}
Wait Until Keyword Succeeds ${MORPH_BLOCK_TIME} ${CONTAINER_WAIT_INTERVAL} Wait Until Keyword Succeeds ${MORPH_BLOCK_TIME} ${CONTAINER_WAIT_INTERVAL}
... Container Existing ${PRIV_KEY} ${CID} ... Container Existing ${PRIV_KEY} ${CID}
${S_OID} = Put object ${PRIV_KEY} ${FILE} ${CID} ${EMPTY} ${EMPTY} ${S_OID} = Put object ${PRIV_KEY} ${FILE} ${CID}
Validate storage policy for object ${PRIV_KEY} ${EXPECTED_VAL} ${CID} ${S_OID} ${EXPECTED_LIST} Validate storage policy for object ${PRIV_KEY} ${EXPECTED_VAL} ${CID} ${S_OID} ${EXPECTED_LIST}
Get object ${PRIV_KEY} ${CID} ${S_OID} ${EMPTY} s_file_read Get object ${PRIV_KEY} ${CID} ${S_OID} ${EMPTY} s_file_read

View file

@ -5,6 +5,7 @@ Variables wellknown_acl.py
Library Collections Library Collections
Library payment_neogo.py Library payment_neogo.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library wallet_keywords.py Library wallet_keywords.py
Library rpc_call_keywords.py Library rpc_call_keywords.py
Library contract_keywords.py Library contract_keywords.py
@ -25,10 +26,10 @@ NeoFS Object Replication
[Timeout] 25 min [Timeout] 25 min
[Setup] Setup [Setup] Setup
Log Check replication mechanism Log Check replication mechanism
Check Replication ${EMPTY} Check Replication ${EMPTY}
Log Check Sticky Bit with SYSTEM Group via replication mechanism Log Check Sticky Bit with SYSTEM Group via replication mechanism
Check Replication ${STICKYBIT_PUB_ACL} Check Replication ${STICKYBIT_PUB_ACL}
[Teardown] Teardown replication [Teardown] Teardown replication
@ -37,7 +38,7 @@ NeoFS Object Replication
Check Replication Check Replication
[Arguments] ${ACL} [Arguments] ${ACL}
${WALLET} ${ADDR} ${WIF} = Prepare Wallet And Deposit ${_} ${_} ${WIF} = Prepare Wallet And Deposit
${CID} = Create Container ${WIF} ${ACL} ${PLACEMENT_RULE} ${CID} = Create Container ${WIF} ${ACL} ${PLACEMENT_RULE}
Wait Until Keyword Succeeds ${MORPH_BLOCK_TIME} ${CONTAINER_WAIT_INTERVAL} Wait Until Keyword Succeeds ${MORPH_BLOCK_TIME} ${CONTAINER_WAIT_INTERVAL}
... Container Existing ${WIF} ${CID} ... Container Existing ${WIF} ${CID}
@ -45,7 +46,7 @@ Check Replication
${FILE} = Generate file of bytes ${SIMPLE_OBJ_SIZE} ${FILE} = Generate file of bytes ${SIMPLE_OBJ_SIZE}
${FILE_HASH} = Get file hash ${FILE} ${FILE_HASH} = Get file hash ${FILE}
${S_OID} = Put Object ${WIF} ${FILE} ${CID} ${EMPTY} ${EMPTY} ${S_OID} = Put Object ${WIF} ${FILE} ${CID}
Validate storage policy for object ${WIF} ${EXPECTED_COPIES} ${CID} ${S_OID} Validate storage policy for object ${WIF} ${EXPECTED_COPIES} ${CID} ${S_OID}
@{NODES_OBJ} = Get nodes with Object ${WIF} ${CID} ${S_OID} @{NODES_OBJ} = Get nodes with Object ${WIF} ${CID} ${S_OID}

View file

@ -2,10 +2,11 @@
Variables common.py Variables common.py
Variables wellknown_acl.py Variables wellknown_acl.py
Library Collections
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Library String Library String
Library Collections
Resource setup_teardown.robot Resource setup_teardown.robot
Resource payment_operations.robot Resource payment_operations.robot

View file

@ -1,6 +1,7 @@
*** Settings *** *** Settings ***
Variables common.py Variables common.py
Library neofs_verbs.py
Library neofs.py Library neofs.py
Library payment_neogo.py Library payment_neogo.py
Library contract_keywords.py Library contract_keywords.py

View file

@ -2,6 +2,7 @@
Variables common.py Variables common.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Library contract_keywords.py Library contract_keywords.py
@ -35,12 +36,12 @@ NeoFS Simple Object Operations
# Failed on attempt to create epoch from the past # Failed on attempt to create epoch from the past
Run Keyword And Expect Error * Run Keyword And Expect Error *
... Put object ${WIF} ${FILE} ${CID} ${EMPTY} __NEOFS__EXPIRATION_EPOCH=${EPOCH_PRE} ... Put object ${WIF} ${FILE} ${CID} options= --attributes __NEOFS__EXPIRATION_EPOCH=${EPOCH_PRE}
# Put object with different expiration epoch numbers (current, next, and from the distant future) # Put object with different expiration epoch numbers (current, next, and from the distant future)
${OID_CUR} = Put object ${WIF} ${FILE} ${CID} ${EMPTY} __NEOFS__EXPIRATION_EPOCH=${EPOCH} ${OID_CUR} = Put object ${WIF} ${FILE} ${CID} options= --attributes __NEOFS__EXPIRATION_EPOCH=${EPOCH}
${OID_NXT} = Put object ${WIF} ${FILE} ${CID} ${EMPTY} __NEOFS__EXPIRATION_EPOCH=${EPOCH_NEXT} ${OID_NXT} = Put object ${WIF} ${FILE} ${CID} options= --attributes __NEOFS__EXPIRATION_EPOCH=${EPOCH_NEXT}
${OID_PST} = Put object ${WIF} ${FILE} ${CID} ${EMPTY} __NEOFS__EXPIRATION_EPOCH=${EPOCH_POST} ${OID_PST} = Put object ${WIF} ${FILE} ${CID} options= --attributes __NEOFS__EXPIRATION_EPOCH=${EPOCH_POST}
# Check objects for existence # Check objects for existence
Get object ${WIF} ${CID} ${OID_CUR} ${EMPTY} file_read_cur Get object ${WIF} ${CID} ${OID_CUR} ${EMPTY} file_read_cur

View file

@ -2,6 +2,7 @@
Variables common.py Variables common.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Library contract_keywords.py Library contract_keywords.py
Library Collections Library Collections
@ -25,7 +26,7 @@ NeoFS Simple Object Operations
[Setup] Setup [Setup] Setup
${WALLET} ${ADDR} ${WIF} = Init Wallet with Address ${ASSETS_DIR} ${WALLET} ${ADDR} ${WIF} = Init Wallet with Address ${ASSETS_DIR}
Payment Operations ${ADDR} ${WIF} Payment Operations ${ADDR} ${WIF}
${CID} = Prepare container ${WIF} ${CID} = Prepare container ${WIF}
${FILE} = Generate file of bytes ${SIMPLE_OBJ_SIZE} ${FILE} = Generate file of bytes ${SIMPLE_OBJ_SIZE}

View file

@ -1,9 +1,10 @@
*** Settings *** *** Settings ***
Variables common.py Variables common.py
Library Collections
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Library Collections
Resource common_steps_object.robot Resource common_steps_object.robot
Resource setup_teardown.robot Resource setup_teardown.robot
@ -11,11 +12,12 @@ Resource payment_operations.robot
*** Variables *** *** Variables ***
${UNEXIST_OID} = B2DKvkHnLnPvapbDgfpU1oVUPuXQo5LTfKVxmNDZXQff ${UNEXIST_OID} = B2DKvkHnLnPvapbDgfpU1oVUPuXQo5LTfKVxmNDZXQff
&{USER_HEADER} = key1=1 key2=2
*** Test cases *** *** Test cases ***
NeoFS Complex Storagegroup NeoFS Complex Storagegroup
[Documentation] Testcase to validate NeoFS operations with Storagegroup. [Documentation] Testcase to validate NeoFS operations with Storagegroup.
[Tags] Object NeoFS NeoCLI [Tags] Object
[Timeout] 20 min [Timeout] 20 min
[Setup] Setup [Setup] Setup
@ -28,8 +30,8 @@ NeoFS Complex Storagegroup
${FILE_HASH_S} = Get file hash ${FILE_S} ${FILE_HASH_S} = Get file hash ${FILE_S}
# Put two Simple Object # Put two Simple Object
${S_OID_1} = Put object ${WIF} ${FILE_S} ${CID} ${EMPTY} ${EMPTY} ${S_OID_1} = Put object ${WIF} ${FILE_S} ${CID}
${S_OID_2} = Put object ${WIF} ${FILE_S} ${CID} ${EMPTY} ${FILE_USR_HEADER} ${S_OID_2} = Put object ${WIF} ${FILE_S} ${CID} user_headers=&{USER_HEADER}
@{S_OBJ_ALL} = Create List ${S_OID_1} ${S_OID_2} @{S_OBJ_ALL} = Create List ${S_OID_1} ${S_OID_2}

View file

@ -2,6 +2,7 @@
Variables common.py Variables common.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library payment_neogo.py Library payment_neogo.py
Resource common_steps_object.robot Resource common_steps_object.robot
@ -10,6 +11,7 @@ Resource payment_operations.robot
*** Variables *** *** Variables ***
${UNEXIST_OID} = B2DKvkHnLnPvapbDgfpU1oVUPuXQo5LTfKVxmNDZXQff ${UNEXIST_OID} = B2DKvkHnLnPvapbDgfpU1oVUPuXQo5LTfKVxmNDZXQff
&{USER_HEADER} = key1=1 key2=2
*** Test cases *** *** Test cases ***
NeoFS Simple Storagegroup NeoFS Simple Storagegroup
@ -28,8 +30,8 @@ NeoFS Simple Storagegroup
# Put two Simple Object # Put two Simple Object
${S_OID_1} = Put object ${WIF} ${FILE_S} ${CID} ${EMPTY} ${EMPTY} ${S_OID_1} = Put object ${WIF} ${FILE_S} ${CID}
${S_OID_2} = Put object ${WIF} ${FILE_S} ${CID} ${EMPTY} ${FILE_USR_HEADER} ${S_OID_2} = Put object ${WIF} ${FILE_S} ${CID} user_headers=&{USER_HEADER}
@{S_OBJ_ALL} = Create List ${S_OID_1} ${S_OID_2} @{S_OBJ_ALL} = Create List ${S_OID_1} ${S_OID_2}

View file

@ -3,6 +3,7 @@ Variables common.py
Variables wellknown_acl.py Variables wellknown_acl.py
Library neofs.py Library neofs.py
Library neofs_verbs.py
Library http_gate.py Library http_gate.py
Resource payment_operations.robot Resource payment_operations.robot
@ -33,8 +34,8 @@ NeoFS HTTP Gateway
${FILE_HASH} = Get file hash ${FILE} ${FILE_HASH} = Get file hash ${FILE}
${FILE_L_HASH} = Get file hash ${FILE_L} ${FILE_L_HASH} = Get file hash ${FILE_L}
${S_OID} = Put object ${WIF} ${FILE} ${CID} ${EMPTY} ${EMPTY} ${S_OID} = Put object ${WIF} ${FILE} ${CID}
${L_OID} = Put object ${WIF} ${FILE_L} ${CID} ${EMPTY} ${EMPTY} ${L_OID} = Put object ${WIF} ${FILE_L} ${CID}
# By request from Service team - try to GET object from the node without object # By request from Service team - try to GET object from the node without object
@ -44,8 +45,10 @@ NeoFS HTTP Gateway
${GET_OBJ_S} = Get object ${WIF} ${CID} ${S_OID} ${EMPTY} s_file_read ${NODE} ${GET_OBJ_S} = Get object ${WIF} ${CID} ${S_OID} ${EMPTY} s_file_read ${NODE}
${FILEPATH} = Get via HTTP Gate ${CID} ${S_OID} ${FILEPATH} = Get via HTTP Gate ${CID} ${S_OID}
Verify file hash ${GET_OBJ_S} ${FILE_HASH} ${PLAIN_FILE_HASH} = Get file hash ${GET_OBJ_S}
Verify file hash ${FILEPATH} ${FILE_HASH} ${GATE_FILE_HASH} = Get file hash ${FILEPATH}
Should Be Equal ${FILE_HASH} ${PLAIN_FILE_HASH}
Should Be Equal ${FILE_HASH} ${GATE_FILE_HASH}
@{GET_NODE_LIST} = Get nodes without object ${WIF} ${CID} ${L_OID} @{GET_NODE_LIST} = Get nodes without object ${WIF} ${CID} ${L_OID}
${NODE} = Evaluate random.choice($GET_NODE_LIST) random ${NODE} = Evaluate random.choice($GET_NODE_LIST) random
@ -53,7 +56,9 @@ NeoFS HTTP Gateway
${GET_OBJ_L} = Get object ${WIF} ${CID} ${L_OID} ${EMPTY} l_file_read ${NODE} ${GET_OBJ_L} = Get object ${WIF} ${CID} ${L_OID} ${EMPTY} l_file_read ${NODE}
${FILEPATH} = Get via HTTP Gate ${CID} ${L_OID} ${FILEPATH} = Get via HTTP Gate ${CID} ${L_OID}
Verify file hash ${GET_OBJ_L} ${FILE_L_HASH} ${PLAIN_FILE_HASH} = Get file hash ${GET_OBJ_L}
Verify file hash ${FILEPATH} ${FILE_L_HASH} ${GATE_FILE_HASH} = Get file hash ${FILEPATH}
Should Be Equal ${FILE_L_HASH} ${PLAIN_FILE_HASH}
Should Be Equal ${FILE_L_HASH} ${GATE_FILE_HASH}
[Teardown] Teardown http_gate [Teardown] Teardown http_gate

View file

@ -58,6 +58,8 @@ Objects in NeoFS S3 Gateway
${OBJ_PATH} = Get object S3 ${S3_CLIENT} ${NEW_BUCKET} ${S3_OBJECT_KEY} ${OBJ_PATH} = Get object S3 ${S3_CLIENT} ${NEW_BUCKET} ${S3_OBJECT_KEY}
Verify file hash ${OBJ_PATH} ${FILE_S3_HASH} Verify file hash ${OBJ_PATH} ${FILE_S3_HASH}
${HASH} = Get file hash ${OBJ_PATH}
Should Be Equal ${FILE_S3_HASH} ${HASH}
#TODO: Solve the issue on CopyObject #260 https://github.com/nspcc-dev/neofs-s3-gw/issues/260 #TODO: Solve the issue on CopyObject #260 https://github.com/nspcc-dev/neofs-s3-gw/issues/260