Skip to content

Commit

Permalink
Merge branch 'develop' into f-list-batches
Browse files Browse the repository at this point in the history
  • Loading branch information
Artem Saprykin committed Apr 26, 2019
2 parents ba3f72e + bc3ba52 commit e805d04
Show file tree
Hide file tree
Showing 19 changed files with 392 additions and 17 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,25 @@ $ remme node get-configs --node-url=node-genesis-testnet.remme.io
}
```

Get the node's peers — ``remme node get-peers``:

| Arguments | Type | Required | Description |
| :-------: | :----: | :-------: | ------------------------------- |
| node-url | String | No | Node URL to apply a command to. |

```bash
$ remme node get-peers --node-url=node-genesis-testnet.remme.io
{
"result": {
"peers": [
"tcp://node-22-testnet.remme.io:8800",
"tcp://node-9-testnet.remme.io:8800",
"tcp://node-29-testnet.remme.io:8800"
]
}
}
```

### Public key

Get a list of the addresses of the public keys by account address — ``remme public-key get-list``:
Expand Down
2 changes: 1 addition & 1 deletion cli/batch/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
)

from cli.generic.forms.fields import (
BatchIdField,
BatchIdentifierListField,
BatchIdField,
BlockIdField,
NodeURLField,
)
Expand Down
34 changes: 33 additions & 1 deletion cli/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@
Provide implementation of the CLI configurations file.
"""
import pathlib
import platform

import yaml
from accessify import private

from cli.constants import CLI_CONFIG_FILE_NAME
from cli.constants import (
CLI_CONFIG_FILE_NAME,
LINUX_NODE_PRIVATE_KEY_FILE_PATH,
SUPPORTED_OS_TO_EXECUTE_NODE_MANAGEMENT_COMMANDS,
)
from cli.errors import NotSupportedOsToGetNodePrivateKeyError


class ConfigParameters:
Expand Down Expand Up @@ -63,3 +69,29 @@ def parse(self, name=CLI_CONFIG_FILE_NAME):
node_url = config_as_dict.get('node-url')

return ConfigParameters(node_url=node_url)


class NodePrivateKey:
"""
Implementation of the node's private key.
"""

@staticmethod
def get(file_path=LINUX_NODE_PRIVATE_KEY_FILE_PATH):
"""
Get the node's private key.
Supported operating systems to get the private key are: Linux.
Not supported operating systems to get the private key are: Darwin (aka MacOS), Windows.
"""
if platform.system() not in SUPPORTED_OS_TO_EXECUTE_NODE_MANAGEMENT_COMMANDS:
raise NotSupportedOsToGetNodePrivateKeyError(
'The current operating system is not supported to get the node\'s private key.',
)

try:
with open(file_path) as private_key_file:
return private_key_file.readline().rstrip()

except FileNotFoundError:
raise FileNotFoundError('Private key hasn\'t been founded on the machine.')
8 changes: 8 additions & 0 deletions cli/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
ADDRESS_REGEXP = r'^[0-9a-f]{70}$'
BATCH_ID_REGEXP = r'^[0-9a-f]{128}$'
PUBLIC_KEY_REGEXP = r'^[0-9a-f]{66}$'
PRIVATE_KEY_REGEXP = r'^[a-f0-9]{64}$'
HEADER_SIGNATURE_REGEXP = r'^[0-9a-f]{128}$'
DOMAIN_NAME_REGEXP = r'(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]'
Expand All @@ -18,5 +19,12 @@
NODE_IP_ADDRESS_FOR_TESTING = '159.89.104.9'
LATEST_RELEASE_NODE_IP_ADDRESS_FOR_TESTING = '165.22.75.163'
RELEASE_0_9_0_ALPHA_NODE_ADDRESS = '165.227.169.119'
NODE_27_IN_TESTNET_ADDRESS = 'node-27-testnet.remme.io'

PRIVATE_KEY_FOR_TESTING = 'b03e31d2f310305eab249133b53b5fb3270090fc1692c9b022b81c6b9bb6029b'

LINUX_NODE_PRIVATE_KEY_FILE_PATH = '/var/lib/docker/volumes/remme_validator_keys/_data/validator.priv'

SUPPORTED_OS_TO_EXECUTE_NODE_MANAGEMENT_COMMANDS = (
'Linux'
)
12 changes: 12 additions & 0 deletions cli/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""
Provide errors for command line interface.
"""


class NotSupportedOsToGetNodePrivateKeyError(Exception):
"""
Operating system is not supported to get the node's private key error.
"""

def __init__(self, message):
self.message = message
1 change: 0 additions & 1 deletion cli/generic/forms/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
HEADER_SIGNATURE_REGEXP,
PRIVATE_KEY_REGEXP,
)
from cli.utils import dict_to_pretty_json


class AccountAddressField(fields.Field):
Expand Down
34 changes: 33 additions & 1 deletion cli/node/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
FAILED_EXIT_FROM_COMMAND_CODE,
NODE_URL_ARGUMENT_HELP_MESSAGE,
)
from cli.node.forms import GetNodeConfigurationsForm
from cli.node.forms import (
GetNodeConfigurationsForm,
GetNodePeersForm,
)
from cli.node.service import Node
from cli.utils import (
default_node_url,
Expand Down Expand Up @@ -54,3 +57,32 @@ def get_config(node_url):
sys.exit(FAILED_EXIT_FROM_COMMAND_CODE)

print_result(result=result)


@click.option('--node-url', type=str, required=False, help=NODE_URL_ARGUMENT_HELP_MESSAGE, default=default_node_url())
@node_commands.command('get-peers')
def get_peers(node_url):
"""
Get the node's peers.
"""
arguments, errors = GetNodePeersForm().load({
'node_url': node_url,
})

if errors:
print_errors(errors=errors)
sys.exit(FAILED_EXIT_FROM_COMMAND_CODE)

node_url = arguments.get('node_url')

remme = Remme(network_config={
'node_address': str(node_url) + ':8080',
})

result, errors = Node(service=remme).get_peers()

if errors is not None:
print_errors(errors=errors)
sys.exit(FAILED_EXIT_FROM_COMMAND_CODE)

print_result(result=result)
8 changes: 8 additions & 0 deletions cli/node/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,11 @@ class GetNodeConfigurationsForm(Schema):
"""

node_url = NodeURLField(allow_none=True, required=False)


class GetNodePeersForm(Schema):
"""
Get the node's peers.
"""

node_url = NodeURLField(allow_none=True, required=False)
6 changes: 6 additions & 0 deletions cli/node/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@ def get_configs(self):
Get node configurations.
"""
pass

def get_peers(self):
"""
Get the node's peers.
"""
pass
14 changes: 14 additions & 0 deletions cli/node/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,17 @@ def get_configs(self):
return {
'configurations': configurations.data,
}, None

def get_peers(self):
"""
Get the node's peers.
"""
try:
peers = loop.run_until_complete(self.service.blockchain_info.get_peers())

except Exception as error:
return None, str(error)

return {
'peers': peers,
}, None
2 changes: 1 addition & 1 deletion tests/batch/test_get_batches.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"""
import json

from cli.utils import dict_to_pretty_json
from click.testing import CliRunner

from cli.constants import (
Expand All @@ -12,6 +11,7 @@
PASSED_EXIT_FROM_COMMAND_CODE,
)
from cli.entrypoint import cli
from cli.utils import dict_to_pretty_json

BATCH_IDENTIFIER_PRESENTED_ON_THE_TEST_NODE = \
'93225596c6dcd8e520846700e052651728b1c85d1ae2fcf44e14bb628d97b4c9' \
Expand Down
Empty file added tests/config/__init__.py
Empty file.
2 changes: 1 addition & 1 deletion tests/test_config.py → tests/config/test_config_file.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Provide tests for implementation of the config commands.
Provide tests for implementation of the config file.
"""
from cli.config import ConfigFile

Expand Down
43 changes: 43 additions & 0 deletions tests/config/test_node_private_key_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
Provide tests for implementation of the node private key file.
"""
import pytest

from cli.config import NodePrivateKey
from cli.errors import NotSupportedOsToGetNodePrivateKeyError
from tests.constants import NODE_PRIVATE_KEY_FILE_PATH_IN_TESTING


def test_node_private_key_get(create_node_private_key_file):
"""
Case: get the node's private key.
Expect: private key has been read from the node's private key file.
"""
private_key = NodePrivateKey.get(file_path=NODE_PRIVATE_KEY_FILE_PATH_IN_TESTING)
assert '8a069bfff838f73d1b072ba72ee0f61b19d9b7216d5a735d7ff4d15063dd9772' == private_key


@pytest.mark.parametrize('operating_system', ['Darwin', 'Windows'])
def test_node_private_key_get_not_supported_os(operating_system, mocker):
"""
Case: get the node's private key from not supported operating system.
Expect: operating system is not supported to get the node's private key error message.
"""
mock_account_get_balance = mocker.patch('platform.system')
mock_account_get_balance.return_value = operating_system

with pytest.raises(NotSupportedOsToGetNodePrivateKeyError) as error:
NodePrivateKey.get(file_path=NODE_PRIVATE_KEY_FILE_PATH_IN_TESTING)

assert 'The current operating system is not supported to get the node\'s private key.' in error.value.message


def test_node_private_key_get_from_non_existing_file():
"""
Case: get the node's private key from non-existing file.
Expect: private key hasn't been founded on the machine error message.
"""
with pytest.raises(FileNotFoundError) as error:
NodePrivateKey.get(file_path=NODE_PRIVATE_KEY_FILE_PATH_IN_TESTING)

assert 'Private key hasn\'t been founded on the machine.' in str(error)
22 changes: 22 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

import pytest

from tests.constants import (
NODE_PRIVATE_KEY_DIRECTORY_PATH,
NODE_PRIVATE_KEY_FILE_PATH_IN_TESTING,
)


def pytest_configure():
"""
Expand Down Expand Up @@ -77,6 +82,23 @@ def create_empty_config_file():
os.remove(path_to_copy_fixture_file_to)


@pytest.yield_fixture()
def create_node_private_key_file():
"""
Create the node's private key file.
The example of the configuration file is located in the tests fixture folder.
"""
fixture_file_path = os.getcwd() + '/tests/fixtures/validator.priv'

pathlib.Path(NODE_PRIVATE_KEY_DIRECTORY_PATH).mkdir(parents=True, exist_ok=True)
shutil.copyfile(fixture_file_path, NODE_PRIVATE_KEY_FILE_PATH_IN_TESTING)

yield

os.remove(NODE_PRIVATE_KEY_FILE_PATH_IN_TESTING)


class SentTransaction:
"""
Impose transaction data transfer object.
Expand Down
7 changes: 7 additions & 0 deletions tests/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""
Provide constants for testing a command line interface.
"""
import pathlib

NODE_PRIVATE_KEY_DIRECTORY_PATH = str(pathlib.Path.home()) + '/docker/volumes/remme_validator_keys/_data/'
NODE_PRIVATE_KEY_FILE_PATH_IN_TESTING = NODE_PRIVATE_KEY_DIRECTORY_PATH + 'validator.priv'
1 change: 1 addition & 0 deletions tests/fixtures/validator.priv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8a069bfff838f73d1b072ba72ee0f61b19d9b7216d5a735d7ff4d15063dd9772
22 changes: 11 additions & 11 deletions tests/node/test_get_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
Provide tests for command line interface's node get configurations command.
"""
import json
import re

from click.testing import CliRunner

from cli.constants import (
ADDRESS_REGEXP,
FAILED_EXIT_FROM_COMMAND_CODE,
NODE_27_IN_TESTNET_ADDRESS,
PASSED_EXIT_FROM_COMMAND_CODE,
RELEASE_0_9_0_ALPHA_NODE_ADDRESS,
PUBLIC_KEY_REGEXP,
)
from cli.entrypoint import cli
from cli.utils import dict_to_pretty_json
Expand All @@ -24,20 +27,17 @@ def test_get_node_configs():
'node',
'get-configs',
'--node-url',
RELEASE_0_9_0_ALPHA_NODE_ADDRESS,
NODE_27_IN_TESTNET_ADDRESS,
])

expected_node_configurations = {
'result': {
'configurations': {
'node_address': '116829f18683f6c30146559c9cb8d5d302545019ff00f2ab72500df99bceb7b81a1dad',
'node_public_key': '0350e9cf23966ad404dc56438fd01ec11a913446cfd7c4fb8d95586a58718431e7',
},
},
}
node_configurations = json.loads(result.output).get('result').get('configurations')

node_address = node_configurations.get('node_address')
node_public_key = node_configurations.get('node_public_key')

assert PASSED_EXIT_FROM_COMMAND_CODE == result.exit_code
assert expected_node_configurations == json.loads(result.output)
assert re.match(pattern=ADDRESS_REGEXP, string=node_address) is not None
assert re.match(pattern=PUBLIC_KEY_REGEXP, string=node_public_key) is not None


def test_get_node_configs_without_node_url(mocker, node_configurations):
Expand Down
Loading

0 comments on commit e805d04

Please sign in to comment.