mirror of
https://github.com/basicswap/basicswap.git
synced 2025-04-06 14:27:30 +00:00
prepare: Make setup config persistent.
This commit is contained in:
parent
c28eb9ab9b
commit
7972a50341
5 changed files with 209 additions and 48 deletions
|
@ -283,18 +283,23 @@ TOR_PROXY_HOST = os.getenv("TOR_PROXY_HOST", "127.0.0.1")
|
|||
TOR_PROXY_PORT = int(os.getenv("TOR_PROXY_PORT", 9050))
|
||||
TOR_CONTROL_PORT = int(os.getenv("TOR_CONTROL_PORT", 9051))
|
||||
TOR_DNS_PORT = int(os.getenv("TOR_DNS_PORT", 5353))
|
||||
TOR_CONTROL_LISTEN_INTERFACE = os.getenv(
|
||||
"TOR_CONTROL_LISTEN_INTERFACE", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0"
|
||||
)
|
||||
TORRC_PROXY_HOST = os.getenv(
|
||||
"TORRC_PROXY_HOST", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0"
|
||||
)
|
||||
TORRC_CONTROL_HOST = os.getenv(
|
||||
"TORRC_CONTROL_HOST", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0"
|
||||
)
|
||||
TORRC_DNS_HOST = os.getenv(
|
||||
"TORRC_DNS_HOST", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0"
|
||||
)
|
||||
|
||||
|
||||
def setTorrcVars():
|
||||
global TOR_CONTROL_LISTEN_INTERFACE, TORRC_PROXY_HOST, TORRC_CONTROL_HOST, TORRC_DNS_HOST
|
||||
TOR_CONTROL_LISTEN_INTERFACE = os.getenv(
|
||||
"TOR_CONTROL_LISTEN_INTERFACE", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0"
|
||||
)
|
||||
TORRC_PROXY_HOST = os.getenv(
|
||||
"TORRC_PROXY_HOST", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0"
|
||||
)
|
||||
TORRC_CONTROL_HOST = os.getenv(
|
||||
"TORRC_CONTROL_HOST", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0"
|
||||
)
|
||||
TORRC_DNS_HOST = os.getenv(
|
||||
"TORRC_DNS_HOST", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0"
|
||||
)
|
||||
|
||||
|
||||
TEST_TOR_PROXY = toBool(
|
||||
os.getenv("TEST_TOR_PROXY", "true")
|
||||
|
@ -2073,7 +2078,69 @@ def load_config(config_path):
|
|||
if not os.path.exists(config_path):
|
||||
exitWithError("{} does not exist".format(config_path))
|
||||
with open(config_path) as fs:
|
||||
return json.load(fs)
|
||||
settings = json.load(fs)
|
||||
|
||||
BSX_ALLOW_ENV_OVERRIDE = toBool(os.getenv("BSX_ALLOW_ENV_OVERRIDE", "false"))
|
||||
|
||||
saved_env_var_settings = [
|
||||
("setup_docker_mode", "BSX_DOCKER_MODE"),
|
||||
("setup_local_tor", "BSX_LOCAL_TOR"),
|
||||
("setup_tor_control_listen_interface", "TOR_CONTROL_LISTEN_INTERFACE"),
|
||||
("setup_torrc_proxy_host", "TORRC_PROXY_HOST"),
|
||||
("setup_torrc_control_host", "TORRC_CONTROL_HOST"),
|
||||
("setup_torrc_dns_host", "TORRC_DNS_HOST"),
|
||||
("tor_proxy_host", "TOR_PROXY_HOST"),
|
||||
("tor_proxy_port", "TOR_PROXY_PORT"),
|
||||
("tor_control_port", "TOR_CONTROL_PORT"),
|
||||
]
|
||||
for setting in saved_env_var_settings:
|
||||
config_name, env_name = setting
|
||||
env_value = globals()[env_name]
|
||||
saved_config_value = settings.get(config_name, env_value)
|
||||
if saved_config_value != env_value:
|
||||
if os.getenv(env_name):
|
||||
# If the env var was manually set override the saved config if allowed else fail.
|
||||
if BSX_ALLOW_ENV_OVERRIDE:
|
||||
logger.warning(
|
||||
f"Env var {env_name} differs from saved config '{config_name}', overriding."
|
||||
)
|
||||
else:
|
||||
print(
|
||||
f"Env var {env_name} differs from saved config '{config_name}', set 'BSX_ALLOW_ENV_OVERRIDE' to override.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
else:
|
||||
logger.info(f"Setting {env_name} from saved config '{config_name}'.")
|
||||
globals()[env_name] = saved_config_value
|
||||
# Recalculate env vars that depend on the changed var
|
||||
if env_name == "BSX_LOCAL_TOR":
|
||||
setTorrcVars()
|
||||
return settings
|
||||
|
||||
|
||||
def save_config(config_path, settings, add_options: bool = True) -> None:
|
||||
|
||||
if add_options is True:
|
||||
if os.getenv("BSX_DOCKER_MODE") or "docker_mode" not in settings:
|
||||
settings["setup_docker_mode"] = BSX_DOCKER_MODE
|
||||
if os.getenv("BSX_LOCAL_TOR") or "local_tor" not in settings:
|
||||
settings["setup_local_tor"] = BSX_LOCAL_TOR
|
||||
|
||||
# Add to settings only if manually set
|
||||
if os.getenv("TOR_CONTROL_LISTEN_INTERFACE"):
|
||||
settings["setup_tor_control_listen_interface"] = (
|
||||
TOR_CONTROL_LISTEN_INTERFACE
|
||||
)
|
||||
if os.getenv("TORRC_PROXY_HOST"):
|
||||
settings["setup_torrc_proxy_host"] = TORRC_PROXY_HOST
|
||||
if os.getenv("TORRC_CONTROL_HOST"):
|
||||
settings["setup_torrc_control_host"] = TORRC_CONTROL_HOST
|
||||
if os.getenv("TORRC_DNS_HOST"):
|
||||
settings["setup_torrc_dns_host"] = TORRC_DNS_HOST
|
||||
|
||||
with open(config_path, "w") as fp:
|
||||
json.dump(settings, fp, indent=4)
|
||||
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
|
@ -2143,6 +2210,7 @@ def ensure_coin_valid(coin: str, test_disabled: bool = True) -> None:
|
|||
|
||||
def main():
|
||||
global use_tor_proxy, with_coins_changed
|
||||
setTorrcVars()
|
||||
data_dir = None
|
||||
bin_dir = None
|
||||
port_offset = None
|
||||
|
@ -2735,9 +2803,7 @@ def main():
|
|||
settings, coin, tor_control_password, enable=True, extra_opts=extra_opts
|
||||
)
|
||||
|
||||
with open(config_path, "w") as fp:
|
||||
json.dump(settings, fp, indent=4)
|
||||
|
||||
save_config(config_path, settings)
|
||||
logger.info("Done.")
|
||||
return 0
|
||||
|
||||
|
@ -2754,9 +2820,7 @@ def main():
|
|||
extra_opts=extra_opts,
|
||||
)
|
||||
|
||||
with open(config_path, "w") as fp:
|
||||
json.dump(settings, fp, indent=4)
|
||||
|
||||
save_config(config_path, settings)
|
||||
logger.info("Done.")
|
||||
return 0
|
||||
|
||||
|
@ -2781,9 +2845,7 @@ def main():
|
|||
if "manage_wallet_daemon" in coin_settings:
|
||||
coin_settings["manage_wallet_daemon"] = False
|
||||
|
||||
with open(config_path, "w") as fp:
|
||||
json.dump(settings, fp, indent=4)
|
||||
|
||||
save_config(config_path, settings)
|
||||
logger.info("Done.")
|
||||
return 0
|
||||
|
||||
|
@ -2805,8 +2867,7 @@ def main():
|
|||
coin_settings["manage_daemon"] = True
|
||||
if "manage_wallet_daemon" in coin_settings:
|
||||
coin_settings["manage_wallet_daemon"] = True
|
||||
with open(config_path, "w") as fp:
|
||||
json.dump(settings, fp, indent=4)
|
||||
save_config(config_path, settings)
|
||||
logger.info("Done.")
|
||||
return 0
|
||||
exitWithError("{} is already in the settings file".format(add_coin))
|
||||
|
@ -2821,7 +2882,6 @@ def main():
|
|||
test_particl_encryption(data_dir, settings, chain, use_tor_proxy)
|
||||
|
||||
settings["chainclients"][add_coin] = chainclients[add_coin]
|
||||
settings["use_tor_proxy"] = use_tor_proxy
|
||||
|
||||
if not no_cores:
|
||||
prepareCore(add_coin, known_coins[add_coin], settings, data_dir, extra_opts)
|
||||
|
@ -2843,8 +2903,7 @@ def main():
|
|||
use_tor_proxy,
|
||||
)
|
||||
|
||||
with open(config_path, "w") as fp:
|
||||
json.dump(settings, fp, indent=4)
|
||||
save_config(config_path, settings)
|
||||
|
||||
logger.info(f"Done. Coin {add_coin} successfully added.")
|
||||
return 0
|
||||
|
@ -2863,8 +2922,7 @@ def main():
|
|||
if c not in settings["chainclients"]:
|
||||
settings["chainclients"][c] = chainclients[c]
|
||||
elif upgrade_cores:
|
||||
with open(config_path) as fs:
|
||||
settings = json.load(fs)
|
||||
settings = load_config(config_path)
|
||||
|
||||
with_coins_start = with_coins
|
||||
if not with_coins_changed:
|
||||
|
@ -2913,8 +2971,8 @@ def main():
|
|||
# Run second loop to update, so all versions are logged together.
|
||||
# Backup settings
|
||||
old_config_path = config_path[:-5] + "_" + str(int(time.time())) + ".json"
|
||||
with open(old_config_path, "w") as fp:
|
||||
json.dump(settings, fp, indent=4)
|
||||
save_config(old_config_path, settings, add_options=False)
|
||||
|
||||
for c in with_coins:
|
||||
prepareCore(c, known_coins[c], settings, data_dir, extra_opts)
|
||||
current_coin_settings = chainclients[c]
|
||||
|
@ -2927,8 +2985,7 @@ def main():
|
|||
settings["chainclients"][c][
|
||||
"core_version_group"
|
||||
] = current_version_group
|
||||
with open(config_path, "w") as fp:
|
||||
json.dump(settings, fp, indent=4)
|
||||
save_config(config_path, settings)
|
||||
|
||||
logger.info("Done.")
|
||||
return 0
|
||||
|
@ -2978,8 +3035,7 @@ def main():
|
|||
for c in with_coins:
|
||||
prepareDataDir(c, settings, chain, particl_wallet_mnemonic, extra_opts)
|
||||
|
||||
with open(config_path, "w") as fp:
|
||||
json.dump(settings, fp, indent=4)
|
||||
save_config(config_path, settings)
|
||||
|
||||
if particl_wallet_mnemonic == "none":
|
||||
logger.info("Done.")
|
||||
|
|
|
@ -197,7 +197,7 @@ class Test(unittest.TestCase):
|
|||
logger.handlers = []
|
||||
logger.setLevel(logging.INFO) # DEBUG shows many messages from requests.post
|
||||
formatter = logging.Formatter("%(asctime)s %(levelname)s : %(message)s")
|
||||
stream_stdout = logging.StreamHandler()
|
||||
stream_stdout = logging.StreamHandler(sys.stdout)
|
||||
stream_stdout.setFormatter(formatter)
|
||||
logger.addHandler(stream_stdout)
|
||||
|
||||
|
|
|
@ -6,30 +6,34 @@
|
|||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import importlib
|
||||
import json
|
||||
import shutil
|
||||
import logging
|
||||
import unittest
|
||||
import threading
|
||||
import multiprocessing
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import threading
|
||||
import unittest
|
||||
|
||||
from io import StringIO
|
||||
from unittest.mock import patch
|
||||
|
||||
import basicswap.config as cfg
|
||||
from tests.basicswap.util import (
|
||||
make_boolean,
|
||||
read_json_api,
|
||||
waitForServer,
|
||||
)
|
||||
|
||||
TEST_DELETE_DIRS = make_boolean(os.getenv("TEST_DELETE_DIRS", True))
|
||||
bin_path = os.path.expanduser(os.getenv("TEST_BIN_PATH", ""))
|
||||
test_base_path = os.path.expanduser(os.getenv("TEST_PREPARE_PATH", "~/test_basicswap"))
|
||||
test_path_plain = os.path.join(test_base_path, "plain")
|
||||
test_path_encrypted = os.path.join(test_base_path, "encrypted")
|
||||
test_path_encrypt = os.path.join(test_base_path, "encrypt")
|
||||
|
||||
|
||||
delay_event = threading.Event()
|
||||
logger = logging.getLogger()
|
||||
logger.level = logging.DEBUG
|
||||
|
@ -59,14 +63,28 @@ def start_run(args, env_pairs=[]):
|
|||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(Test, cls).setUpClass()
|
||||
# Reset env vars
|
||||
reset_vars = ["BSX_ALLOW_ENV_OVERRIDE", "BSX_DOCKER_MODE", "BSX_LOCAL_TOR"]
|
||||
for var_name in reset_vars:
|
||||
if var_name in os.environ:
|
||||
del os.environ[var_name]
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(self):
|
||||
try:
|
||||
for test_dir in (test_path_plain, test_path_encrypted, test_path_encrypt):
|
||||
if os.path.exists(test_dir):
|
||||
shutil.rmtree(test_dir)
|
||||
if TEST_DELETE_DIRS:
|
||||
for test_dir in (
|
||||
test_path_plain,
|
||||
test_path_encrypted,
|
||||
test_path_encrypt,
|
||||
):
|
||||
if os.path.exists(test_dir):
|
||||
shutil.rmtree(test_dir)
|
||||
except Exception as ex:
|
||||
logger.warning("tearDownClass %s", str(ex))
|
||||
logger.warning(f"tearDownClass {ex}")
|
||||
super(Test, self).tearDownClass()
|
||||
|
||||
def test_plain(self):
|
||||
|
@ -146,6 +164,7 @@ class Test(unittest.TestCase):
|
|||
self.assertTrue(
|
||||
settings["chainclients"]["bitcoin"]["connection_type"] == "rpc"
|
||||
)
|
||||
assert settings.get("use_tor", False) is False
|
||||
|
||||
logging.info("notorproxy")
|
||||
testargs = [
|
||||
|
@ -165,8 +184,89 @@ class Test(unittest.TestCase):
|
|||
"--usetorproxy and --notorproxy together" in fake_stderr.getvalue()
|
||||
)
|
||||
|
||||
logger.info("Test persistent setup config.")
|
||||
|
||||
with open(config_path) as fs:
|
||||
settings = json.load(fs)
|
||||
assert settings.get("use_tor", False) is False
|
||||
assert settings["setup_docker_mode"] is False
|
||||
assert settings["setup_local_tor"] is False
|
||||
assert "setup_tor_control_listen_interface" not in settings
|
||||
assert "setup_torrc_dns_host" not in settings
|
||||
|
||||
os.environ["BSX_LOCAL_TOR"] = "true"
|
||||
# Reimport to reset globals and set env
|
||||
importlib.reload(prepareSystem)
|
||||
|
||||
testargs = [
|
||||
"basicswap-prepare",
|
||||
"-datadir=" + test_path_plain,
|
||||
"--enabletor",
|
||||
]
|
||||
with patch("sys.stderr", new=StringIO()) as fake_stderr:
|
||||
with patch.object(sys, "argv", testargs):
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
prepareSystem.main()
|
||||
|
||||
self.assertEqual(cm.exception.code, 1)
|
||||
self.assertTrue(
|
||||
"Env var BSX_LOCAL_TOR differs from saved config"
|
||||
in fake_stderr.getvalue()
|
||||
)
|
||||
|
||||
os.environ["BSX_ALLOW_ENV_OVERRIDE"] = "true"
|
||||
os.environ["TOR_CONTROL_LISTEN_INTERFACE"] = "127.1.1.1"
|
||||
importlib.reload(prepareSystem)
|
||||
|
||||
with patch.object(sys, "argv", testargs):
|
||||
prepareSystem.main()
|
||||
|
||||
with open(config_path) as fs:
|
||||
settings = json.load(fs)
|
||||
assert settings.get("use_tor", False) is True
|
||||
assert settings["setup_docker_mode"] is False
|
||||
assert settings["setup_local_tor"] is True
|
||||
assert settings["setup_tor_control_listen_interface"] == "127.1.1.1"
|
||||
assert "setup_torrc_dns_host" not in settings
|
||||
|
||||
particl_config_path = os.path.join(
|
||||
test_path_plain, "particl", "particl.conf"
|
||||
)
|
||||
with open(particl_config_path) as fs:
|
||||
particl_conf = fs.read()
|
||||
assert "bind=127.1.1.1:" in particl_conf
|
||||
|
||||
testargs = [
|
||||
"basicswap-prepare",
|
||||
"-datadir=" + test_path_plain,
|
||||
"-disablecoin=bitcoin",
|
||||
]
|
||||
with patch.object(sys, "argv", testargs):
|
||||
prepareSystem.main()
|
||||
|
||||
os.environ["TOR_PROXY_HOST"] = "127.2.2.2"
|
||||
del os.environ["BSX_ALLOW_ENV_OVERRIDE"]
|
||||
importlib.reload(prepareSystem)
|
||||
|
||||
testargs = [
|
||||
"basicswap-prepare",
|
||||
"-datadir=" + test_path_plain,
|
||||
"-addcoin=bitcoin",
|
||||
"-notorproxy", # Disable TOR connection check
|
||||
]
|
||||
with patch("sys.stderr", new=StringIO()) as fake_stderr:
|
||||
with patch.object(sys, "argv", testargs):
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
prepareSystem.main()
|
||||
|
||||
self.assertEqual(cm.exception.code, 1)
|
||||
self.assertTrue(
|
||||
"Env var TOR_PROXY_HOST differs from saved config"
|
||||
in fake_stderr.getvalue()
|
||||
)
|
||||
|
||||
finally:
|
||||
del prepareSystem
|
||||
del prepareSystem # Does not cause next import to refresh globals and env (tested v3.13)
|
||||
|
||||
def test_encrypted(self):
|
||||
if os.path.exists(test_path_encrypted):
|
||||
|
|
|
@ -12,6 +12,7 @@ import os
|
|||
import random
|
||||
import shutil
|
||||
import signal
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
|
@ -350,7 +351,7 @@ class BaseTest(unittest.TestCase):
|
|||
logger.handlers = []
|
||||
logger.setLevel(logging.INFO) # DEBUG shows many messages from requests.post
|
||||
formatter = logging.Formatter("%(asctime)s %(levelname)s : %(message)s")
|
||||
stream_stdout = logging.StreamHandler()
|
||||
stream_stdout = logging.StreamHandler(sys.stdout)
|
||||
stream_stdout.setFormatter(formatter)
|
||||
logger.addHandler(stream_stdout)
|
||||
|
||||
|
|
|
@ -19,7 +19,11 @@ REQUIRED_SETTINGS = {
|
|||
}
|
||||
|
||||
|
||||
def make_boolean(s):
|
||||
def make_boolean(s) -> bool:
|
||||
if isinstance(s, bool):
|
||||
return s
|
||||
if isinstance(s, int):
|
||||
return False if s == 0 else True
|
||||
return s.lower() in ["1", "true"]
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue