summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorms <ms@taler.net>2021-09-27 18:15:30 +0200
committerms <ms@taler.net>2021-09-27 18:15:30 +0200
commit1a41de419330ab450ff524583eebe758a3b39672 (patch)
treecfba2968bdffcaf6b2d65ba820dbbc5cce5120d2
parent78a499ecc87544b5ca95acf1d6addd05c7153cf5 (diff)
downloaddeployment-1a41de419330ab450ff524583eebe758a3b39672.tar.gz
deployment-1a41de419330ab450ff524583eebe758a3b39672.tar.bz2
deployment-1a41de419330ab450ff524583eebe758a3b39672.zip
taler-local: arranging code, check state before starting
-rwxr-xr-xbin/WIP/taler-local620
1 files changed, 365 insertions, 255 deletions
diff --git a/bin/WIP/taler-local b/bin/WIP/taler-local
index af7d633..6bfcbca 100755
--- a/bin/WIP/taler-local
+++ b/bin/WIP/taler-local
@@ -15,6 +15,8 @@
# You should have received a copy of the GNU General Public License
# along with GNU Taler. If not, see <https://www.gnu.org/licenses/>.
+import signal
+import socket
import shutil
import atexit
import click
@@ -35,7 +37,7 @@ from shutil import copy
from multiprocessing import Process
from string import ascii_letters, ascii_uppercase
from sys import exit
-from urllib.parse import urljoin
+from urllib.parse import urljoin, quote
from os import remove
import requests
from collections import OrderedDict
@@ -48,6 +50,12 @@ from flask import Flask, request, Response
from werkzeug.datastructures import Headers
from werkzeug.exceptions import HTTPException
+
+TALER_ROOT_DIR = Path.home() / ".taler"
+# Print No Newline.
+def print_nn(msg):
+ print(msg, end="")
+
@dataclass
class Repo:
name: str
@@ -295,7 +303,7 @@ repos = {
}
def get_repos_names() -> List[str]:
- r_dir = Path.home() / ".taler-sources"
+ r_dir = TALER_ROOT_DIR / "sources"
return [el for el in listdir(r_dir) if isdir(join(r_dir, el)) and repos.get(el)]
# Get the installed repositories from the sources directory.
@@ -304,7 +312,7 @@ def load_repos(reposNames) -> List[Repo]:
def update_repos(repos: List[Repo]) -> None:
for r in repos:
- r_dir = Path.home() / ".taler-sources" / r.name
+ r_dir = TALER_ROOT_DIR / "sources" / r.name
subprocess.run(["git", "-C", str(r_dir), "fetch"], check=True)
res = subprocess.run(
["git", "-C", str(r_dir), "status", "-sb"],
@@ -322,7 +330,7 @@ def get_stale_repos(repos: List[Repo]) -> List[Repo]:
timestamps = {}
stale = []
for r in repos:
- r_dir = Path.home() / ".taler-sources" / r.name
+ r_dir = TALER_ROOT_DIR / "sources" / r.name
s = r_dir / "taler-buildstamp"
if not s.exists():
timestamps[r.name] = time.time()
@@ -367,23 +375,10 @@ def build(without_repos) -> None:
diff = set(r.deps) - set(repos_names)
if len(diff) > 0:
print(f"WARNING: those dependencies are not being built: {diff}")
- p = Path.home() / ".taler-sources" / r.name
+ p = TALER_ROOT_DIR / "sources" / r.name
os.chdir(str(p))
r.builder(r, p)
-# Download the repository.
-def checkout_repos(repos: List[Repo]):
- if len(repos) == 0:
- print("No repositories can be checked out. Spelled correctly?")
- return
- home = Path.home()
- sources = home / ".taler-sources"
- for r in repos:
- r_dir = home / ".taler-sources" / r.name
- if not r_dir.exists():
- r_dir.mkdir(parents=True, exist_ok=True)
- subprocess.run(["git", "-C", str(sources), "clone", r.url], check=True)
-
@cli.command()
@click.option(
"--repos", "-r",
@@ -395,20 +390,50 @@ def checkout_repos(repos: List[Repo]):
def bootstrap(repos) -> None:
"""Clone all the specified repositories."""
- home = Path.home()
+
+ # Download the repository.
+ def checkout_repos(repos: List[Repo]):
+ if len(repos) == 0:
+ print("No repositories can be checked out. Spelled correctly?")
+ return
+ sources = TALER_ROOT_DIR / "sources"
+ for r in repos:
+ r_dir = sources / r.name
+ if not r_dir.exists():
+ r_dir.mkdir(parents=True, exist_ok=True)
+ subprocess.run(["git", "-C", str(sources), "clone", r.url], check=True)
+
reposList = split_repos_list(repos)
checkout_repos(load_repos(reposList))
class TalerReverseProxy(Flask):
+ def __init__(self, log_dir, unix_sockets_dir):
+ super().__init__("taler-proxy")
+ all_methods = [
+ "GET", "POST", "HEAD",
+ "DELETE", "OPTIONS", "PUT"
+ ]
+ self.log_dir = log_dir
+ self.unix_sockets_dir = unix_sockets_dir
+ self.add_url_rule("/", view_func=self.index)
+ self.add_url_rule("/<component>", view_func=self.proxy, methods=all_methods)
+ self.add_url_rule("/<component>/", view_func=self.proxy, methods=all_methods)
+ self.add_url_rule("/<component>/<path:path>", view_func=self.proxy, methods=all_methods)
+
def stop(self):
self.proc.terminate()
self.proc.join()
del os.environ["WERKZEUG_RUN_MAIN"]
+ def get_log_filename(self):
+ return self.logger.handlers[0].baseFilename
+
def start(self):
- logging.basicConfig(filename="/tmp/reverse-proxy.log", filemode="a")
- logger = logging.getLogger("werkzeug")
- logger.setLevel(logging.DEBUG)
+ if not self.log_dir.is_dir():
+ os.makedirs(self.log_dir)
+ logging.basicConfig(filename=self.log_dir / "reverse-proxy.log", filemode="a")
+ self.logger = logging.getLogger("werkzeug")
+ self.logger.setLevel(logging.DEBUG)
self.proc = Process(
target=self.run,
kwargs=dict(debug=False, port=8080, host="localhost")
@@ -424,7 +449,8 @@ class TalerReverseProxy(Flask):
logger = logging.getLogger("werkzeug")
logger.setLevel(logging.DEBUG)
s = Session()
- uri = f"http+unix://%2Ftmp%2F{component}.sock/{path}"
+ sockets_dir_urlenc = quote(str(self.unix_sockets_dir), safe="")
+ uri = f"http+unix://%2F{sockets_dir_urlenc}%2F{component}.sock/{path}"
raw_data = request.get_data()
if len(request.args) > 0:
uri += f"?{request.query_string.decode()}"
@@ -455,17 +481,6 @@ class TalerReverseProxy(Flask):
def get_app(self):
return self
- def __init__(self):
- super().__init__("taler-proxy")
- all_methods = [
- "GET", "POST", "HEAD",
- "DELETE", "OPTIONS", "PUT"
- ]
- self.add_url_rule("/", view_func=self.index)
- self.add_url_rule("/<component>", view_func=self.proxy, methods=all_methods)
- self.add_url_rule("/<component>/", view_func=self.proxy, methods=all_methods)
- self.add_url_rule("/<component>/<path:path>", view_func=self.proxy, methods=all_methods)
-
@cli.command()
def prepare():
@@ -474,69 +489,12 @@ def prepare():
def fail(reason=None):
if reason:
print("ERROR: " + reason)
- print("See logs in /tmp/$component.log")
exit(1)
-
- # Print No Newline.
- def print_nn(msg):
- print(msg, end="")
-
- # Runs a command synchronously.
- def cmd(
- args, env=os.environ,
- custom_name=None, return_stdout=False
- ):
- handle = launch(
- args, env=env,
- custom_name=custom_name,
- return_stdout=return_stdout
- )
- return_code = handle.wait()
- if return_code != 0:
- print("\nCommand: " + " ".join(args) + " failed, return code: " + str(return_code))
- name = custom_name if custom_name else args[0]
- print(f"See logs in /tmp/{name}.log")
- exit(return_code)
- return handle
def kill(proc):
proc.terminate()
proc.wait()
-
- # Runs a command in the background.
- def launch(cmd, env=os.environ, custom_name=None, return_stdout=False):
- name = custom_name if custom_name else cmd[0]
- log_file = open(f"/tmp/{name}.log", "a+")
- try:
- handle = Popen(
- cmd,
- stdin=DEVNULL,
- stdout=log_file if not return_stdout else PIPE,
- stderr=log_file,
- env=env
- )
- except Exception as error:
- fail(f"Could not launch: {name}: {error}")
- atexit.register(lambda: kill(handle))
- return handle
-
- def check_running(check_url):
- for i in range(10):
- print_nn(".")
- try:
- # Raises if the service is not reachable.
- response = requests.get(check_url)
- # Raises if the request gets a non 200 OK.
- response.raise_for_status()
- except:
- if i == 9:
- print("FAIL")
- return False
- time.sleep(0.5)
- continue
- break
- return True
-
+
def get_nexus_cli_env(
username, password,
nexus_url
@@ -571,7 +529,7 @@ def prepare():
env
):
# make connection
- cmd(
+ Command(
[
"libeufin-cli", "connections",
"new-ebics-connection",
@@ -582,25 +540,26 @@ def prepare():
bank_connection_name
],
env
- )
+ ).run()
+
# connect
- cmd(
+ Command(
[
"libeufin-cli", "connections",
"connect", bank_connection_name
],
env
- )
+ ).run()
# Import bank account
- cmd(
+ Command(
[
"libeufin-cli", "connections",
"download-bank-accounts",
bank_connection_name
],
env
- )
- cmd(
+ ).run()
+ Command(
[
"libeufin-cli", "connections",
"import-bank-account",
@@ -611,9 +570,9 @@ def prepare():
bank_connection_name
],
env
- )
+ ).run()
# Set background tasks.
- cmd(
+ Command(
[
"libeufin-cli", "accounts",
"task-schedule", bank_account_name_nexus,
@@ -622,8 +581,8 @@ def prepare():
"--task-cronspec", "* * *"
],
env
- )
- cmd(
+ ).run()
+ Command(
[
"libeufin-cli", "accounts",
"task-schedule", bank_account_name_nexus,
@@ -634,7 +593,7 @@ def prepare():
"--task-param-range-type", "latest"
],
env
- )
+ ).run()
def prepare_sandbox_account(
currency,
@@ -647,7 +606,7 @@ def prepare():
bank_account_iban,
env
):
- cmd(
+ Command(
[
"libeufin-cli", "sandbox",
"--sandbox-url", sandbox_url,
@@ -657,8 +616,8 @@ def prepare():
"--user-id", ebics_user_id
],
env
- )
- cmd(
+ ).run()
+ Command(
[
"libeufin-cli", "sandbox",
"--sandbox-url", sandbox_url,
@@ -673,8 +632,120 @@ def prepare():
"--currency", currency
],
env
- )
+ ).run()
+
+ CURRENCY = "EUR"
+ WIRE_METHOD = "sepa"
+
+ # Filesystem's paths
+ CFG_OUTDIR = TALER_ROOT_DIR / "config"
+ UNIX_SOCKETS_DIR = TALER_ROOT_DIR / "sockets"
+ TALER_RUNTIME_DIR = TALER_ROOT_DIR / "runtime"
+ TALER_DATA_DIR = TALER_ROOT_DIR / "data"
+ LOG_DIR = TALER_ROOT_DIR / "logs"
+ # IBANs
+ IBAN_EXCHANGE = "EX00000000000000000000"
+ IBAN_MERCHANT = "ME00000000000000000001"
+ IBAN_CUSTOMER = "WA00000000000000000000"
+
+ # Credentials / API keys
+ SANDBOX_ADMIN_USERNAME = "admin"
+ SANDBOX_ADMIN_PASSWORD = "secret"
+ EXCHANGE_NEXUS_USERNAME = "exchange-nexus-user"
+ EXCHANGE_NEXUS_PASSWORD = "exchange-nexus-password"
+ FRONTENDS_API_TOKEN = "secret:secret"
+ TALER_MERCHANT_TOKEN = "secret:secret" # same as above?
+
+ # URLs
+ REV_PROXY = "http://localhost:8080"
+ SANDBOX_URL = REV_PROXY + "/sandbox"
+ NEXUS_URL = REV_PROXY + "/nexus"
+
+ # EBICS
+ EBICS_HOST_ID = "ebicsDeployedHost"
+ EXCHANGE_EBICS_USER_ID = "exchangeEbicsUserId"
+ EXCHANGE_EBICS_PARTNER_ID = "exchangeEbicsPartnerId"
+ EBICS_URL = REV_PROXY + "/sandbox/ebicsweb"
+
+ # euFin
+ NEXUS_DB_FILE = "/tmp/nexus.sqlite"
+ SANDBOX_DB_FILE = "/tmp/sandbox.sqlite"
+ EXCHANGE_BANK_ACCOUNT_NEXUS = "exchange-imported-account-nexus"
+ EXCHANGE_BANK_ACCOUNT_SANDBOX = "exchange-account-sandbox"
+ EXCHANGE_BANK_CONNECTION = "exchange-ebics-connection"
+ EXCHANGE_FACADE_NAME = "exchange-taler-facade"
+
+ class Command:
+ def __init__(
+ self, cmd, env=os.environ, log_dir=LOG_DIR,
+ custom_name=None, capture_stdout=False
+ ):
+ if len(cmd) == 0:
+ fail("Could not find a command to execute")
+ self.name = custom_name if custom_name else cmd[0]
+ self.cmd = cmd
+ self.env=env
+ self.capture_stdout=capture_stdout
+ self.log_dir = log_dir
+
+ @staticmethod
+ def is_serving(check_url):
+ for i in range(10):
+ print_nn(".")
+ try:
+ # Raises if the service is not reachable.
+ response = requests.get(check_url)
+ # Raises if the request gets a non 200 OK.
+ response.raise_for_status()
+ except:
+ if i == 9:
+ return False
+ time.sleep(0.5)
+ continue
+ break
+ return True
+
+ def run(self):
+ self.do()
+ return_code = self.handle.wait()
+ if return_code != 0:
+ fail(f"Command {self.name} failed. Logs in {self.get_log_filename()}")
+ self.cleanup()
+ if self.capture_stdout:
+ return self.handle.communicate()[0].decode("utf-8").rstrip()
+
+ def launch(self):
+ self.do()
+ return self
+
+ def stop(self):
+ self.cleanup()
+ self.handle.terminate()
+ self.handle.wait()
+
+ def get_log_filename(self):
+ return self.log_file.name
+
+ def cleanup(self):
+ if not self.log_file.closed:
+ self.log_file.close()
+ def do(self):
+ if not self.log_dir.is_dir():
+ os.makedirs(self.log_dir)
+ self.log_file = open(self.log_dir / (self.name + ".log"), "a+")
+ try:
+ self.handle = Popen(
+ self.cmd,
+ stdin=DEVNULL,
+ stdout=self.log_file if not self.capture_stdout else PIPE,
+ stderr=self.log_file,
+ env=self.env
+ )
+ except Exception as error:
+ fail(f"Could not launch: {self.name}: {error}")
+ atexit.register(self.stop)
+
class ConfigFile:
def __init__(self, filename):
self.sections = OrderedDict()
@@ -689,8 +760,9 @@ def prepare():
s[key] = value
def cfg_write(self, outdir):
-
if outdir:
+ if not os.path.isdir(outdir):
+ os.makedirs(outdir)
fstream = open(os.path.join(outdir, self.filename), "w")
else:
fstream = open(sys.stdout)
@@ -701,14 +773,36 @@ def prepare():
fstream.write(key + " = " + value + "\n")
fstream.write("\n")
fstream.close()
- # Writes on disk too, like the other config_* functions.
+
+ def config_specify_master_pub(
+ filename,
+ currency,
+ exchange_master_pub
+ ):
+ Command([
+ "taler-config", "-c", filename,
+ "-s", "exchange", "-o", "master_public_key",
+ "-V", exchange_master_pub
+ ]).run()
+ Command([
+ "taler-config", "-c", filename,
+ "-s", f"merchant-exchange-{currency}",
+ "-o", "master_key",
+ "-V", exchange_master_pub
+ ]).run()
+
+ # When called, there is no exchange master pub yet.
+ # taler-exchange-offline will prouce the key _after_
+ # taler.conf is generated. Only after that, we'll
+ # specify the master key where it is missing; namely
+ # in the merchant backend and exchange HTTP daemon sections.
def config_main(
filename,
outdir,
+ unix_sockets_dir,
currency,
rev_proxy_url,
wire_method,
- exchange_master_pub,
exchange_wire_address,
merchant_wire_address,
exchange_wire_gateway_username,
@@ -742,8 +836,8 @@ def prepare():
obj.cfg_put(sec, "rsa_keysize", rsa_keysize)
obj = ConfigFile("taler.conf")
- obj.cfg_put("paths", "TALER_DATA_HOME", "${HOME}/.taler-data")
- if not os.path.isdir(taler_runtime_dir):
+ obj.cfg_put("paths", "TALER_DATA_HOME", str(TALER_DATA_DIR))
+ if not taler_runtime_dir.is_dir():
os.makedirs(taler_runtime_dir)
obj.cfg_put("paths", "TALER_RUNTIME_DIR", str(taler_runtime_dir))
obj.cfg_put("taler", "CURRENCY", currency)
@@ -751,7 +845,7 @@ def prepare():
obj.cfg_put("bank", "serve", "uwsgi")
obj.cfg_put("bank", "uwsgi_serve", "unix")
- obj.cfg_put("bank", "uwsgi_unixpath", "/tmp/bank.sock")
+ obj.cfg_put("bank", "uwsgi_unixpath", str(unix_sockets_dir / "bank.sock"))
obj.cfg_put("bank", "uwsgi_unixpath_mode", "660")
obj.cfg_put("bank", "database", "taler")
obj.cfg_put("bank", "max_debt", "%s:500.0" % currency)
@@ -763,27 +857,27 @@ def prepare():
obj.cfg_put("donations", "serve", "uwsgi")
obj.cfg_put("donations", "uwsgi_serve", "unix")
- obj.cfg_put("donations", "uwsgi_unixpath", "/tmp/donations.sock")
+ obj.cfg_put("donations", "uwsgi_unixpath", str(unix_sockets_dir / "DONATIONS.Sock"))
obj.cfg_put("donations", "uwsgi_unixpath_mode", "660")
obj.cfg_put("landing", "serve", "uwsgi")
obj.cfg_put("landing", "uwsgi_serve", "unix")
- obj.cfg_put("landing", "uwsgi_unixpath", "/tmp/landing.sock")
+ obj.cfg_put("landing", "uwsgi_unixpath", str(unix_sockets_dir / "landing.sock"))
obj.cfg_put("landing", "uwsgi_unixpath_mode", "660")
obj.cfg_put("blog", "serve", "uwsgi")
obj.cfg_put("blog", "uwsgi_serve", "unix")
- obj.cfg_put("blog", "uwsgi_unixpath", "/tmp/blog.sock")
+ obj.cfg_put("blog", "uwsgi_unixpath", str(unix_sockets_dir / "blog.sock"))
obj.cfg_put("blog", "uwsgi_unixpath_mode", "660")
obj.cfg_put("survey", "serve", "uwsgi")
obj.cfg_put("survey", "uwsgi_serve", "unix")
- obj.cfg_put("survey", "uwsgi_unixpath", "/tmp/survey.sock")
+ obj.cfg_put("survey", "uwsgi_unixpath", str(unix_sockets_dir / "survey.sock"))
obj.cfg_put("survey", "uwsgi_unixpath_mode", "660")
obj.cfg_put("survey", "bank_password", "x")
obj.cfg_put("merchant", "serve", "unix")
- obj.cfg_put("merchant", "unixpath", "/tmp/merchant-backend.sock")
+ obj.cfg_put("merchant", "unixpath", str(unix_sockets_dir / "merchant-backend.sock"))
obj.cfg_put("merchant", "wire_transfer_delay", "0 s")
obj.cfg_put("merchant", "default_max_wire_fee", currency + ":" + "0.01")
obj.cfg_put("merchant", "default_max_deposit_fee", currency + ":" + "0.05")
@@ -794,35 +888,34 @@ def prepare():
"merchant-exchange-{}".format(currency),
"exchange_base_url", rev_proxy_url + "/exchange/",
)
- obj.cfg_put(
- "merchant-exchange-{}".format(currency),
- "master_key", exchange_master_pub,
- )
-
obj.cfg_put("auditor", "serve", "unix")
# FIXME: both below used?
obj.cfg_put("auditor", "base_url", rev_proxy_url + "/auditor")
obj.cfg_put("auditor", "auditor_url", rev_proxy_url + "/auditor")
- obj.cfg_put("auditor", "unixpath", "/tmp/auditor.sock")
+ obj.cfg_put("auditor", "unixpath", str(unix_sockets_dir / "auditor.sock"))
obj.cfg_put("auditor", "tiny_amount", currency + ":0.01")
- obj.cfg_put("taler-exchange-secmod-eddsa", "unixpath", "/tmp/exchange-secmod-eddsa.sock")
- obj.cfg_put("taler-exchange-secmod-rsa", "unixpath", "/tmp/exchange-secmod-rsa.sock")
+ obj.cfg_put(
+ "taler-exchange-secmod-eddsa",
+ "unixpath",
+ str(unix_sockets_dir / "exchange-secmod-eddsa.sock")
+ )
+ obj.cfg_put(
+ "taler-exchange-secmod-rsa",
+ "unixpath",
+ str(unix_sockets_dir / "exchange-secmod-rsa.sock")
+ )
obj.cfg_put("taler-exchange-secmod-rsa", "sm_priv_key",
- "/tmp/.taler-data/taler-exchange-secmod-rsa/secmod-private-key"
+ "${TALER_DATA_HOME}/taler-exchange-secmod-rsa/secmod-private-key"
)
obj.cfg_put("exchange", "base_url", rev_proxy_url + "/exchange/")
- obj.cfg_put("exchange", "master_public_key", exchange_master_pub)
-
obj.cfg_put("exchange", "serve", "unix")
- obj.cfg_put("exchange", "unixpath", "/tmp/exchange.sock")
-
+ obj.cfg_put("exchange", "unixpath", str(unix_sockets_dir / "exchange.sock"))
obj.cfg_put("exchange", "terms_etag", "0")
obj.cfg_put("exchange", "terms_dir", "$HOME/.local/share/taler-exchange/tos")
obj.cfg_put("exchange", "privacy_etag", "0")
obj.cfg_put("exchange", "privacy_dir", "$HOME/.local/share/taler-exchange/pp")
-
obj.cfg_put("exchangedb-postgres", "db_conn_str", "postgres:///taler")
obj.cfg_put("exchangedb-postgres", "config", "postgres:///taler")
obj.cfg_put("auditordb-postgres", "db_conn_str", "postgres:///taler")
@@ -854,11 +947,11 @@ def prepare():
obj.cfg_write(outdir)
return obj
- def config_sync(filename, outdir, currency, api_key, rev_proxy_url):
+ def config_sync(filename, outdir, unix_sockets_dir, currency, api_key, rev_proxy_url):
obj = ConfigFile(filename)
obj.cfg_put("taler", "currency", currency)
obj.cfg_put("sync", "serve", "unix")
- obj.cfg_put("sync", "unixpath", "$HOME/sockets/sync.http")
+ obj.cfg_put("sync", "unixpath", str(unix_sockets_dir / "sync.sock"))
obj.cfg_put("sync", "apikey", f"Bearer {api_key}")
obj.cfg_put("sync", "annual_fee", f"{currency}:0.1")
obj.cfg_put("sync", "fulfillment_url", "taler://fulfillment-success/")
@@ -866,12 +959,12 @@ def prepare():
obj.cfg_put("syncdb-postgres", "config", f"postgres:///taler")
obj.cfg_write(outdir)
- def config_anastasis(filename, outdir, currency, rev_proxy_url, api_key):
+ def config_anastasis(filename, outdir, unix_sockets_dir, currency, rev_proxy_url, api_key):
obj = ConfigFile(filename)
obj.cfg_put("taler", "currency", currency)
obj.cfg_put("anastasis", "serve", "unix")
obj.cfg_put("anastasis", "business_name", f"GNU Taler Demo Anastasis Provider")
- obj.cfg_put("anastasis", "unixpath", "/tmp/anastasis.sock")
+ obj.cfg_put("anastasis", "unixpath", str(unix_sockets_dir / "anastasis.sock"))
obj.cfg_put("anastasis", "annual_fee", f"{currency}:0")
obj.cfg_put("anastasis", "question_cost", f"{currency}:0")
obj.cfg_put("anastasis", "insurance", f"{currency}:0")
@@ -887,68 +980,35 @@ def prepare():
obj.cfg_put("authorization-question", "cost", f"{currency}:0")
obj.cfg_put("authorization-question", "enabled", "yes")
obj.cfg_write(outdir)
-
- CURRENCY = "EUR"
- WIRE_METHOD = "sepa"
-
- # Directories
- CFG_OUTDIR = Path.home() / ".config"
- TALER_RUNTIME_DIR = Path.home() / ".taler-runtime"
- TALER_DATA_DIR = Path.home() / ".taler-data"
-
- # IBANs
- IBAN_EXCHANGE = "EX00000000000000000000"
- IBAN_MERCHANT = "ME00000000000000000001"
- IBAN_CUSTOMER = "WA00000000000000000000"
-
- # Credentials / API keys
- SANDBOX_ADMIN_USERNAME = "admin"
- SANDBOX_ADMIN_PASSWORD = "secret"
- EXCHANGE_NEXUS_USERNAME = "exchange-nexus-user"
- EXCHANGE_NEXUS_PASSWORD = "exchange-nexus-password"
- FRONTENDS_API_TOKEN = "secret:secret"
- TALER_MERCHANT_TOKEN = "secret:secret" # same as above?
- # URLs
- REV_PROXY = "http://localhost:8080"
- SANDBOX_URL = REV_PROXY + "/sandbox"
- NEXUS_URL = REV_PROXY + "/nexus"
-
- # EBICS
- EBICS_HOST_ID = "ebicsDeployedHost"
- EXCHANGE_EBICS_USER_ID = "exchangeEbicsUserId"
- EXCHANGE_EBICS_PARTNER_ID = "exchangeEbicsPartnerId"
- EBICS_URL = REV_PROXY + "/sandbox/ebicsweb"
+ print_nn("Ensure no service is running...")
+ if Command.is_serving(REV_PROXY + "/"):
+ fail("Reverse proxy is unexpectedly running!")
+ if UNIX_SOCKETS_DIR.is_dir():
+ for left_socket in os.listdir(UNIX_SOCKETS_DIR):
+ s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ socket_file = str(UNIX_SOCKETS_DIR / left_socket)
+ if s.connect_ex(socket_file.encode("utf-8")) == 0:
+ fail(f"A service is unexpectedly running and bound to {socket_file}!")
+ print(" OK")
- # euFin
- NEXUS_DB_FILE = "/tmp/nexus.sqlite"
- SANDBOX_DB_FILE = "/tmp/sandbox.sqlite"
- EXCHANGE_BANK_ACCOUNT_NEXUS = "exchange-imported-account-nexus"
- EXCHANGE_BANK_ACCOUNT_SANDBOX = "exchange-account-sandbox"
- EXCHANGE_BANK_CONNECTION = "exchange-ebics-connection"
- EXCHANGE_FACADE_NAME = "exchange-taler-facade"
-
- print_nn("Remove stale data..")
+ print_nn("Remove stale data and config...")
if TALER_DATA_DIR.exists():
shutil.rmtree(TALER_DATA_DIR)
if TALER_RUNTIME_DIR.exists():
shutil.rmtree(TALER_RUNTIME_DIR)
+ if CFG_OUTDIR.exists():
+ shutil.rmtree(CFG_OUTDIR)
print(" OK")
- print_nn("Generate exchange's master key...")
- res = cmd(
- ["taler-exchange-offline", "setup"],
- return_stdout=True
- )
- EXCHANGE_MASTER_PUB = res.communicate()[0].decode("utf-8").rstrip()
- print(" OK")
-
+
+ print_nn("Generate preliminary taler.conf...")
mc = config_main(
"taler.conf",
outdir=CFG_OUTDIR,
+ unix_sockets_dir=UNIX_SOCKETS_DIR,
currency=CURRENCY,
rev_proxy_url=REV_PROXY,
wire_method=WIRE_METHOD,
- exchange_master_pub=EXCHANGE_MASTER_PUB,
exchange_wire_address=IBAN_EXCHANGE,
merchant_wire_address=IBAN_MERCHANT,
exchange_wire_gateway_username=EXCHANGE_NEXUS_USERNAME,
@@ -956,65 +1016,104 @@ def prepare():
frontend_api_key=FRONTENDS_API_TOKEN,
taler_runtime_dir=TALER_RUNTIME_DIR
)
+ print(" OK")
+ print_nn("Generate exchange's master key...")
+ EXCHANGE_MASTER_PUB = Command(
+ [
+ "taler-exchange-offline",
+ "-c", CFG_OUTDIR / "taler.conf",
+ "setup"
+ ],
+ capture_stdout=True
+ ).run()
+ print(" OK")
+ print_nn("Specify exchange master pub in taler.conf...")
+ config_specify_master_pub(
+ CFG_OUTDIR / "taler.conf",
+ CURRENCY,
+ EXCHANGE_MASTER_PUB
+ )
+ print(" OK")
+ print_nn("Generating sync.conf...")
config_sync(
"sync.conf",
outdir=CFG_OUTDIR,
+ unix_sockets_dir=UNIX_SOCKETS_DIR,
currency=CURRENCY,
api_key=FRONTENDS_API_TOKEN,
rev_proxy_url=REV_PROXY
)
+ print(" OK")
+ print_nn("Generating anastasis.conf...")
config_anastasis(
"anastasis.conf",
outdir=CFG_OUTDIR,
+ unix_sockets_dir=UNIX_SOCKETS_DIR,
currency=CURRENCY,
rev_proxy_url=REV_PROXY,
api_key=FRONTENDS_API_TOKEN
)
-
- print_nn("Reset and init exchange DB..")
- cmd(["taler-exchange-dbinit", "--reset"])
print(" OK")
-
- print_nn("Remove previous key and data files..")
- cmd(
- ["rm", "-fr", Path.home() / ".taler-data" / "*"],
- custom_name="remove-taler-data"
- )
+ print_nn("Reset and init exchange DB..")
+ Command([
+ "taler-exchange-dbinit",
+ "-c", CFG_OUTDIR / "taler.conf",
+ "--reset"]
+ ).run()
print(" OK")
-
print_nn("Launching the reverse proxy...")
- rev_proxy = TalerReverseProxy()
+ rev_proxy = TalerReverseProxy(LOG_DIR, UNIX_SOCKETS_DIR)
rev_proxy.start()
- if not check_running(REV_PROXY + "/"):
- fail("Reverse proxy did not start correctly.")
+ if not Command.is_serving(REV_PROXY + "/"):
+ fail(f"Reverse proxy did not start correctly. \
+Logs: {rev_proxy.get_log_filename()}"
+ )
# Do check.
print(" OK")
print_nn("Launching the exchange RSA helper...")
- exchange_rsa_handle = launch(["taler-exchange-secmod-rsa"])
+ exchange_rsa_handle = Command([
+ "taler-exchange-secmod-rsa",
+ "-c", CFG_OUTDIR / "taler.conf"
+ ]).launch()
print(" OK")
print_nn("Launching the exchange EDDSA helper...")
- exchange_eddsa_handle = launch(["taler-exchange-secmod-eddsa"])
+ exchange_eddsa_handle = Command([
+ "taler-exchange-secmod-eddsa",
+ "-c", CFG_OUTDIR / "taler.conf"
+ ]).launch()
print(" OK")
print_nn("Launching the exchange...")
- exchange_handle = launch(["taler-exchange-httpd"])
- if not check_running(REV_PROXY + "/exchange/"):
- fail("Exchange did not start correctly.")
+ exchange_handle = Command([
+ "taler-exchange-httpd",
+ "-c", CFG_OUTDIR / "taler.conf"
+ ]).launch()
+ if not Command.is_serving(REV_PROXY + "/exchange/"):
+ fail(f"Exchange did not start correctly. Logs: {exchange_handle.get_log_filename()}")
print(" OK")
print_nn("exchange-offline: signing key material...")
- cmd(["taler-exchange-offline", "download", "sign", "upload"])
+ Command([
+ "taler-exchange-offline",
+ "-c", CFG_OUTDIR / "taler.conf",
+ "download", "sign", "upload"
+ ]).run()
print(" OK")
PAYTO_URI=mc.sections["exchange-account-1"]["payto_uri"]
print_nn(f"exchange-offline: enabling {PAYTO_URI}...")
- cmd(["taler-exchange-offline", "enable-account", PAYTO_URI, "upload"])
+ Command([
+ "taler-exchange-offline",
+ "-c", CFG_OUTDIR / "taler.conf",
+ "enable-account", PAYTO_URI, "upload"]
+ ).run()
print(" OK")
# Set up wire fees for next 5 years
NOW = datetime.now()
YEAR = NOW.year
print_nn("Setting wire fees for the next 5 years...")
for year in range(YEAR, YEAR+5):
- cmd(
+ Command(
[
"taler-exchange-offline",
+ "-c", CFG_OUTDIR / "taler.conf",
"wire-fee",
str(year),
WIRE_METHOD,
@@ -1023,21 +1122,22 @@ def prepare():
"upload"
],
custom_name="set-wire-fee"
- )
+ ).run()
print(" OK")
print_nn("Stopping exchange HTTP daemon and crypto helpers...")
- kill(exchange_rsa_handle)
- kill(exchange_eddsa_handle)
- kill(exchange_handle)
+ exchange_rsa_handle.stop()
+ exchange_eddsa_handle.stop()
+ exchange_handle.stop()
print(" OK")
print_nn("Add this exchange to the auditor...")
- cmd(
+ Command(
[
"taler-auditor-exchange",
+ "-c", CFG_OUTDIR / "taler.conf",
"-m", EXCHANGE_MASTER_PUB,
"-u", REV_PROXY + "/exchange/"
],
- )
+ ).run()
print(" OK")
## Step 4: Set up euFin
print_nn("Resetting euFin databases...")
@@ -1050,7 +1150,7 @@ def prepare():
print(" OK")
print_nn("Create Sandbox superuser...")
- cmd(
+ Command(
[
"libeufin-sandbox", "superuser",
SANDBOX_ADMIN_USERNAME,
@@ -1058,23 +1158,26 @@ def prepare():
],
custom_name="sandbox-superuser",
env=get_sandbox_server_env(SANDBOX_DB_FILE)
- )
+ ).run()
print(" OK")
+ # FIXME: tested until here. To proceed, euFin needs to
+ # bind to Unix domain sockets.
+ exit(1)
+
print_nn("Launching Sandbox...")
- handle_sandbox = launch(
+ sandbox_handle = Command(
[
"libeufin-sandbox", "serve",
- "--with-unix-socket", "/tmp/sandbox.sock",
+ "--with-unix-socket", UNIX_SOCKETS_DIR / "sandbox.sock",
],
env=get_sandbox_server_env(SANDBOX_DB_FILE)
- )
- if not check_running(SANDBOX_URL):
- fail("Sandbox did not start correctly")
+ ).launch()
+ if not Command.is_serving(SANDBOX_URL):
+ fail(f"Sandbox did not start correctly. Logs: {sandbox_handle.get_log_filename()}")
print(" OK")
- exit(22)
print_nn("Make Sandbox EBICS host...")
- cmd(
+ Command(
[
"libeufin-cli", "sandbox",
"--sandbox-url", SANDBOX_URL,
@@ -1086,7 +1189,7 @@ def prepare():
SANDBOX_ADMIN_PASSWORD
),
custom_name="sandbox-create-ebicshost",
- )
+ ).run()
print(" OK")
prepare_sandbox_account(
@@ -1132,22 +1235,22 @@ def prepare():
)
)
print_nn("Make Nexus superuser ...")
- cmd(
+ Command(
[
"libeufin-nexus", "superuser",
EXCHANGE_NEXUS_USERNAME,
"--password", EXCHANGE_NEXUS_PASSWORD
],
custom_name="nexus-superuser",
- )
+ ).run()
print(" OK")
print_nn("Launching Nexus...")
- handle_nexus = launch("nexus", [
+ nexus_handle = Command("nexus", [
"libeufin-nexus", "serve",
- "--with-unix-socket", "/tmp/nexus.sock"
- ])
- if not check_running(NEXUS_URL):
- fail("Nexus did not start correctly")
+ "--with-unix-socket", UNIX_SOCKETS_DIR / "nexus.sock"
+ ]).launch()
+ if not Command.is_serving(NEXUS_URL):
+ fail(f"Nexus did not start correctly. Logs: {nexus_handle.get_log_filename()}")
print(" OK")
prepare_nexus_account(
@@ -1165,7 +1268,7 @@ def prepare():
)
)
print_nn("Create Taler facade ...")
- cmd(
+ Command(
[
"libeufin-cli", "facades",
"new-taler-wire-gateway-facade",
@@ -1180,7 +1283,7 @@ def prepare():
NEXUS_URL
),
custom_name="create-taler-facade",
- )
+ ).run()
print(" OK")
try:
response = requests.get(
@@ -1197,45 +1300,52 @@ def prepare():
FACADE_URL=response.json().get("facade")[0].get("baseUrl")
print_nn("Terminating Nexus...")
- kill(handle_nexus)
+ nexus_handle.stop()
print(" OK")
print_nn("Terminating Sandbox...")
- kill(handle_sandbox)
+ sandbox_handle.stop()
print(" OK")
# Point the exchange to the facade.
- cmd(
+ Command(
[
- "taler-config", "-s"
+ "taler-config", "-s",
+ "-c", CFG_OUTDIR / "taler.conf",
f"exchange-account-credentials-1",
"-o" "wire_gateway_url",
"-V", FACADE_URL
],
custom_name="specify-facade-url",
- )
- cmd(
+ ).run()
+ Command(
[
- "taler-config", "-s"
- f"exchange-account-credentials-1",
+ "taler-config", "-s",
+ "-c", CFG_OUTDIR / "taler.conf",
+ "exchange-account-credentials-1",
"-o" "username",
"-V", EXCHANGE_NEXUS_USERNAME
],
custom_name="specify-username-for-facade",
- )
- cmd(
+ ).run()
+ Command(
[
- "taler-config", "-s"
- f"exchange-account-credentials-1",
+ "taler-config", "-s",
+ "-c", CFG_OUTDIR / "taler.conf",
+ "exchange-account-credentials-1",
"-o" "password",
"-V", EXCHANGE_NEXUS_PASSWORD
],
custom_name="specify-password-for-facade",
- )
+ ).run()
## Step 6: Set up merchant
print_nn("Reset and init merchant database...")
- cmd(["taler-merchant-dbinit", "--reset"])
+ Command([
+ "taler-merchant-dbinit",
+ "-c", CFG_OUTDIR / "taler.conf",
+ "--reset"
+ ]).run()
print(" OK")
def ensure_instance(
@@ -1282,12 +1392,12 @@ def prepare():
print_nn("Start merchant (with TALER_MERCHANT_TOKEN into the env)...")
auth_env = os.environ.copy()
auth_env["TALER_MERCHANT_TOKEN"] = TALER_MERCHANT_TOKEN
- merchant_handle = launch(
- ["taler-merchant-httpd"],
+ merchant_handle = Command(
+ ["taler-merchant-httpd", "-c", CFG_OUTDIR / "taler.conf"],
env=auth_env
- )
- if not check_running("/merchant-backend"):
- fail("Merchant backend did not start correctly")
+ ).launch()
+ if not Command.is_serving(REV_PROXY + "/merchant-backend"):
+ fail(f"Merchant backend did not start correctly. Logs: {merchant_handle.get_log_filename()}")
print(" OK")
ensure_instance(
@@ -1300,13 +1410,13 @@ def prepare():
auth_token=FRONTENDS_API_TOKEN
)
print_nn("Stopping the merchant...")
- kill(merchant_handle)
+ merchant_handle.stop()
print(" OK")
print_nn("Restarting the merchant WITHOUT the auth-token in the env...")
- merchant_handle = launch(["taler-merchant-httpd"])
- if not check_running("/merchant-backend"):
+ merchant_handle.launch()
+ if not Command.is_serving(REV_PROXY + "/merchant-backend"):
# check_running logs errors already.
- fail("Merchant backend did not start correctly")
+ fail(f"Merchant backend did not re start correctly. Logs: {merchant_handle.get_log_filename()}")
print(" OK")
print_nn("Creating the 'donations' instance...")
ensure_instance(