Skip to content

Commit f8e1fa0

Browse files
authored
Merge pull request #772 from skalenetwork/fix-repair
Fix repair
2 parents 816dd0f + 2ddd6df commit f8e1fa0

File tree

10 files changed

+91
-140
lines changed

10 files changed

+91
-140
lines changed

node_cli/cli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = '2.4.1'
1+
__version__ = '2.5.0'
22

33
if __name__ == "__main__":
44
print(__version__)

node_cli/configs/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343

4444
NODE_DATA_PATH = os.path.join(SKALE_DIR, 'node_data')
4545
SCHAIN_NODE_DATA_PATH = os.path.join(NODE_DATA_PATH, 'schains')
46+
NODE_CLI_STATUS_FILENAME = 'node_cli.status'
4647
NODE_CONFIG_PATH = os.path.join(NODE_DATA_PATH, 'node_config.json')
4748
CONTAINER_CONFIG_PATH = os.path.join(SKALE_DIR, 'config')
4849
CONTAINER_CONFIG_TMP_PATH = os.path.join(SKALE_TMP_DIR, 'config')

node_cli/core/schains.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,23 @@
22
import os
33
import pprint
44
import shutil
5+
import time
56
from pathlib import Path
67

78
from typing import Dict, Optional
89

910
from node_cli.configs import (
1011
ALLOCATION_FILEPATH,
1112
NODE_CONFIG_PATH,
13+
NODE_CLI_STATUS_FILENAME,
1214
SCHAIN_NODE_DATA_PATH
1315
)
1416
from node_cli.configs.env import get_env_config
1517

1618
from node_cli.utils.helper import (
1719
get_request,
1820
error_exit,
19-
safe_load_yml,
20-
post_request
21+
safe_load_yml
2122
)
2223
from node_cli.utils.exit_codes import CLIExitCodes
2324
from node_cli.utils.print_formatters import (
@@ -27,7 +28,7 @@
2728
print_schains
2829
)
2930
from node_cli.utils.docker_utils import ensure_volume, is_volume_exists
30-
from node_cli.utils.helper import read_json, run_cmd
31+
from node_cli.utils.helper import read_json, run_cmd, save_json
3132
from lvmpy.src.core import mount, volume_mountpoint
3233

3334

@@ -89,22 +90,24 @@ def show_config(name: str) -> None:
8990
error_exit(payload, exit_code=CLIExitCodes.BAD_API_RESPONSE)
9091

9192

93+
def get_node_cli_schain_status_filepath(schain_name: str) -> str:
94+
return os.path.join(SCHAIN_NODE_DATA_PATH, schain_name, NODE_CLI_STATUS_FILENAME)
95+
96+
97+
def update_node_cli_schain_status(schain_name: str, status: dict) -> None:
98+
path = get_node_cli_schain_status_filepath(schain_name)
99+
save_json(path, status)
100+
101+
92102
def toggle_schain_repair_mode(
93103
schain: str,
94104
snapshot_from: Optional[str] = None
95105
) -> None:
96-
json_params = {'schain_name': schain}
97-
if snapshot_from:
98-
json_params.update({'snapshot_from': snapshot_from})
99-
status, payload = post_request(
100-
blueprint=BLUEPRINT_NAME,
101-
method='repair',
102-
json=json_params
103-
)
104-
if status == 'ok':
105-
print('Schain has been set for repair')
106-
else:
107-
error_exit(payload, exit_code=CLIExitCodes.BAD_API_RESPONSE)
106+
ts = int(time.time())
107+
status = {'schain_name': schain, 'repair_ts': ts}
108+
status.update({'snapshot_from': snapshot_from})
109+
update_node_cli_schain_status(schain, status)
110+
print('Schain has been set for repair')
108111

109112

110113
def describe(schain: str, raw=False) -> None:

node_cli/utils/helper.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import os
2323
import re
2424
import sys
25+
import uuid
2526
from urllib.parse import urlparse
2627

2728
import yaml
@@ -77,16 +78,22 @@ class InvalidEnvFileError(Exception):
7778
pass
7879

7980

80-
def read_json(path):
81+
def read_json(path: str) -> dict:
8182
with open(path, encoding='utf-8') as data_file:
8283
return json.loads(data_file.read())
8384

8485

85-
def write_json(path, content):
86+
def write_json(path: str, content: dict) -> None:
8687
with open(path, 'w') as outfile:
8788
json.dump(content, outfile, indent=4)
8889

8990

91+
def save_json(path: str, content: dict) -> None:
92+
tmp_path = get_tmp_path(path)
93+
write_json(tmp_path, content)
94+
shutil.move(tmp_path, path)
95+
96+
9097
def init_file(path, content=None):
9198
if not os.path.exists(path):
9299
write_json(path, content)
@@ -400,3 +407,9 @@ def convert(self, value, param, ctx):
400407

401408
URL_TYPE = UrlType()
402409
IP_TYPE = IpType()
410+
411+
412+
def get_tmp_path(path: str) -> str:
413+
base, ext = os.path.splitext(path)
414+
salt = uuid.uuid4().hex[:5]
415+
return base + salt + '.tmp' + ext

tests/cli/schains_test.py

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import requests
2424

