summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorms <ms@taler.net>2021-11-28 18:16:44 +0100
committerms <ms@taler.net>2021-11-28 18:16:44 +0100
commit3341cdfa5915725ae5a2059abab4444c94af437a (patch)
treeced052e45bfd3868e52860d39556dd20a8b7fe36
parent503cb67bdc52a6337830717bc8ffecaf066b94c5 (diff)
downloaddeployment-3341cdfa5915725ae5a2059abab4444c94af437a.tar.gz
deployment-3341cdfa5915725ae5a2059abab4444c94af437a.tar.bz2
deployment-3341cdfa5915725ae5a2059abab4444c94af437a.zip
taler-local
HTTP proxying and process management done only with Nginx and SystemD.
-rwxr-xr-xbin/WIP/taler-local662
1 files changed, 236 insertions, 426 deletions
diff --git a/bin/WIP/taler-local b/bin/WIP/taler-local
index a777ac7..e38a58d 100755
--- a/bin/WIP/taler-local
+++ b/bin/WIP/taler-local
@@ -434,141 +434,11 @@ def bootstrap(list_repos, repos) -> None:
reposList = split_repos_list(repos)
checkout_repos(load_repos(reposList))
-class TalerReverseProxy(Flask):
- def __init__(
- self,
- log_dir,
- unix_sockets_dir,
- proxy_proto,
- proxy_netloc
- ):
- 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.proxy_proto = proxy_proto
- self.proxy_netloc = proxy_netloc
- 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()
-
- def get_log_filename(self):
- return self.logger.root.handlers[0].baseFilename
-
- def start(self):
- 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)
- os.environ["WERKZEUG_RUN_MAIN"] = "true"
- self.proc = Process(
- target=self.run,
- kwargs=dict(debug=False, port=8080, host="localhost")
- )
-
- # This proxy does set Content-Length, as it often
- # reassembles chunked responses. Future versions
- # will echo back chunks as they arrive.
- # Response.automatically_set_content_length = False
-
- self.proc.start()
- atexit.register(self.stop)
-
- def index(self):
- return "I'm the Taler reverse proxy."
-
- def iter_response(self, r):
- for line in r.iter_lines():
- self.logger.debug("Responding chunk " + line.decode("utf-8"))
- yield line
-
- def proxy(self, component, path=""):
- s = Session()
- try:
- if request.method == "GET":
- method = s.get
- if request.method == "POST":
- method = s.post
- if request.method == "PUT":
- method = s.put
- if request.method == "DELETE":
- method = s.delete
- proxied_headers = {
- "X-Forwarded-Host": self.proxy_netloc,
- "X-Forwarded-Proto": self.proxy_proto,
- "X-Forwarded-Prefix": f"/{component}"
- }
- for k, v in request.headers.items():
- proxied_headers[k] = v
-
- socket_path = f"{self.unix_sockets_dir}/{component}.sock"
- self.logger.debug("Proxying to: " + socket_path + "/" + path)
- uri = f"http+unix://{quote(socket_path, safe='')}/{path.replace('?', '%3F')}"
- if len(request.args) > 0:
- uri += f"?{request.query_string.decode()}"
- resp = method(
- uri,
- headers=proxied_headers,
- data=request.get_data(),
- allow_redirects=False
- )
- except Exception as error:
- self.logger.error(error)
- self.logger.error(f"Failing request was: {request.get_data()}")
- return "Could not connect to upstream", 500
-
- self.logger.debug(f"Upstream responds: {resp.text}")
- headers = Headers()
- for k in resp.headers.keys():
- # This version does not send chunked responses, so
- # remove that header when it's found. Content-Length
- # will be added before sending the response.
- if k == "Transfer-Encoding" and resp.headers[k] == "chunked":
- continue
- # The content was already decompressed by this proxy, therefore
- # the following header would confuse the client.
- if k == "Content-Encoding" and (resp.headers[k] in ["deflate", "gzip"]):
- continue
- # 'requests' collapses multiple Set-Cookies response headers
- # into one (comma-separated list of cookie definitions). That
- # breaks browsers' cookie acceptance, resulting in HTTP sessions
- # being lost. A typical example is the blog shop not functioning
- # for this reason.
- #
- # Skipping here, as it appears to _still_ collapse them, even if
- # each one is individually set. Trying below via the "final" flask
- # Response object.
- if k == "Set-Cookie":
- continue
- headers.set(k, resp.headers[k])
-
- Resp = Response(
- response=resp.text,
- status=resp.status_code,
- headers=headers,
- )
- if "Set-Cookie" in resp.headers:
- cookies = resp.headers["Set-Cookie"].split(",")
- for cookie in cookies:
- Resp.headers.add("Set-Cookie", cookie.strip())
- return Resp
-
- def get_app(self):
- return self
-
-
# Globals sharead accross multiple sub-commands:
# needed to configure and launch the reverse proxy.
-REV_PROXY_NETLOC = "localhost:8080"
+REV_PROXY_HOSTNAME = "localhost"
+REV_PROXY_PORT = "8080"
+REV_PROXY_NETLOC = REV_PROXY_HOSTNAME + ":" + REV_PROXY_PORT
REV_PROXY_PROTO = "http"
REV_PROXY_URL = f"{REV_PROXY_PROTO}://{REV_PROXY_NETLOC}"
UNIX_SOCKETS_DIR = TALER_ROOT_DIR / "sockets"
@@ -586,11 +456,33 @@ def prepare():
"""Generate configuration, run-time blobs, instances, euFin accounts."""
- def fail(reason=None, proxy_proc=None):
+ def is_serving(check_url, tries=10):
+ for i in range(tries):
+ try:
+ print_nn(".")
+ # Raises if the service is not reachable.
+ response = requests.get(
+ check_url,
+ timeout=1
+ )
+ # The reverse proxy may return 500 if the
+ # end service is not ready, therefore this
+ # case should be tolerated.
+ response.raise_for_status()
+ except:
+ time.sleep(0.5)
+ if i == tries - 1:
+ return False
+ continue
+ break
+ return True
+
+
+
+ def fail(reason=None):
if reason:
- print("ERROR: " + reason)
- if proxy_proc:
- print(f"Proxy logs in: {proxy_proc.get_log_filename()}")
+ print("ERROR:", reason)
+ print(f"Logs in {LOG_DIR}")
exit(1)
def kill(proc):
@@ -810,7 +702,7 @@ def prepare():
FRONTENDS_API_TOKEN = "secret-token:secret"
TALER_MERCHANT_TOKEN = "secret-token:secret"
ALL_INSTANCES_BANK_PASSWORD = "secret"
- EXCHANGE_BANK_ACCOUNT_SANDBOX = "exchange-account-sandbox"
+ EXCHANGE_BANK_ACCOUNT_SANDBOX = "sandbox-account-exchange"
EXCHANGE_BANK_ACCOUNT_PASSWORD = "secret"
# EBICS
@@ -841,28 +733,6 @@ def prepare():
self.log_dir = log_dir
self.env = env
- @staticmethod
- def is_serving(check_url, tries=10):
- for i in range(tries):
- try:
- print_nn(".")
- # Raises if the service is not reachable.
- response = requests.get(
- check_url,
- timeout=1
- )
- # The reverse proxy may return 500 if the
- # end service is not ready, therefore this
- # case should be tolerated.
- response.raise_for_status()
- except:
- time.sleep(0.5)
- if i == tries - 1:
- return False
- continue
- break
- return True
-
def run(self):
self.do()
return_code = self.handle.wait()
@@ -872,15 +742,6 @@ def prepare():
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
@@ -907,7 +768,6 @@ def prepare():
)
except Exception as error:
fail(f"Could not execute: {' '.join(self.cmd)}: {error}")
- atexit.register(self.stop)
class ConfigFile:
def __init__(self, filename):
@@ -1090,7 +950,7 @@ def prepare():
obj.cfg_put("exchange-account-1", "enable_debit", "yes")
obj.cfg_put("exchange-account-1", "enable_credit", "yes")
obj.cfg_put("merchant-account-merchant", "payto_uri",
- f"payto://{wire_method}/{rev_proxy_url + '/bank'}/{merchant_wire_address}"
+ f"payto://{wire_method}/{rev_proxy_url + '/sandbox'}/{merchant_wire_address}"
)
obj.cfg_put("merchant-account-merchant",
"wire_response",
@@ -1141,9 +1001,24 @@ def prepare():
obj.cfg_put("authorization-question", "cost", f"{currency}:0")
obj.cfg_put("authorization-question", "enabled", "yes")
obj.cfg_write(outdir)
+
+ def unit_file_content(description, cmd, env=None):
+ executable_name = cmd.split(" ")[0].split("/")[-1]
+ content = (
+ "[Unit]\n"
+ f"Description={description}\n"
+ "[Service]\n"
+ f"ExecStart={cmd}\n"
+ f"StandardOutput=append:{LOG_DIR / executable_name}.log\n"
+ f"StandardError=append:{LOG_DIR / executable_name}.log"
+ )
+ if env:
+ content += f"\nEnvironmentFile={env}"
+ return content
+
print_nn("Ensure no service is running...")
- if Command.is_serving(REV_PROXY_URL + "/", tries=3):
+ if is_serving(REV_PROXY_URL + "/", tries=3):
fail("Reverse proxy is unexpectedly running!")
if UNIX_SOCKETS_DIR.is_dir():
for left_socket in os.listdir(UNIX_SOCKETS_DIR):
@@ -1177,6 +1052,128 @@ def prepare():
taler_runtime_dir=TALER_RUNTIME_DIR
)
print(" OK")
+
+ print_nn("Installing SystemD unit files...")
+ if not systemd_user_dir.exists():
+ systemd_user_dir.mkdir(parents=True, exist_ok=True)
+
+ if not TALER_UNIT_FILES_DIR.exists():
+ TALER_UNIT_FILES_DIR.mkdir(parents=True, exist_ok=True)
+
+ # Exchange HTTPD unit file.
+ with open(TALER_UNIT_FILES_DIR / "taler-local-exchange-httpd.service", "w") as exchange_unit:
+ exchange_unit.write(unit_file_content(
+ description = "Taler Exchange HTTP daemon",
+ cmd = f"{TALER_PREFIX}/bin/taler-exchange-httpd -L DEBUG -c {CFG_OUTDIR / 'taler.conf'}",
+ env = TALER_UNIT_FILES_DIR / "taler-local-postgres.env" if os.environ.get("PGPORT") else None
+ ))
+ with open(TALER_UNIT_FILES_DIR / "taler-local-exchange-wirewatch.service", "w") as exchange_wirewatch_unit:
+ exchange_wirewatch_unit.write(unit_file_content(
+ description = "Taler Exchange Wirewatch",
+ cmd = f"{TALER_PREFIX}/bin/taler-exchange-wirewatch -L DEBUG -c {CFG_OUTDIR / 'taler.conf'}",
+ env = TALER_UNIT_FILES_DIR / "taler-local-postgres.env" if os.environ.get("PGPORT") else None
+ ))
+ with open(TALER_UNIT_FILES_DIR / "taler-local-exchange-aggregator.service", "w") as exchange_aggregator_unit:
+ exchange_aggregator_unit.write(unit_file_content(
+ description = "Taler Exchange Aggregator",
+ cmd = f"{TALER_PREFIX}/bin/taler-exchange-aggregator -L DEBUG -c {CFG_OUTDIR / 'taler.conf'}",
+ env = TALER_UNIT_FILES_DIR / "taler-local-postgres.env" if os.environ.get("PGPORT") else None
+ ))
+ with open(TALER_UNIT_FILES_DIR / "taler-local-exchange-secmod-rsa.service", "w") as exchange_rsa_unit:
+ exchange_rsa_unit.write(unit_file_content(
+ description = "Taler Exchange RSA security module",
+ cmd = f"{TALER_PREFIX}/bin/taler-exchange-secmod-rsa -L DEBUG -c {CFG_OUTDIR / 'taler.conf'}"
+ ))
+ with open(TALER_UNIT_FILES_DIR / "taler-local-exchange-secmod-eddsa.service", "w") as exchange_eddsa_unit:
+ exchange_eddsa_unit.write(unit_file_content(
+ description = "Taler Exchange EDDSA security module",
+ cmd = f"{TALER_PREFIX}/bin/taler-exchange-secmod-eddsa -L DEBUG -c {CFG_OUTDIR / 'taler.conf'}"
+ ))
+ with open(TALER_UNIT_FILES_DIR / "taler-local-merchant-backend.service", "w") as merchant_unit:
+ merchant_unit.write(unit_file_content(
+ description = "Taler Merchant backend",
+ cmd = f"{TALER_PREFIX}/bin/taler-merchant-httpd -L DEBUG -c {CFG_OUTDIR / 'taler.conf'}",
+ env = TALER_UNIT_FILES_DIR / "taler-local-postgres.env" if os.environ.get("PGPORT") else None
+ ))
+ with open(TALER_UNIT_FILES_DIR / "taler-local-merchant-backend-token.service", "w") as merchant_token_unit:
+ merchant_token_unit.write(unit_file_content(
+ description = "Taler Merchant backend with auth token to allow default instance creation.",
+ cmd = f"{TALER_PREFIX}/bin/taler-merchant-httpd -a {TALER_MERCHANT_TOKEN} -L DEBUG -c {CFG_OUTDIR / 'taler.conf'}",
+ env = TALER_UNIT_FILES_DIR / "taler-local-postgres.env" if os.environ.get("PGPORT") else None
+ ))
+ # Custom Postgres connection.
+ if os.environ.get("PGPORT"):
+ with open(TALER_UNIT_FILES_DIR / "taler-local-postgres.env", "w") as postgres_env:
+ postgres_env.write(f"PGPORT={os.environ.get('PGPORT')}")
+
+ # euFin unit files.
+ with open(TALER_UNIT_FILES_DIR / "taler-local-sandbox.service", "w") as sandbox_unit:
+ sandbox_unit.write(unit_file_content(
+ description = "euFin Sandbox",
+ cmd = f"{TALER_PREFIX}/bin/libeufin-sandbox serve --with-unix-socket {UNIX_SOCKETS_DIR / 'sandbox.sock'}",
+ env = TALER_UNIT_FILES_DIR / "taler-local-sandbox.env"
+ ))
+ with open(TALER_UNIT_FILES_DIR / "taler-local-nexus.service", "w") as nexus_unit:
+ nexus_unit.write(unit_file_content(
+ description = "euFin Nexus",
+ cmd = f"{TALER_PREFIX}/bin/libeufin-nexus serve --with-unix-socket {UNIX_SOCKETS_DIR / 'nexus.sock'}",
+ env = TALER_UNIT_FILES_DIR / "taler-local-nexus.env"
+ ))
+ # euFin env files.
+ with open(TALER_UNIT_FILES_DIR / "taler-local-sandbox.env", "w") as sandbox_env:
+ sandbox_env.write(f"LIBEUFIN_SANDBOX_DB_CONNECTION=jdbc:sqlite:{SANDBOX_DB_FILE}\n")
+ sandbox_env.write(f"LIBEUFIN_SANDBOX_ADMIN_PASSWORD={SANDBOX_ADMIN_PASSWORD}")
+ with open(TALER_UNIT_FILES_DIR / "taler-local-nexus.env", "w") as nexus_env:
+ nexus_env.write(f"LIBEUFIN_NEXUS_DB_CONNECTION=jdbc:sqlite:{NEXUS_DB_FILE}\n")
+
+ with open(TALER_UNIT_FILES_DIR / "taler-local-donations.service", "w") as donations_unit:
+ donations_unit.write(unit_file_content(
+ description = "Donation Website that accepts Taler payments.",
+ cmd = f"{TALER_PREFIX}/bin/taler-merchant-demos donations -c {CFG_OUTDIR / 'taler.conf'}",
+ env = TALER_UNIT_FILES_DIR / "taler-frontends-local.env"
+ ))
+ with open(TALER_UNIT_FILES_DIR / "taler-local-blog.service", "w") as blog_unit:
+ blog_unit.write(unit_file_content(
+ description = "Blog that accepts Taler payments.",
+ cmd = f"{TALER_PREFIX}/bin/taler-merchant-demos blog -c {CFG_OUTDIR / 'taler.conf'}",
+ env = TALER_UNIT_FILES_DIR / "taler-frontends-local.env"
+ ))
+ with open(TALER_UNIT_FILES_DIR / "taler-local-survey.service", "w") as survey_unit:
+ survey_unit.write(unit_file_content(
+ description = "Survey Website awarding tips via Taler.",
+ cmd = f"{TALER_PREFIX}/bin/taler-merchant-demos survey -c {CFG_OUTDIR / 'taler.conf'}",
+ env = TALER_UNIT_FILES_DIR / "taler-frontends-local.env"
+ ))
+ with open(TALER_UNIT_FILES_DIR / "taler-local-landing.service", "w") as landing_unit:
+ landing_unit.write(unit_file_content(
+ description = "Landing Website of Taler demo.",
+ cmd = f"{TALER_PREFIX}/bin/taler-merchant-demos landing -c {CFG_OUTDIR / 'taler.conf'}",
+ env = TALER_UNIT_FILES_DIR / "taler-frontends-local.env"
+ ))
+ with open(TALER_UNIT_FILES_DIR / "taler-local-frontends.env", "w") as frontends_env:
+ frontends_env.write((
+ f"PATH={os.environ.get('PATH')}\n"
+ f"TALER_CONFIG_FILE={CFG_OUTDIR / 'taler.conf'}\n"
+ f"TALER_ENV_URL_INTRO={REV_PROXY_URL + '/landing/'}\n"
+ f"TALER_ENV_URL_BANK={SANDBOX_URL + '/'}\n"
+ f"TALER_ENV_URL_MERCHANT_BLOG={REV_PROXY_URL + '/blog/'}\n"
+ f"TALER_ENV_URL_MERCHANT_DONATIONS={REV_PROXY_URL + '/donations/'}\n"
+ f"TALER_ENV_URL_MERCHANT_SURVEY={REV_PROXY_URL + '/survey/'}\n"
+ ))
+ with open(TALER_UNIT_FILES_DIR / "taler-local-nginx.service", "w") as nginx_unit:
+ nginx_unit.write(unit_file_content(
+ description = "Nginx: reverse proxy for taler-local.",
+ cmd = f"nginx -c {CFG_OUTDIR / 'nginx.conf'}",
+ ))
+ print(" OK")
+ print_nn("Reload SystemD...")
+ Command(["systemctl", "--user", "daemon-reload"]).run()
+ atexit.register(lambda: subprocess.run(
+ ["systemctl", "--user", "stop", "taler-local-*.service"],
+ check=True
+ )
+ )
+ print(" OK")
print_nn("Generate exchange's master key...")
EXCHANGE_MASTER_PUB = Command(
[
@@ -1221,42 +1218,46 @@ def prepare():
"--reset"]
).run()
print(" OK")
+
print_nn("Launching the reverse proxy...")
- rev_proxy = TalerReverseProxy(
- LOG_DIR,
- UNIX_SOCKETS_DIR,
- REV_PROXY_PROTO,
- REV_PROXY_NETLOC
- )
- rev_proxy.start()
- if not Command.is_serving(REV_PROXY_URL + "/"):
- fail(f"Reverse proxy did not start correctly. \
-Logs: {rev_proxy.get_log_filename()}"
- )
+ with open(CFG_OUTDIR / "nginx.conf", "w") as nginx_conf:
+ nginx_conf.write((
+ f"error_log {LOG_DIR / 'nginx.log'};\n"
+ f"pid {TALER_ROOT_DIR / 'nginx.pid'};\n"
+ "daemon off;\n"
+ "events {}\n"
+ "http {\n"
+ f"access_log {LOG_DIR / 'nginx.log'};\n"
+ "server {\n"
+ f"listen {REV_PROXY_PORT};\n"
+ "location / {\n"
+ "return 200 'Hello, I am Nginx - proxying taler-local';\n"
+ "}\n"
+ "location ~* ^/(?<component>[a-z\-]+)(/(?<taler_uri>.*))? {\n"
+ "proxy_pass http://unix:/home/job/.taler/sockets/$component.sock:/$taler_uri?$args;\n"
+ "proxy_redirect off;\n"
+ "proxy_set_header X-Forwarded-Prefix /$component;\n"
+ f"proxy_set_header X-Forwarded-Host {REV_PROXY_NETLOC};\n"
+ f"proxy_set_header X-Forwarded-Proto {REV_PROXY_PROTO};\n"
+ "}\n"
+ "}\n"
+ "}\n"
+ ))
+ subprocess.run(["systemctl", "--user", "start", "taler-local-nginx.service"], check=True)
+ if not is_serving(REV_PROXY_URL + "/"):
+ fail(f"Reverse proxy did not start correctly")
# Do check.
print(" OK")
print_nn("Launching the exchange RSA helper...")
- exchange_rsa_handle = Command([
- "taler-exchange-secmod-rsa",
- "-c", CFG_OUTDIR / "taler.conf"
- ]).launch()
+ subprocess.run(["systemctl", "--user", "start", "taler-local-exchange-secmod-rsa.service"])
print(" OK")
print_nn("Launching the exchange EDDSA helper...")
- exchange_eddsa_handle = Command([
- "taler-exchange-secmod-eddsa",
- "-c", CFG_OUTDIR / "taler.conf"
- ]).launch()
+ subprocess.run(["systemctl", "--user", "start", "taler-local-exchange-secmod-eddsa.service"])
print(" OK")
print_nn("Launching the exchange...")
- exchange_handle = Command([
- "taler-exchange-httpd",
- "-c", CFG_OUTDIR / "taler.conf"
- ]).launch()
- if not Command.is_serving(REV_PROXY_URL + "/exchange/"):
- fail(
- f"Exchange did not start correctly. Logs: {exchange_handle.get_log_filename()}",
- rev_proxy
- )
+ subprocess.run(["systemctl", "--user", "start", "taler-local-exchange-httpd.service"])
+ if not is_serving(REV_PROXY_URL + "/exchange/"):
+ fail(f"Exchange did not start correctly.")
print(" OK")
print_nn("exchange-offline: signing key material...")
Command([
@@ -1313,22 +1314,9 @@ Logs: {rev_proxy.get_log_filename()}"
# This step transparantly creates a default demobank.
print_nn("Launching Sandbox...")
- sandbox_handle = Command(
- [
- "libeufin-sandbox", "serve",
- "--with-unix-socket", UNIX_SOCKETS_DIR / "sandbox.sock",
- ],
- env=get_sandbox_server_env(
- SANDBOX_DB_FILE,
- SANDBOX_URL,
- SANDBOX_ADMIN_PASSWORD
- )
- ).launch()
- if not Command.is_serving(SANDBOX_URL):
- fail(
- f"Sandbox did not start correctly. Logs: {sandbox_handle.get_log_filename()}",
- rev_proxy
- )
+ subprocess.run(["systemctl", "--user", "start", "taler-local-sandbox.service"])
+ if not is_serving(SANDBOX_URL):
+ fail(f"Sandbox did not start correctly.")
print(" OK")
print_nn("Make Sandbox EBICS host...")
Command(
@@ -1365,24 +1353,20 @@ Logs: {rev_proxy.get_log_filename()}"
)
EXCHANGE_PAYTO = exchange_bank_account_info["paytoUri"]
print(" OK")
- print_nn("Specify own payto-URI to exchange's configuration.")
+ print_nn("Specify own payto-URI to exchange's configuration..")
Command([
- "taler-config", "-s", "exchange-account-1",
- "-o", "payto_uri", "-V", EXCHANGE_PAYTO
+ "taler-config", "-c", CFG_OUTDIR / 'taler.conf',
+ "-s", "exchange-account-1", "-o", "payto_uri", "-V",
+ EXCHANGE_PAYTO
]).run()
print(" OK")
print_nn(f"exchange-offline: enabling {EXCHANGE_PAYTO}...")
Command([
"taler-exchange-offline",
"-c", CFG_OUTDIR / "taler.conf",
- "enable-account", EXCHANGE_PAYTO, "upload"]
- ).run()
+ "enable-account", EXCHANGE_PAYTO, "upload"
+ ]).run()
print(" OK")
- print_nn("Stopping exchange HTTP daemon and crypto helpers...")
- exchange_rsa_handle.stop()
- exchange_eddsa_handle.stop()
- exchange_handle.stop()
- print(" OK")
# Give each instance a Sandbox account (note: 'default')
# won't have one, as it should typically only manage other
@@ -1426,18 +1410,9 @@ Logs: {rev_proxy.get_log_filename()}"
print(" OK")
print_nn("Launching Nexus...")
- nexus_handle = Command(
- [
- "libeufin-nexus", "serve",
- "--with-unix-socket", UNIX_SOCKETS_DIR / "nexus.sock"
- ],
- env=get_nexus_server_env(NEXUS_DB_FILE, NEXUS_URL)
- ).launch()
- if not Command.is_serving(NEXUS_URL):
- fail(
- f"Nexus did not start correctly. Logs: {nexus_handle.get_log_filename()}",
- rev_proxy
- )
+ subprocess.run(["systemctl", "--user", "start", "taler-local-nexus.service"])
+ if not is_serving(NEXUS_URL):
+ fail(f"Nexus did not start correctly")
print(" OK")
print_nn("Create Exchange account at Nexus...")
@@ -1485,12 +1460,9 @@ Logs: {rev_proxy.get_log_filename()}"
)
response.raise_for_status()
except Exception as error:
- fail(error, rev_proxy)
+ fail(error)
FACADE_URL=response.json().get("facades")[0].get("baseUrl")
- print_nn("Terminating Nexus...")
- nexus_handle.stop()
- print(" OK")
print_nn("Set suggested exchange at Sandbox...")
Command([
"libeufin-sandbox",
@@ -1599,21 +1571,14 @@ Logs: {rev_proxy.get_log_filename()}"
headers = auth_header
)
if resp.status_code < 200 or resp.status_code >= 300:
- print(f"Could not create (or patch) instance '{instance_id}'")
print(f"Backend responds: {resp.status_code}/{resp.text}")
- fail(proxy_proc=rev_proxy)
+ fail(f"Could not create (or patch) instance '{instance_id}'")
print_nn(f"Start merchant (with TALER_MERCHANT_TOKEN into the env)...")
- auth_env = os.environ.copy()
- auth_env["TALER_MERCHANT_TOKEN"] = TALER_MERCHANT_TOKEN
- merchant_handle = Command(
- ["taler-merchant-httpd", "-c", CFG_OUTDIR / "taler.conf"],
- env=auth_env
- ).launch()
- if not Command.is_serving(REV_PROXY_URL + "/merchant-backend/config"):
+ subprocess.run(["systemctl", "--user", "start", "taler-local-merchant-backend-token.service"], check=True)
+ if not is_serving(REV_PROXY_URL + "/merchant-backend/config"):
fail(
- f"Merchant backend did not start correctly. Logs: {merchant_handle.get_log_filename()}",
- rev_proxy
+ f"Merchant backend did not start correctly.",
)
print(" OK")
print_nn("Give default instance a bank account...")
@@ -1636,18 +1601,12 @@ Logs: {rev_proxy.get_log_filename()}"
merchant_wire_address = IBAN_MERCHANT_DEFAULT,
auth_token=FRONTENDS_API_TOKEN
)
- print_nn("Stopping the merchant...")
- merchant_handle.stop()
- print(" OK")
print_nn("Restarting the merchant WITHOUT the auth-token in the env...")
- merchant_handle.launch()
- if not Command.is_serving(REV_PROXY_URL + "/merchant-backend/config"):
+ subprocess.run(["systemctl", "--user", "start", "taler-local-merchant-backend.service"], check=True)
+ if not is_serving(REV_PROXY_URL + "/merchant-backend/config"):
# check_running logs errors already.
- fail(
- f"Merchant backend did not re start correctly. Logs: {merchant_handle.get_log_filename()}",
- rev_proxy
- )
+ fail(f"Merchant backend did not re start correctly.")
print(" OK")
for instance_id, iban in INSTANCES.items():
@@ -1662,174 +1621,25 @@ Logs: {rev_proxy.get_log_filename()}"
auth_token=FRONTENDS_API_TOKEN
)
print(" OK")
- print_nn("Terminating Sandbox...")
- sandbox_handle.stop()
- print(" OK")
- print_nn("Stopping the merchant backend...")
- merchant_handle.stop()
- print(" OK")
- print_nn("Stopping the reverse proxy...")
- rev_proxy.stop()
- print(" OK")
-
- print_nn("Installing SystemD unit files...")
-
- if not systemd_user_dir.exists():
- systemd_user_dir.mkdir(parents=True, exist_ok=True)
-
- if not TALER_UNIT_FILES_DIR.exists():
- TALER_UNIT_FILES_DIR.mkdir(parents=True, exist_ok=True)
-
- def unit_file_content(description, cmd, env=None):
- executable_name = cmd.split(" ")[0].split("/")[-1]
- content = (
- "[Unit]\n"
- f"Description={description}\n"
- "[Service]\n"
- f"ExecStart={cmd}\n"
- f"StandardOutput=append:{LOG_DIR / executable_name}.log\n"
- f"StandardError=append:{LOG_DIR / executable_name}.log"
- )
- if env:
- content += f"\nEnvironmentFile={env}"
- return content
-
- # Exchange HTTPD unit file.
- with open(TALER_UNIT_FILES_DIR / "taler-exchange-httpd-local.service", "w") as exchange_unit:
- exchange_unit.write(unit_file_content(
- description = "Taler Exchange HTTP daemon",
- cmd = f"{TALER_PREFIX}/bin/taler-exchange-httpd -L DEBUG -c {CFG_OUTDIR / 'taler.conf'}",
- env = TALER_UNIT_FILES_DIR / "taler-postgres-local.env" if os.environ.get("PGPORT") else None
- ))
- with open(TALER_UNIT_FILES_DIR / "taler-exchange-wirewatch-local.service", "w") as exchange_wirewatch_unit:
- exchange_wirewatch_unit.write(unit_file_content(
- description = "Taler Exchange Wirewatch",
- cmd = f"{TALER_PREFIX}/bin/taler-exchange-wirewatch -L DEBUG -c {CFG_OUTDIR / 'taler.conf'}",
- env = TALER_UNIT_FILES_DIR / "taler-postgres-local.env" if os.environ.get("PGPORT") else None
- ))
- with open(TALER_UNIT_FILES_DIR / "taler-exchange-secmod-rsa-local.service", "w") as exchange_rsa_unit:
- exchange_rsa_unit.write(unit_file_content(
- description = "Taler Exchange RSA security module",
- cmd = f"{TALER_PREFIX}/bin/taler-exchange-secmod-rsa -L DEBUG -c {CFG_OUTDIR / 'taler.conf'}"
- ))
- with open(TALER_UNIT_FILES_DIR / "taler-exchange-secmod-eddsa-local.service", "w") as exchange_eddsa_unit:
- exchange_eddsa_unit.write(unit_file_content(
- description = "Taler Exchange EDDSA security module",
- cmd = f"{TALER_PREFIX}/bin/taler-exchange-secmod-eddsa -L DEBUG -c {CFG_OUTDIR / 'taler.conf'}"
- ))
- with open(TALER_UNIT_FILES_DIR / "taler-merchant-httpd-local.service", "w") as merchant_unit:
- merchant_unit.write(unit_file_content(
- description = "Taler Merchant backend",
- cmd = f"{TALER_PREFIX}/bin/taler-merchant-httpd -L DEBUG -c {CFG_OUTDIR / 'taler.conf'}",
- env = TALER_UNIT_FILES_DIR / "taler-postgres-local.env" if os.environ.get("PGPORT") else None
- ))
- # Custom Postgres connection.
- if os.environ.get("PGPORT"):
- with open(TALER_UNIT_FILES_DIR / "taler-postgres-local.env", "w") as postgres_env:
- postgres_env.write(f"PGPORT={os.environ.get('PGPORT')}")
-
- # euFin unit files.
- with open(TALER_UNIT_FILES_DIR / "libeufin-sandbox-local.service", "w") as sandbox_unit:
- sandbox_unit.write(unit_file_content(
- description = "euFin Sandbox",
- cmd = f"{TALER_PREFIX}/bin/libeufin-sandbox serve --with-unix-socket {UNIX_SOCKETS_DIR / 'sandbox.sock'}",
- env = TALER_UNIT_FILES_DIR / "libeufin-sandbox-local.env"
- ))
- with open(TALER_UNIT_FILES_DIR / "libeufin-nexus-local.service", "w") as nexus_unit:
- nexus_unit.write(unit_file_content(
- description = "euFin Nexus",
- cmd = f"{TALER_PREFIX}/bin/libeufin-nexus serve --with-unix-socket {UNIX_SOCKETS_DIR / 'nexus.sock'}",
- env = TALER_UNIT_FILES_DIR / "libeufin-nexus-local.env"
- ))
- # euFin env files.
- with open(TALER_UNIT_FILES_DIR / "libeufin-sandbox-local.env", "w") as sandbox_env:
- sandbox_env.write(f"LIBEUFIN_SANDBOX_DB_CONNECTION=jdbc:sqlite:{SANDBOX_DB_FILE}\n")
- sandbox_env.write(f"LIBEUFIN_SANDBOX_ADMIN_PASSWORD={SANDBOX_ADMIN_PASSWORD}")
- with open(TALER_UNIT_FILES_DIR / "libeufin-nexus-local.env", "w") as nexus_env:
- nexus_env.write(f"LIBEUFIN_NEXUS_DB_CONNECTION=jdbc:sqlite:{NEXUS_DB_FILE}\n")
-
- with open(TALER_UNIT_FILES_DIR / "taler-donations-local.service", "w") as donations_unit:
- donations_unit.write(unit_file_content(
- description = "Donation Website that accepts Taler payments.",
- cmd = f"{TALER_PREFIX}/bin/taler-merchant-demos donations -c {CFG_OUTDIR / 'taler.conf'}",
- env = TALER_UNIT_FILES_DIR / "taler-frontends-local.env"
- ))
- with open(TALER_UNIT_FILES_DIR / "taler-blog-local.service", "w") as blog_unit:
- blog_unit.write(unit_file_content(
- description = "Blog that accepts Taler payments.",
- cmd = f"{TALER_PREFIX}/bin/taler-merchant-demos blog -c {CFG_OUTDIR / 'taler.conf'}",
- env = TALER_UNIT_FILES_DIR / "taler-frontends-local.env"
- ))
- with open(TALER_UNIT_FILES_DIR / "taler-survey-local.service", "w") as survey_unit:
- survey_unit.write(unit_file_content(
- description = "Survey Website awarding tips via Taler.",
- cmd = f"{TALER_PREFIX}/bin/taler-merchant-demos survey -c {CFG_OUTDIR / 'taler.conf'}",
- env = TALER_UNIT_FILES_DIR / "taler-frontends-local.env"
- ))
- with open(TALER_UNIT_FILES_DIR / "taler-landing-local.service", "w") as landing_unit:
- landing_unit.write(unit_file_content(
- description = "Landing Website of Taler demo.",
- cmd = f"{TALER_PREFIX}/bin/taler-merchant-demos landing -c {CFG_OUTDIR / 'taler.conf'}",
- env = TALER_UNIT_FILES_DIR / "taler-frontends-local.env"
- ))
- with open(TALER_UNIT_FILES_DIR / "taler-frontends-local.env", "w") as frontends_env:
- frontends_env.write((
- f"PATH={os.environ.get('PATH')}\n"
- f"TALER_CONFIG_FILE={CFG_OUTDIR / 'taler.conf'}\n"
- f"TALER_ENV_URL_INTRO={REV_PROXY_URL + '/landing/'}\n"
- f"TALER_ENV_URL_BANK={SANDBOX_URL + '/'}\n"
- f"TALER_ENV_URL_MERCHANT_BLOG={REV_PROXY_URL + '/blog/'}\n"
- f"TALER_ENV_URL_MERCHANT_DONATIONS={REV_PROXY_URL + '/donations/'}\n"
- f"TALER_ENV_URL_MERCHANT_SURVEY={REV_PROXY_URL + '/survey/'}\n"
- ))
- print(" OK")
-
- # more units here..
- print_nn("Reload SystemD...")
- Command(["systemctl", "--user", "daemon-reload"]).run()
- print(" OK")
@cli.command()
def launch():
+ subprocess.run(["systemctl", "--user", "start", "taler-local-nginx.service"], check=True)
+ subprocess.run(["systemctl", "--user", "start", "taler-local-exchange-secmod-rsa.service"], check=True)
+ subprocess.run(["systemctl", "--user", "start", "taler-local-exchange-secmod-eddsa.service"], check=True)
+ subprocess.run(["systemctl", "--user", "start", "taler-local-exchange-httpd.service"], check=True)
+ subprocess.run(["systemctl", "--user", "start", "taler-local-exchange-wirewatch.service"], check=True)
+ subprocess.run(["systemctl", "--user", "start", "taler-local-exchange-aggregator.service"], check=True)
+ subprocess.run(["systemctl", "--user", "start", "taler-local-merchant-backend.service"], check=True)
+ subprocess.run(["systemctl", "--user", "start", "taler-local-sandbox.service"], check=True)
+ subprocess.run(["systemctl", "--user", "start", "taler-local-nexus.service"], check=True)
+ subprocess.run(["systemctl", "--user", "start", "taler-local-donations.service"], check=True)
+ subprocess.run(["systemctl", "--user", "start", "taler-local-blog.service"], check=True)
+ subprocess.run(["systemctl", "--user", "start", "taler-local-survey.service"], check=True)
- subprocess.run(["systemctl", "--user", "start", "taler-exchange-httpd-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "start", "taler-exchange-wirewatch-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "start", "taler-exchange-secmod-rsa-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "start", "taler-exchange-secmod-eddsa-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "start", "taler-merchant-httpd-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "start", "libeufin-nexus-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "start", "libeufin-sandbox-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "start", "taler-donations-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "start", "taler-blog-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "start", "taler-survey-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "start", "taler-landing-local.service"], check=True)
-
- rev_proxy = TalerReverseProxy(
- LOG_DIR,
- UNIX_SOCKETS_DIR,
- REV_PROXY_PROTO,
- REV_PROXY_NETLOC
- )
- netloc_parts = REV_PROXY_NETLOC.split(":")
- rev_proxy.run(
- host=netloc_parts[0],
- port=netloc_parts[1],
- debug=False
- )
- # Stop with CTRL+C
- print_nn("Stopping the services...")
- subprocess.run(["systemctl", "--user", "stop", "taler-landing-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "stop", "taler-survey-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "stop", "taler-blog-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "stop", "taler-donations-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "stop", "libeufin-sandbox-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "stop", "libeufin-nexus-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "stop", "taler-merchant-httpd-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "stop", "taler-exchange-secmod-eddsa-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "stop", "taler-exchange-secmod-rsa-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "stop", "taler-exchange-wirewatch-local.service"], check=True)
- subprocess.run(["systemctl", "--user", "stop", "taler-exchange-httpd-local.service"], check=True)
- print(" OK")
+@cli.command()
+def stop():
+ subprocess.run(["systemctl", "--user", "stop", "taler-local-*.service"], check=True)
@cli.command()
def withdraw():