summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorms <ms@taler.net>2021-09-23 16:30:59 +0200
committerms <ms@taler.net>2021-09-23 16:30:59 +0200
commite5b76632437824c77cbc881f23b2e6bb350e25d6 (patch)
treedf0bff1e85f3f6e5d49dc3ed98e1f1c9ea7492a6
parentef468a70e8d0e94391172188623fb0cb83ac1384 (diff)
downloaddeployment-e5b76632437824c77cbc881f23b2e6bb350e25d6.tar.gz
deployment-e5b76632437824c77cbc881f23b2e6bb350e25d6.tar.bz2
deployment-e5b76632437824c77cbc881f23b2e6bb350e25d6.zip
Developer utilities. Work in progress
Drafting programs that will help building / configuring / launching a whole Taler setup on the developer's machine without having to configure Nginx, versioning private keys, sourcing environment scripts, and generally trying to minimize the amount of configuration values to provide.
-rwxr-xr-xbin/WIP/taler-config-local244
-rwxr-xr-xbin/WIP/taler-local380
-rwxr-xr-xbin/WIP/taler-prepare-local285
3 files changed, 909 insertions, 0 deletions
diff --git a/bin/WIP/taler-config-local b/bin/WIP/taler-config-local
new file mode 100755
index 0000000..38144e4
--- /dev/null
+++ b/bin/WIP/taler-config-local
@@ -0,0 +1,244 @@
+#!/usr/bin/env python3
+import click
+import sys
+from collections import OrderedDict
+import json
+import os
+import urllib.parse
+import stat
+from taler_urls import get_urls, get_port
+
+
+class ConfigFile:
+ def __init__(self, filename):
+ self.sections = OrderedDict()
+ self.filename = filename
+
+ def destroy(self):
+ del self.sections
+ self.sections = OrderedDict()
+
+ def cfg_put(self, section_name, key, value):
+ s = self.sections[section_name] = self.sections.get(section_name, OrderedDict())
+ s[key] = value
+
+ def cfg_write(self, outdir):
+
+ if outdir:
+ fstream = open(os.path.join(outdir, self.filename), "w")
+ else:
+ fstream = open(sys.stdout)
+
+ for section_name, section in self.sections.items():
+ fstream.write("[" + section_name + "]" + "\n")
+ for key, value in section.items():
+ fstream.write(key + " = " + value + "\n")
+ fstream.write("\n")
+ fstream.close()
+
+def coin(
+ obj,
+ currency,
+ name,
+ value,
+ d_withdraw="3 years",
+ d_spend="5 years",
+ d_legal="10 years",
+ f_withdraw="0.01",
+ f_deposit="0.01",
+ f_refresh="0.01",
+ f_refund="0.01",
+ rsa_keysize="2048",
+):
+ sec = "coin_" + currency + "_" + name
+ obj.cfg_put(sec, "value", currency + ":" + value)
+ obj.cfg_put(sec, "duration_withdraw", d_withdraw)
+ obj.cfg_put(sec, "duration_spend", d_spend)
+ obj.cfg_put(sec, "duration_legal", d_legal)
+ obj.cfg_put(sec, "fee_withdraw", currency + ":" + f_withdraw)
+ obj.cfg_put(sec, "fee_refresh", currency + ":" + f_refresh)
+ obj.cfg_put(sec, "fee_refund", currency + ":" + f_refund)
+ obj.cfg_put(sec, "fee_deposit", currency + ":" + f_deposit)
+ obj.cfg_put(sec, "rsa_keysize", rsa_keysize)
+
+
+def config(
+ obj,
+ rev_proxy_url,
+ wire_method,
+ currency,
+ exchange_wire_address,
+ merchant_wire_address,
+ exchange_wire_gateway_username,
+ exchange_wire_gateway_password,
+):
+ obj.cfg_put("paths", "TALER_DATA_HOME", "${HOME}/.taler-data")
+ obj.cfg_put("paths", "TALER_RUNTIME_DIR", "${HOME}/.taler-runtime")
+ obj.cfg_put("taler", "CURRENCY", obj.currency)
+ obj.cfg_put("taler", "CURRENCY_ROUND_UNIT", f"{currency}:0.01")
+ 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_mode", "660")
+ obj.cfg_put("bank", "database", "taler")
+ obj.cfg_put("bank", "max_debt", "%s:500.0" % obj.currency)
+ obj.cfg_put("bank", "max_debt_bank", "%s:1000000000.0" % obj.currency)
+ obj.cfg_put("bank", "allow_registrations", "YES")
+ obj.cfg_put("bank", "base_url", rev_proxy_url + "/bank/")
+ obj.cfg_put("bank", "database", "postgres:///taler")
+ obj.cfg_put("bank", "suggested_exchange", rev_proxy_url + "/exchange/")
+
+ 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_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_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_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_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", "wire_transfer_delay", "0 s")
+ obj.cfg_put("merchant", "default_max_wire_fee", obj.currency + ":" + "0.01")
+ obj.cfg_put("merchant", "default_max_deposit_fee", obj.currency + ":" + "0.05")
+ obj.cfg_put("merchantdb-postgres", "config", "postgres:///taler")
+
+ obj.cfg_put("frontends", "backend", rev_proxy_url + "/merchant-backend/")
+ obj.cfg_put(
+ "merchant-exchange-{}".format(currency),
+ "exchange_base_url", rev_proxy_url + "/exchange/",
+ )
+
+ 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", "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-rsa", "sm_priv_key",
+ "/tmp/taler-data/taler-exchange-secmod-rsa/secmod-private-key"
+ )
+ obj.cfg_put("exchange", "base_url", rev_proxy_url + "/exchange/")
+
+ obj.cfg_put("exchange", "serve", "unix")
+ obj.cfg_put("exchange", "unixpath", "/tmp/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")
+ obj.cfg_put("auditordb-postgres", "config", "postgres:///taler")
+
+ obj.cfg_put(
+ "exchange-account-1",
+ "payto_uri",
+ f"payto://{wire_method}/{rev_proxy_url + '/bank'}/{exchange_wire_address}"
+ )
+ 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}"
+ )
+ obj.cfg_put("merchant-account-merchant",
+ "wire_response",
+ "${TALER_DATA_HOME}/merchant/wire/merchant.json",
+ )
+ obj.cfg_put("merchant-account-merchant", "wire_file_mode", "770")
+
+ # The following block should be obsoleted by the new API to configure instances.
+ merchant_instance_names = ("default", "Tor", "GNUnet", "Taler", "FSF", "Tutorial")
+ for mi in merchant_instance_names:
+ obj.cfg_put("merchant-account-merchant", f"HONOR_{mi}", "YES")
+ obj.cfg_put("merchant-account-merchant", f"ACTIVE_{mi}", "YES")
+
+ coin(obj, currency, "ct_10", "0.10")
+ coin(obj, currency, "1", "1")
+ coin(obj, currency, "2", "2")
+ coin(obj, currency, "5", "5")
+ coin(obj, currency, "10", "10")
+ coin(obj, currency, "1000", "1000")
+
+@click.command()
+@click.option("--currency", required=True)
+@click.option("--outdir", required=True)
+@click.option("--exchange-pub", required=True)
+@click.option("--exchange-wire-address", required=True)
+@click.option("--merchant-wire-address", required=True)
+@click.option("--rev-proxy-url", required=True)
+# Expected to contain already the 'secret-token:' scheme.
+@click.option("--frontends-apitoken", required=True)
+def main(
+ currency,
+ outdir,
+ exchange_wire_address,
+ merchant_wire_address,
+ rev_proxy_url,
+ frontends_apitoken
+):
+
+ config_files = []
+
+ mc = ConfigFile("taler.conf")
+ mc.cfg_put("frontends", "backend_apikey", f"{frontends_apitoken}")
+ config(mc) # does 99%
+ config_files.append(mc)
+
+ sc = ConfigFile("sync.conf")
+ sc.cfg_put("taler", "currency", currency)
+ sc.cfg_put("sync", "serve", "unix")
+ sc.cfg_put("sync", "unixpath", "$HOME/sockets/sync.http")
+ sc.cfg_put("sync", "apikey", f"Bearer {frontends_apitoken}")
+ sc.cfg_put("sync", "annual_fee", f"{currency}:0.1")
+ sc.cfg_put("sync", "fulfillment_url", "taler://fulfillment-success/")
+ sc.cfg_put("sync", "payment_backend_url", rev_proxy_url + "merchant-backend/instances/Taler/")
+ sc.cfg_put("syncdb-postgres", "config", f"postgres:///taler")
+ config_files.append(sc)
+
+ ac = ConfigFile("anastasis.conf")
+ ac.cfg_put("taler", "currency", currency)
+ ac.cfg_put("anastasis", "serve", "unix")
+ ac.cfg_put("anastasis", "business_name", f"GNU Taler Demo Anastasis Provider")
+ ac.cfg_put("anastasis", "unixpath", "/tmp/anastasis.sock")
+ ac.cfg_put("anastasis", "annual_fee", f"{currency}:0")
+ ac.cfg_put("anastasis", "question_cost", f"{currency}:0")
+ ac.cfg_put("anastasis", "insurance", f"{currency}:0")
+ ac.cfg_put("anastasis", "truth_upload_fee", f"{currency}:0")
+ ac.cfg_put("anastasis", "fulfillment_url", "taler://fulfillment-success/")
+ ac.cfg_put("anastasis", "server_salt", "kreb3ia9dmj43gfa")
+ ac.cfg_put("stasis-postgres", "config", f"postgres:///taler")
+ ac.cfg_put("anastasis-merchant-backend",
+ "payment_backend_url",
+ rev_proxy_url "merchant-backend/instances/anastasis/"
+ )
+ ac.cfg_put("anastasis-merchant-backend", "api_key", f"Bearer {frontends_apitoken}")
+ ac.cfg_put("authorization-question", "cost", f"{currency}:0")
+ ac.cfg_put("authorization-question", "enabled", "yes")
+ config_files.append(ac)
+
+ assert 0 < len(config_files)
+ for obj in config_files:
+ obj.cfg_write(outdir)
+
+if __name__ == "__main__":
+ main()
diff --git a/bin/WIP/taler-local b/bin/WIP/taler-local
new file mode 100755
index 0000000..eb6589a
--- /dev/null
+++ b/bin/WIP/taler-local
@@ -0,0 +1,380 @@
+#!/usr/bin/env python3
+
+# This file is part of GNU Taler.
+#
+# GNU Taler is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GNU Taler is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 click
+import types
+import os
+import sys
+import os.path
+import subprocess
+import time
+import random
+from os import listdir
+from os.path import isdir, join
+from pathlib import Path
+from dataclasses import dataclass
+from typing import List, Callable
+from shutil import copy
+from taler_urls import get_urls
+from string import ascii_letters, ascii_uppercase
+
+@dataclass
+class Repo:
+ name: str
+ url: str
+ deps: List[str]
+ builder: Callable[["Repo", Path], None]
+
+@click.group()
+def cli():
+ pass
+
+def split_repos_list(repos):
+ return [repo for repo in repos.split(",") if repo != ""]
+
+def update_checkout(r: Repo, p: Path):
+ """Clean the repository's working directory and
+ update it to the match the latest version of the upstream branch
+ that we are tracking."""
+ subprocess.run(["git", "-C", str(p), "clean", "-fdx"], check=True)
+ subprocess.run(["git", "-C", str(p), "fetch"], check=True)
+ subprocess.run(["git", "-C", str(p), "reset"], check=True)
+ res = subprocess.run(
+ [
+ "git",
+ "-C",
+ str(p),
+ "rev-parse",
+ "--abbrev-ref",
+ "--symbolic-full-name",
+ "@{u}",
+ ],
+ stderr=subprocess.DEVNULL,
+ stdout=subprocess.PIPE,
+ encoding="utf-8",
+ )
+ if res.returncode != 0:
+ ref = "HEAD"
+ else:
+ ref = res.stdout.strip("\n ")
+ print(f"resetting {r.name} to ref {ref}")
+ subprocess.run(["git", "-C", str(p), "reset", "--hard", ref], check=True)
+
+
+def default_configure(*extra):
+ pfx = Path.home() / ".local"
+ extra_list = list(extra)
+ subprocess.run(["./configure", f"--prefix={pfx}"] + extra_list, check=True)
+
+def pyconfigure(*extra):
+ """For python programs, --prefix doesn't work."""
+ subprocess.run(["./configure"] + list(extra), check=True)
+
+def build_libeufin(r: Repo, p: Path):
+ update_checkout(r, p)
+ subprocess.run(["./bootstrap"], check=True)
+ default_configure()
+ subprocess.run(["make", "install"], check=True)
+ (p / "taler-buildstamp").touch()
+
+def build_libmicrohttpd(r: Repo, p: Path):
+ update_checkout(r, p)
+ subprocess.run(["./bootstrap"], check=True)
+ # Debian gnutls packages are too old ...
+ default_configure("--with-gnutls=/usr/local")
+ subprocess.run(["make"], check=True)
+ subprocess.run(["make", "install"], check=True)
+ (p / "taler-buildstamp").touch()
+
+def build_gnunet(r: Repo, p: Path):
+ update_checkout(r, p)
+ subprocess.run(["./bootstrap"], check=True)
+ pfx = Path.home() / ".local"
+ default_configure(
+ "--enable-logging=verbose",
+ f"--with-microhttpd={pfx}",
+ "--disable-documentation",
+ )
+ subprocess.run(["make", "install"], check=True)
+ (p / "taler-buildstamp").touch()
+
+def build_exchange(r: Repo, p: Path):
+ update_checkout(r, p)
+ subprocess.run(["./bootstrap"], check=True)
+ pfx = Path.home() / ".local"
+ default_configure(
+ "CFLAGS=-ggdb -O0",
+ "--enable-logging=verbose",
+ f"--with-microhttpd={pfx}",
+ f"--with-gnunet={pfx}",
+ )
+ subprocess.run(["make", "install"], check=True)
+ (p / "taler-buildstamp").touch()
+
+def build_wallet(r, p):
+ update_checkout(r, p)
+ subprocess.run(["./bootstrap"], check=True)
+ default_configure()
+ subprocess.run(["make", "install"], check=True)
+ (p / "taler-buildstamp").touch()
+
+def build_twister(r, p):
+ update_checkout(r, p)
+ subprocess.run(["./bootstrap"], check=True)
+ pfx = Path.home() / ".local"
+ default_configure(
+ "CFLAGS=-ggdb -O0",
+ "--enable-logging=verbose",
+ f"--with-exchange={pfx}",
+ f"--with-gnunet={pfx}",
+ )
+ subprocess.run(["make", "install"], check=True)
+ (p / "taler-buildstamp").touch()
+
+
+def build_merchant(r, p):
+ update_checkout(r, p)
+ subprocess.run(["./bootstrap"], check=True)
+ pfx = Path.home() / ".local"
+ default_configure(
+ "CFLAGS=-ggdb -O0",
+ "--enable-logging=verbose",
+ f"--with-microhttpd={pfx}",
+ f"--with-exchange={pfx}",
+ f"--with-gnunet={pfx}",
+ "--disable-doc",
+ )
+ subprocess.run(["make", "install"], check=True)
+ (p / "taler-buildstamp").touch()
+
+def build_sync(r, p):
+ update_checkout(r, p)
+ subprocess.run(["./bootstrap"], check=True)
+ pfx = Path.home() / ".local"
+ default_configure(
+ "CFLAGS=-ggdb -O0",
+ "--enable-logging=verbose",
+ f"--with-microhttpd={pfx}",
+ f"--with-exchange={pfx}",
+ f"--with-merchant={pfx}",
+ f"--with-gnunet={pfx}",
+ "--disable-doc",
+ )
+ subprocess.run(["make", "install"], check=True)
+ (p / "taler-buildstamp").touch()
+
+
+def build_anastasis(r, p):
+ update_checkout(r, p)
+ subprocess.run(["./bootstrap"], check=True)
+ pfx = Path.home() / ".local"
+ default_configure(
+ "CFLAGS=-ggdb -O0",
+ "--enable-logging=verbose",
+ f"--with-microhttpd={pfx}",
+ f"--with-exchange={pfx}",
+ f"--with-merchant={pfx}",
+ f"--with-gnunet={pfx}",
+ "--disable-doc",
+ )
+ subprocess.run(["make", "install"], check=True)
+ (p / "taler-buildstamp").touch()
+
+
+def build_demos(r, p):
+ update_checkout(r, p)
+ pfx = Path.home() / ".local"
+ pyconfigure()
+ subprocess.run(["make", "install"], check=True)
+ (p / "taler-buildstamp").touch()
+
+def build_backoffice(r, p):
+ update_checkout(r, p)
+ subprocess.run(["./bootstrap"])
+ subprocess.run(["./configure"])
+ subprocess.run(["make", "build-single"])
+ (p / "taler-buildstamp").touch()
+
+repos = {
+ "libmicrohttpd": Repo(
+ "libmicrohttpd",
+ "git://git.gnunet.org/libmicrohttpd.git",
+ [],
+ build_libmicrohttpd,
+ ),
+ "gnunet": Repo(
+ "gnunet",
+ "git://git.gnunet.org/gnunet.git",
+ ["libmicrohttpd"],
+ build_gnunet
+ ),
+ "exchange": Repo(
+ "exchange",
+ "git://git.taler.net/exchange",
+ ["gnunet", "libmicrohttpd"],
+ build_exchange,
+ ),
+ "merchant": Repo(
+ "merchant",
+ "git://git.taler.net/merchant",
+ ["exchange","libmicrohttpd","gnunet"],
+ build_merchant,
+ ),
+ "sync": Repo(
+ "sync",
+ "git://git.taler.net/sync",
+ ["exchange",
+ "merchant",
+ "gnunet",
+ "libmicrohttpd"],
+ build_sync,
+ ),
+ "anastasis": Repo(
+ "anastasis",
+ "git://git.taler.net/anastasis",
+ ["exchange",
+ "merchant",
+ "libmicrohttpd",
+ "gnunet"],
+ build_anastasis,
+ ),
+ "wallet-core": Repo(
+ "wallet-core",
+ "git://git.taler.net/wallet-core",
+ [],
+ build_wallet,
+ ),
+ "libeufin": Repo(
+ "libeufin",
+ "git://git.taler.net/libeufin.git",
+ [],
+ build_libeufin,
+ ),
+ "taler-merchant-demos": Repo(
+ "taler-merchant-demos",
+ "git://git.taler.net/taler-merchant-demos",
+ [],
+ build_demos,
+ ),
+ "twister": Repo(
+ "twister",
+ "git://git.taler.net/twister",
+ ["gnunet", "libmicrohttpd"],
+ build_twister,
+ ),
+}
+
+def get_repos_names() -> List[str]:
+ r_dir = Path.home() / ".taler-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.
+def load_repos(reposNames) -> List[Repo]:
+ return [repos.get(r) for r in reposNames if repos.get(r)]
+
+def update_repos(repos: List[Repo]) -> None:
+ for r in repos:
+ r_dir = Path.home() / ".taler-sources" / r.name
+ subprocess.run(["git", "-C", str(r_dir), "fetch"], check=True)
+ res = subprocess.run(
+ ["git", "-C", str(r_dir), "status", "-sb"],
+ check=True,
+ stdout=subprocess.PIPE,
+ encoding="utf-8",
+ )
+ if "behind" in res.stdout:
+ print(f"new commits in {r}")
+ s = r_dir / "taler-buildstamp"
+ if s.exists():
+ s.unlink()
+
+def get_stale_repos(repos: List[Repo]) -> List[Repo]:
+ timestamps = {}
+ stale = []
+ for r in repos:
+ r_dir = Path.home() / ".taler-sources" / r.name
+ s = r_dir / "taler-buildstamp"
+ if not s.exists():
+ timestamps[r.name] = time.time()
+ stale.append(r)
+ return stale
+
+@cli.command()
+@click.option(
+ "--without-repos", metavar="WITHOUT REPOS",
+ help="WITHOUT REPOS is a unspaced and comma-separated list \
+of the repositories to _exclude_ from compilation",
+ default="")
+def build(without_repos) -> None:
+ """Build the deployment from source."""
+ exclude = split_repos_list(without_repos)
+ # Get the repositories names from the source directory
+ repos_names = get_repos_names()
+ # Reorder the list of repositories so that the
+ # most fundamental dependecies appear left-most.
+ repos_keys = repos.keys() # Has the precedence rules.
+ sorted_repos = sorted(
+ set(repos_keys).intersection(repos_names),
+ key=lambda x: list(repos_keys).index(x)
+ )
+ target_repos = load_repos(sorted_repos) # Get Repo objects
+ update_repos(target_repos)
+ stale = get_stale_repos(target_repos)
+ print(f"found stale repos: {[r.name for r in stale]}")
+ for r in stale:
+ if r.name in exclude:
+ print(f"not building: {r.name}")
+ continue
+ # Warn, if a dependency is not being built:
+ 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
+ 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",
+ metavar="REPOS",
+ help="REPOS is a unspaced and comma-separated list of the repositories to clone.",
+ default="libmicrohttpd,gnunet,exchange,merchant,wallet-core,taler-merchant-demos,sync,anastasis,libeufin",
+ show_default=True,
+)
+def bootstrap(repos) -> None:
+
+ """Clone all the specified repositories."""
+
+ home = Path.home()
+ reposList = split_repos_list(repos)
+ checkout_repos(load_repos(reposList))
+
+if __name__ == "__main__":
+ cli()
diff --git a/bin/WIP/taler-prepare-local b/bin/WIP/taler-prepare-local
new file mode 100755
index 0000000..467fd56
--- /dev/null
+++ b/bin/WIP/taler-prepare-local
@@ -0,0 +1,285 @@
+#!/bin/bash
+
+# Values needed:
+#
+# currency
+
+set -eu
+
+# The script stops what started along the flow.
+# This function should help against processes left
+# somehow running.
+function stop_running() {
+ for n in `jobs -p`
+ do
+ kill $n 2> /dev/null || true
+ done
+ wait
+}
+
+trap "stop_running" EXIT
+
+CURRENCY="EUR"
+IBAN_EXCHANGE="EX00000000000000000000"
+IBAN_MERCHANT="ME00000000000000000001"
+IBAN_CUSTOMER="WA00000000000000000000"
+FRONTENDS_APITOKEN="secret"
+WIRE_METHOD="sepa"
+NEXUS_DB_FILESYSTEM="/tmp/nexus.sqlite"
+SANDBOX_DB_FILESYSTEM="/tmp/sandbox.sqlite"
+SANDBOX_ADMIN_PASSWORD="secret"
+REV_PROXY="http://localhost:8080"
+SANDBOX_URL="${REV_PROXY}/sandbox"
+NEXUS_URL="${REV_PROXY}/nexus"
+EBICS_HOST="ebicsDeployedHost"
+# Only the exchange needs Nexus.
+EXCHANGE_NEXUS_USERNAME=exchange-nexus-user
+EXCHANGE_NEXUS_PASSWORD=exchange-nexus-password
+# Needed to create the default instance
+TALER_MERCHANT_TOKEN="secret"
+
+function generate_preliminary_config() {
+ # Known later:
+
+ # exchange pub, needed by merchant
+ # wire gateway URL, credentials, method
+
+ mkdir -p "$HOME/.config"
+ taler-config-local \
+ --currency "$CURRENCY" \
+ --outdir "$HOME/.config" \
+ --exchange-wire-address $IBAN_EXCHANGE \
+ --frontends-apitoken "$TALER_ENV_FRONTENDS_APITOKEN"
+}
+
+echo -n "Reset and init exchange DB.."
+taler-exchange-dbinit --reset
+echo " OK"
+
+echo -n "Remove previous key and data files.."
+rm -fr ~/.taler-data/*
+echo " OK"
+
+##
+## Step 3: Set up the exchange key material
+##
+
+echo -n "Setup exchange's key material.."
+
+# New version
+EXCHANGE_PID=$(taler-exchange > /tmp/exchange.log 2>&1 & echo $!)
+SECMOD_RSA_PID=$(taler-exchange-secmod-rsa > /tmp/exchange-secmod-rsa.log 2>&1 & echo $!)
+SECMOD_EDDSA_PID=$(taler-exchange-secmod-eddsa > /tmp/exchange-secmod-eddsa.log 2>&1 & echo $!)
+
+# FIXME: check the three services above are running correctly.
+
+taler-exchange-offline download sign upload
+
+PAYTO_URI=$(taler-config -s exchange-account-1 -o payto_uri)
+taler-exchange-offline enable-account "$PAYTO_URI" upload
+
+# Set up wire fees for next 5 years
+YEAR=$(date +%Y)
+for y in $(seq $year $((year + 5))); do
+ taler-exchange-offline wire-fee $y $WIRE_METHOD "$CURRENCY:0.01" "$CURRENCY:0.01" upload
+done
+
+echo " OK"
+echo -n "Getting exchange public key via /keys.."
+EXCHANGE_URL=$(taler-config -s exchange -o base_url)
+EXCHANGE_MASTER_PUB=$(curl -s "$EXCHANGE_URL/keys" | jq .master_public_key)
+echo " OK"
+echo -n "Add this exchange to the auditor..."
+taler-auditor-exchange \
+ -m "$EXCHANGE_MASTER_PUB" \
+ -u "$(taler-config -s exchange -o base_url)" || true
+# Make configuration accessible to auditor
+chmod 750 "$HOME/.config"
+echo " OK"
+stop_running
+
+##
+## Step 4: Set up euFin
+##
+
+echo -n "Resetting euFin databases.."
+rm $SANDBOX_DB_FILESYSTEM
+rm $NEXUS_DB_FILESYSTEM
+echo " OK"
+export LIBEUFIN_SANDBOX_USERNAME="admin"
+export LIBEUFIN_SANDBOX_PASSWORD=$SANDBOX_ADMIN_PASSWORD
+# $1 = ebics user id, $2 = ebics partner, $3 = bank connection name
+# $4 = bank account name local to Nexus, $5 = bank account name as known
+# by Sandbox
+function prepare_nexus_account() {
+ echo -n "Making bank connection $3 ..."
+ libeufin-cli connections new-ebics-connection \
+ --ebics-url="${SANDBOX_URL}ebicsweb" \
+ --host-id=$EBICS_HOST \
+ --partner-id=$2 \
+ --ebics-user-id=$1 \
+ $3 > /dev/null
+ echo " OK"
+ echo -n "Connecting $3 ..."
+ libeufin-cli connections connect $3 > /dev/null
+ echo " OK"
+ echo -n "Importing Sandbox bank account ($5) to Nexus ($4) ..."
+ libeufin-cli connections download-bank-accounts $3 > /dev/null
+ libeufin-cli connections import-bank-account \
+ --offered-account-id=$5 --nexus-bank-account-id=$4 $3 > /dev/null
+ echo " OK"
+ # Set how often the automatic routing must fetch the bank account.
+ echo -n "Setting background payment initiator.."
+ libeufin-cli accounts task-schedule $4 \
+ --task-type="submit" \
+ --task-name='submit-payments-every-second' \
+ --task-cronspec='* * *'
+ echo " OK"
+ echo -n "Setting background history fetch.."
+ libeufin-cli accounts task-schedule $4 \
+ --task-type="fetch" \
+ --task-name='fetch-reports-every-second' \
+ --task-cronspec='* * *' \
+ --task-param-level=report \
+ --task-param-range-type=latest
+ echo " OK"
+}
+
+# $1=ebics username, $2=ebics partner name,
+# $3=person name, $4=sandbox bank account name, $5=iban
+function prepare_sandbox_account() {
+ echo -n "Activating ebics subscriber $1 at the sandbox ..."
+ libeufin-cli \
+ sandbox --sandbox-url=$SANDBOX_URL \
+ ebicssubscriber create \
+ --host-id=$EBICS_HOST \
+ --partner-id=$2 \
+ --user-id=$1
+ echo " OK"
+ echo -n "Giving a bank account ($4) to $1 ..."
+ libeufin-cli \
+ sandbox --sandbox-url=$SANDBOX_URL \
+ ebicsbankaccount create \
+ --iban=$5 \
+ --bic="BCMAESM1XXX"\
+ --person-name="$3" \
+ --account-name=$4 \
+ --ebics-user-id=$1 \
+ --ebics-host-id=$EBICS_HOST \
+ --ebics-partner-id=$2 \
+ --currency=$CURRENCY
+ echo " OK"
+}
+
+echo -n "Making Sandbox superuser..."
+libeufin-sandbox superuser admin --password=${SANDBOX_ADMIN_PASSWORD}
+echo " OK"
+
+echo -n "Lunching Sandbox..."
+SANDBOX_PID=$(libeufin-sandbox serve --with-unix-socket > /tmp/sandbox.log 2>&1 & echo $!)
+if ! curl -s --retry 5 --retry-connrefused $SANDBOX_URL > /dev/null; then
+ echo "Could not launch Sandbox"
+ stop_running
+ exit 1
+fi
+echo " OK"
+
+echo -n "Launching Nexus..."
+NEXUS_PID=$(libeufin-nexus serve --with-unix-socket > /tmp/nexus.log 2>&1 & echo $!)
+if ! curl -s --retry 5 --retry-connrefused $NEXUS_URL > /dev/null; then
+ echo "Could not launch Nexus"
+ stop_running
+ exit 1
+fi
+echo " OK"
+
+echo -n "Make Sandbox EBICS host..."
+libeufin-cli \
+ sandbox --sandbox-url=$SANDBOX_URL \
+ ebicshost create \
+ --host-id=$EBICS_HOST
+echo " OK"
+
+# note: Ebisc schema doesn't allow dashed names.
+prepare_sandbox_account \
+ ebicsuserExchange \
+ ebicspartnerExchange \
+ "Person Exchange" \
+ sandbox-account-exchange \
+ $IBAN_EXCHANGE
+prepare_sandbox_account \
+ ebicsuserMerchant \
+ ebicspartnerMerchant \
+ "Person Merchant" \
+ sandbox-account-merchant \
+ $IBAN_MERCHANT
+prepare_sandbox_account \
+ ebicsuserCustomer \
+ ebicspartnerCustomer \
+ "Person Customer" \
+ sandbox-account-customer \
+ $IBAN_CUSTOMER
+
+echo -n "Make Nexus superuser ..."
+libeufin-nexus superuser $EXCHANGE_NEXUS_USERNAME --password=$EXCHANGE_NEXUS_PASSWORD
+echo " OK"
+
+export LIBEUFIN_NEXUS_URL=$NEXUS_URL
+export LIBEUFIN_NEXUS_USERNAME=$EXCHANGE_NEXUS_USERNAME
+export LIBEUFIN_NEXUS_PASSWORD=$EXCHANGE_NEXUS_PASSWORD
+prepare_nexus_account \
+ ebicsuserExchange \
+ ebicspartnerExchange \
+ bankconnection-exchange \
+ nexus-bankaccount-exchange \
+ sandbox-account-exchange
+
+echo -n "Create Taler facade ..."
+libeufin-cli facades new-taler-wire-gateway-facade \
+ --currency=$CURRENCY \
+ --facade-name=facade-exchange \
+ bankconnection-exchange nexus-bankaccount-exchange
+echo " OK"
+FACADE_URL=$(libeufin-cli facades list | jq .facades[0].baseUrl | tr -d \")
+
+stop_running
+
+# Finish configuration now:
+taler-config -s merchant-exchange-$CURRENCY \
+ -o master_key -V $EXCHANGE_MASTER_PUB
+
+# Point the exchange to the facade.
+taler-config -s exchange-accountcredentials-1 \
+ -o WIRE_GATEWAY_URL \
+ -V "${FACADE_URL}"
+
+taler-config -s exchange-accountcredentials-1 \
+ -o USERNAME \
+ -V "${EXCHANGE_NEXUS_USERNAME}"
+
+taler-config -s exchange-accountcredentials-1 \
+ -o PASSWORD \
+ -V "${EXCHANGE_NEXUS_PASSWORD}"
+##
+## Step 6: Set up merchant
+##
+
+echo -n "Reset and init merchant database.."
+taler-merchant-dbinit --reset
+echo " OK"
+
+echo "Configuring instances"
+# Obsoleted: do all here.
+# taler-deployment-config-instances-iban
+export TALER_MERCHANT_TOKEN
+MERCHANT_BACKEND_PID=$(taler-merchant-httpd > /tmp/merchant.log 2>&1 & echo $!)
+
+# Create default instance
+# Create one instance
+
+
+
+
+
+echo "Stopping all the services"
+stop_running