#!/usr/bin/env python3 """ This script makes sure that the merchant backend instances used by the test/demo environment are created. We assume that the merchant backend is running, and that the "~/activate" file has been sourced to provide the right environment variables. """ import requests from os import environ, system from sys import exit from urllib.parse import urljoin from subprocess import Popen from time import sleep import psutil from getpass import getuser ibans = dict( default = "ME00000000000000000000", # Must match the IBAN given in the prepare script, called IBAN_MERCHANT. blog = "ME00000000000000000001", ) def expect_env(name): val = environ.get(name) if not val: print(f"{name} not defined. Please source the ~/activate file.") exit(1) return val def wait_merchant_up(): # Check it started correctly and it is ready to serve requests. checks = 10 url = urljoin(MERCHANT_BACKEND_BASE_URL, "/config") while checks > 0: try: resp = requests.get(url, timeout=5) except Exception: print("Merchant unreachable") sleep(1) checks -= 1 continue if resp.status_code != 200: sleep(1) checks -= 1 continue # Ready. return True print("Merchant is not correctly serving requests.") return False MERCHANT_BACKEND_BASE_URL = expect_env("TALER_ENV_MERCHANT_BACKEND") TALER_ENV_NAME = expect_env("TALER_ENV_NAME") TALER_CONFIG_CURRENCY = expect_env("TALER_CONFIG_CURRENCY") TALER_ENV_FRONTENDS_APITOKEN = expect_env("TALER_ENV_FRONTENDS_APITOKEN") authorization_header = {"Authorization": f"Bearer {TALER_ENV_FRONTENDS_APITOKEN}"} def ensure_instance(instance_id, name, payto_uris, auth): resp = requests.get( urljoin(MERCHANT_BACKEND_BASE_URL, f"management/instances/{instance_id}"), headers = authorization_header ) req = dict( id=instance_id, name=name, payto_uris=payto_uris, address=dict(), jurisdiction=dict(), default_max_wire_fee=f"{TALER_CONFIG_CURRENCY}:1", default_wire_fee_amortization=3, default_max_deposit_fee=f"{TALER_CONFIG_CURRENCY}:1", default_wire_transfer_delay=dict(d_ms="forever"), default_pay_delay=dict(d_ms="forever"), auth=auth, ) http_method = requests.post endpoint = "management/instances" # Instance exists, patching it. if resp.status_code == 200: if instance_id != "Tutorial": print(f"Patching instance '{instance_id}'") http_method = requests.patch endpoint = f"management/instances/{instance_id}" resp = http_method( urljoin(MERCHANT_BACKEND_BASE_URL, endpoint), json=req, headers = authorization_header ) if resp.status_code < 200 or resp.status_code >= 300: print(f"Could not create (or patch) instance '{instance_id}', backend responds: {resp.status_code}/{resp.text}") exit(1) def is_merchant_running(): for proc in psutil.process_iter(): if proc.name() == "taler-merchant-httpd" and proc.username() == getuser(): return True return False def ensure_default_instance(): # Assumed is managed by ARM merchant_was_running = is_merchant_running() if merchant_was_running: print("Found running merchant, assuming is managed by ARM. Terminating it") system("taler-deployment-arm -k taler-merchant") checks = 10 while checks > 0: if is_merchant_running(): sleep(1) checks -= 1 continue break if checks == 0: print("Could not stop the running merchant.") exit(1) # ARM is _not_ running the merchant at this point. env_with_token = environ.copy() env_with_token["TALER_MERCHANT_TOKEN"] = TALER_ENV_FRONTENDS_APITOKEN print("Starting the merchant outside ARM to pass the token into the environment.") # Start the merchant natively. merchant = Popen(["taler-merchant-httpd"], env=env_with_token) if not wait_merchant_up(): merchant.terminate() merchant.wait() exit(1) print("Merchant started successfully, creating the default instance now.") ensure_instance( "default", "default", payto_uris=[f"payto://sepa/bank.{TALER_ENV_NAME}.taler.net/{ibans.get('default')}"], auth=dict(method="token", token=TALER_ENV_FRONTENDS_APITOKEN) ) # Native process can be terminated now. merchant.terminate() merchant.wait() ensure_default_instance() print("Restarting merchant _with_ ARM, to create other non-default instances.") system("taler-deployment-arm -s") system("taler-deployment-arm -i taler-merchant") wait_merchant_up() ensure_instance( "blog", name="Blog", payto_uris=[f"payto://sepa/bank.{TALER_ENV_NAME}.taler.net/{ibans.get('blog')}"], auth=dict(method="token", token=TALER_ENV_FRONTENDS_APITOKEN), ) print("Stopping the ARM merchant") system("taler-deployment-arm -k taler-merchant") # NOTE: ARM itself will be stopped by the main prepare script. # Stopping here will result in indefinite wait at the caller.