2525
from node_cli.configs import G_CONF_HOME
26-
from tests.helper import response_mock, run_command_mock
26+
from tests.helper import response_mock, run_command, run_command_mock
2727
from node_cli.cli.schains import (get_schain_config, ls, dkg, show_rules,
2828
repair, info_)
2929

@@ -153,30 +153,14 @@ def test_schain_rules():
153153
assert result.output == ' IP range Port \n-----------------------------\n127.0.0.2 - 127.0.0.2 10000\n127.0.0.2 - 127.0.0.2 10001\nAll IPs 10002\nAll IPs 10003\n127.0.0.2 - 127.0.0.2 10004\n127.0.0.2 - 127.0.0.2 10005\nAll IPs 10007\nAll IPs 10008\nAll IPs 10009\n' # noqa
154154

155155

156-
def test_repair():
156+
def test_repair(tmp_schains_dir):
157+
os.mkdir(os.path.join(tmp_schains_dir, 'test-schain'))
157158
os.environ['TZ'] = 'Europe/London'
158159
time.tzset()
159-
payload = []
160-
resp_mock = response_mock(
161-
requests.codes.ok,
162-
json_data={'payload': payload, 'status': 'ok'}
163-
)
164-
result = run_command_mock('node_cli.utils.helper.requests.post', resp_mock, repair,
165-
['test-schain', '--yes'])
160+
result = run_command(repair, ['test-schain', '--yes'])
166161
assert result.output == 'Schain has been set for repair\n'
167162
assert result.exit_code == 0
168163

169-
payload = ['error']
170-
resp_mock = response_mock(
171-
requests.codes.ok,
172-
json_data={'payload': payload, 'status': 'error'}
173-
)
174-
result = run_command_mock('node_cli.utils.helper.requests.post', resp_mock, repair,
175-
['test-schain', '--yes'])
176-
print(repr(result.output))
177-
assert result.exit_code == 3
178-
assert result.output == f'Command failed with following errors:\n--------------------------------------------------\nerror\n--------------------------------------------------\nYou can find more info in {G_CONF_HOME}.skale/.skale-cli-log/debug-node-cli.log\n' # noqa
179-
180164

181165
def test_info():
182166
payload = {

tests/conftest.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@
2929
import yaml
3030

3131
from node_cli.configs import (
32-
CONTAINER_CONFIG_TMP_PATH,
33-
GLOBAL_SKALE_CONF_FILEPATH,
34-
GLOBAL_SKALE_DIR,
35-
META_FILEPATH,
36-
NGINX_CONTAINER_NAME,
37-
REMOVED_CONTAINERS_FOLDER_PATH,
38-
STATIC_PARAMS_FILEPATH
32+
CONTAINER_CONFIG_TMP_PATH,
33+
GLOBAL_SKALE_CONF_FILEPATH,
34+
GLOBAL_SKALE_DIR,
35+
META_FILEPATH,
36+
NGINX_CONTAINER_NAME,
37+
REMOVED_CONTAINERS_FOLDER_PATH,
38+
STATIC_PARAMS_FILEPATH,
39+
SCHAIN_NODE_DATA_PATH
3940
)
4041
from node_cli.configs.node_options import NODE_OPTIONS_FILEPATH
4142
from node_cli.configs.ssl import SSL_FOLDER_PATH
@@ -302,3 +303,12 @@ def tmp_config_dir():
302303
yield CONTAINER_CONFIG_TMP_PATH
303304
finally:
304305
shutil.rmtree(CONTAINER_CONFIG_TMP_PATH)
306+
307+
308+
@pytest.fixture
309+
def tmp_schains_dir():
310+
os.makedirs(SCHAIN_NODE_DATA_PATH)
311+
try:
312+
yield SCHAIN_NODE_DATA_PATH
313+
finally:
314+
shutil.rmtree(SCHAIN_NODE_DATA_PATH)
File renamed without changes.
File renamed without changes.

tests/core/core_schains_test.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import os
2+
import datetime
3+
4+
import freezegun
5+
6+
from node_cli.core.schains import toggle_schain_repair_mode
7+
from node_cli.utils.helper import read_json
8+
9+
10+
CURRENT_TIMESTAMP = 1594903080
11+
CURRENT_DATETIME = datetime.datetime.utcfromtimestamp(CURRENT_TIMESTAMP)
12+
13+
14+
@freezegun.freeze_time(CURRENT_DATETIME)
15+
def test_toggle_repair_mode(tmp_schains_dir):
16+
schain_name = "test_schain"
17+
schain_folder = os.path.join(tmp_schains_dir, schain_name)
18+
os.mkdir(schain_folder)
19+
toggle_schain_repair_mode(schain_name)
20+
schain_status_path = os.path.join(schain_folder, "node_cli.status")
21+
assert os.path.isfile(schain_status_path)
22+
23+
assert read_json(schain_status_path) == {
24+
'repair_ts': CURRENT_TIMESTAMP,
25+
'schain_name': 'test_schain',
26+
'snapshot_from': None,
27+
}
28+
29+
toggle_schain_repair_mode(schain_name, snapshot_from='127.0.0.1')
30+
31+
assert read_json(schain_status_path) == {
32+
'repair_ts': CURRENT_TIMESTAMP,
33+
'schain_name': 'test_schain',
34+
'snapshot_from': '127.0.0.1',
35+
}

tests/core_ssl_test.py

Lines changed: 0 additions & 95 deletions
This file was deleted.

0 commit comments

Comments
 (0)